blob: 9e4fb0c1e52b6ec7b97dc8335fb3b4335477b796 [file] [log] [blame]
Zack Williams41513bf2018-07-07 20:08:35 -07001/*
2 * Copyright 2017-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Stephane Barbarie35595062018-02-08 08:34:39 -050016package nbi
17
18import (
19 "context"
20 "crypto/tls"
21 "errors"
22 "github.com/golang/protobuf/ptypes/empty"
23 "github.com/google/gopacket"
24 "github.com/google/gopacket/layers"
25 "github.com/opencord/voltha/ponsim/v2/common"
26 "github.com/opencord/voltha/ponsim/v2/core"
27 "github.com/opencord/voltha/protos/go/voltha"
28 "github.com/sirupsen/logrus"
29 "google.golang.org/grpc"
30 "google.golang.org/grpc/credentials"
31 "strconv"
32 "strings"
33)
34
35// TODO: Cleanup GRPC security config
36// TODO: Pass-in the certificate information as a structure parameter
37
38type PonSimHandler struct {
39 device core.PonSimInterface
40}
41
42/*
43NewPonSimHandler instantiates a handler for a PonSim device
44*/
45func NewPonSimHandler(device core.PonSimInterface) *PonSimHandler {
46 var handler *PonSimHandler
47 handler = &PonSimHandler{device: device}
48 return handler
49}
50
51/*
52SendFrame handles and forwards EGRESS packets (i.e. VOLTHA to OLT)
53*/
54func (handler *PonSimHandler) SendFrame(ctx context.Context, data *voltha.PonSimFrame) (*empty.Empty, error) {
55 frame := gopacket.NewPacket(data.Payload, layers.LayerTypeEthernet, gopacket.Default)
56
57 common.Logger().WithFields(logrus.Fields{
58 "handler": handler,
59 "frame": frame.Dump(),
60 }).Info("Constructed frame")
61
62 handler.device.Forward(context.Background(), 2, frame)
63
64 out := new(empty.Empty)
65 return out, nil
66}
67
68/*
69ReceiveFrames handles a stream of INGRESS packets (i.e. OLT to VOLTHA)
70*/
71func (handler *PonSimHandler) ReceiveFrames(empty *empty.Empty, stream voltha.PonSim_ReceiveFramesServer) error {
72 common.Logger().WithFields(logrus.Fields{
73 "handler": handler,
74 }).Info("start-receiving-frames")
75
76 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
77 var data []byte
78 var ok bool
79
80 common.Logger().WithFields(logrus.Fields{
81 "handler": handler,
82 "device": (handler.device).(*core.PonSimOltDevice),
83 }).Info("receiving-frames-from-olt-device")
84
85 for {
86 select {
87 case data, ok = <-(handler.device).(*core.PonSimOltDevice).GetOutgoing():
88 if ok {
89 frame := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
90 common.Logger().WithFields(logrus.Fields{
91 "handler": handler,
92 "frame": frame,
93 }).Info("Received incoming data")
94
95 frameBytes := &voltha.PonSimFrame{Id: handler.device.GetAddress(), Payload: data}
96 if err := stream.Send(frameBytes); err != nil {
97 common.Logger().WithFields(logrus.Fields{
98 "handler": handler,
99 "frame": frame,
100 "error": err,
101 }).Error("Failed to send incoming data")
102 return err
103 }
104 common.Logger().WithFields(logrus.Fields{
105 "handler": handler,
106 "frame": frame,
107 }).Info("Sent incoming data")
108
109 } else {
110 return errors.New("incoming data channel has closed")
111 }
112 }
113 }
114
115 } else {
116 common.Logger().WithFields(logrus.Fields{
117 "handler": handler,
118 }).Error("Not handling an OLT device")
119 }
120
121 return nil
122}
123
124/*
125GetDeviceInfo returns information of a PonSim device (OLT or ONU)
126*/
127func (handler *PonSimHandler) GetDeviceInfo(
128 ctx context.Context,
129 empty *empty.Empty,
130) (*voltha.PonSimDeviceInfo, error) {
131 common.Logger().WithFields(logrus.Fields{
132 "handler": handler,
133 }).Info("Getting device information")
134
135 var out *voltha.PonSimDeviceInfo
136
137 // Check which device type we're currently handling
138 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
139 common.Logger().WithFields(logrus.Fields{
140 "handler": handler,
141 }).Debug("Handling OLT device")
142 keys := make([]int32, 0, len((handler.device).(*core.PonSimOltDevice).GetOnus()))
143 for k := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
144 keys = append(keys, k)
145 }
146 out = &voltha.PonSimDeviceInfo{NniPort: 0, UniPorts: []int32(keys)}
147
148 } else {
149 common.Logger().WithFields(logrus.Fields{
150 "handler": handler,
151 }).Debug("Handling ONU/OTHER device")
152
153 out = &voltha.PonSimDeviceInfo{}
154 }
155
156 common.Logger().WithFields(logrus.Fields{
157 "handler": handler,
158 "result": out,
159 }).Info("Device information")
160
161 return out, nil
162}
163
164/*
165UpdateFlowTable populates and cleans up the flows for a PonSim device
166*/
167func (handler *PonSimHandler) UpdateFlowTable(
168 ctx context.Context,
169 table *voltha.FlowTable,
170) (*empty.Empty, error) {
171 common.Logger().WithFields(logrus.Fields{
172 "handler": handler,
173 "table": table,
174 }).Info("Updating flows")
175
176 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
177 if table.Port == 0 {
178 common.Logger().WithFields(logrus.Fields{
179 "handler": handler,
180 "port": table.Port,
181 }).Debug("Updating OLT flows")
182
183 if err := (handler.device).(*core.PonSimOltDevice).InstallFlows(ctx, table.Flows); err != nil {
184 common.Logger().WithFields(logrus.Fields{
185 "handler": handler,
186 "error": err.Error(),
187 "flows": table.Flows,
188 }).Error("Problem updating flows on OLT")
189 } else {
190 common.Logger().WithFields(logrus.Fields{
191 "handler": handler,
192 }).Debug("Updated OLT flows")
193 }
194
195 } else {
196 common.Logger().WithFields(logrus.Fields{
197 "handler": handler,
198 "port": table.Port,
199 }).Debug("Updating ONU flows")
200
201 if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[table.Port]; ok {
202 // TODO: make it secure
203 ta := credentials.NewTLS(&tls.Config{
204 InsecureSkipVerify: true,
205 })
206
207 host := strings.Join([]string{
208 child.Device.Address,
209 strconv.Itoa(int(child.Device.Port)),
210 }, ":")
211
212 conn, err := grpc.Dial(
213 host,
214 grpc.WithTransportCredentials(ta),
215 )
216 if err != nil {
217 common.Logger().WithFields(logrus.Fields{
218 "handler": handler,
219 "error": err.Error(),
220 }).Error("GRPC Connection problem")
221 }
222 defer conn.Close()
223 client := voltha.NewPonSimClient(conn)
224
225 if _, err = client.UpdateFlowTable(ctx, table); err != nil {
226 common.Logger().WithFields(logrus.Fields{
227 "handler": handler,
228 "host": host,
229 "error": err.Error(),
230 }).Error("Problem forwarding update request to ONU")
231 }
232 } else {
233 common.Logger().WithFields(logrus.Fields{
234 "handler": handler,
235 "port": table.Port,
236 }).Warn("Unable to find ONU")
237 }
238
239 }
240 } else if _, ok := (handler.device).(*core.PonSimOnuDevice); ok {
241 if err := (handler.device).(*core.PonSimOnuDevice).InstallFlows(ctx, table.Flows); err != nil {
242 common.Logger().WithFields(logrus.Fields{
243 "handler": handler,
244 "error": err.Error(),
245 "flows": table.Flows,
246 }).Error("Problem updating flows on ONU")
247 } else {
248 common.Logger().WithFields(logrus.Fields{
249 "handler": handler,
250 }).Debug("Updated ONU flows")
251 }
252 } else {
253 common.Logger().WithFields(logrus.Fields{
254 "handler": handler,
255 "port": table.Port,
256 }).Warn("Unknown device")
257 }
258
259 common.Logger().WithFields(logrus.Fields{
260 "handler": handler,
261 "table": table,
262 }).Info("Updated flows")
263
264 out := new(empty.Empty)
265 return out, nil
266}
267
268/*
269GetStats retrieves statistics for a PonSim device
270*/
271func (handler *PonSimHandler) GetStats(
272 ctx context.Context,
273 empty *empty.Empty,
274) (*voltha.PonSimMetrics, error) {
275 common.Logger().WithFields(logrus.Fields{
276 "handler": handler,
277 }).Info("Retrieving stats")
278
279 var metrics *voltha.PonSimMetrics = new(voltha.PonSimMetrics)
280
281 if olt, ok := (handler.device).(*core.PonSimOltDevice); ok {
282 common.Logger().WithFields(logrus.Fields{
283 "handler": handler,
284 "olt": olt,
285 }).Debug("Retrieving stats for OLT")
286
287 // Get stats for current device
288
289 // Loop through each onus to get stats from those as well?
290 // send grpc request to each onu
291 for _, child := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
292 // TODO: make it secure
293 ta := credentials.NewTLS(&tls.Config{
294 InsecureSkipVerify: true,
295 })
296
297 host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
298 conn, err := grpc.Dial(
299 host,
300 grpc.WithTransportCredentials(ta),
301 )
302 if err != nil {
303 common.Logger().WithFields(logrus.Fields{
304 "handler": handler,
305 "error": err.Error(),
306 }).Error("GRPC Connection problem")
307 }
308 defer conn.Close()
309 client := voltha.NewPonSimClient(conn)
310
311 if _, err = client.GetStats(ctx, empty); err != nil {
312 common.Logger().WithFields(logrus.Fields{
313 "handler": handler,
314 "host": host,
315 "error": err.Error(),
316 }).Error("Problem forwarding stats request to ONU")
317 }
318 }
319 metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
320
321 common.Logger().WithFields(logrus.Fields{
322 "handler": handler,
323 "metrics": metrics,
324 }).Debug("OLT Metrics")
325
326 } else if onu, ok := (handler.device).(*core.PonSimOnuDevice); ok {
327 common.Logger().WithFields(logrus.Fields{
328 "handler": handler,
329 "onu": onu,
330 }).Debug("Retrieving stats for ONU")
331 } else {
332 common.Logger().WithFields(logrus.Fields{
333 "handler": handler,
334 }).Warn("Unknown device")
335 }
336
337 common.Logger().WithFields(logrus.Fields{
338 "handler": handler,
339 }).Info("Retrieved stats")
340
341 return metrics, nil
342}