blob: df73a346f0497e8dea73f224f1a830f456a17fe6 [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"
Stephane Barbarie35595062018-02-08 08:34:39 -050020 "errors"
Jeff70e8b2d2018-07-24 13:37:29 -070021 "strconv"
22 "strings"
23
Stephane Barbarie35595062018-02-08 08:34:39 -050024 "github.com/golang/protobuf/ptypes/empty"
25 "github.com/google/gopacket"
26 "github.com/google/gopacket/layers"
27 "github.com/opencord/voltha/ponsim/v2/common"
28 "github.com/opencord/voltha/ponsim/v2/core"
29 "github.com/opencord/voltha/protos/go/voltha"
30 "github.com/sirupsen/logrus"
31 "google.golang.org/grpc"
Stephane Barbarie35595062018-02-08 08:34:39 -050032)
33
Stephane Barbarie35595062018-02-08 08:34:39 -050034type PonSimHandler struct {
35 device core.PonSimInterface
36}
37
38/*
39NewPonSimHandler instantiates a handler for a PonSim device
40*/
41func NewPonSimHandler(device core.PonSimInterface) *PonSimHandler {
42 var handler *PonSimHandler
43 handler = &PonSimHandler{device: device}
44 return handler
45}
46
47/*
48SendFrame handles and forwards EGRESS packets (i.e. VOLTHA to OLT)
49*/
50func (handler *PonSimHandler) SendFrame(ctx context.Context, data *voltha.PonSimFrame) (*empty.Empty, error) {
51 frame := gopacket.NewPacket(data.Payload, layers.LayerTypeEthernet, gopacket.Default)
52
53 common.Logger().WithFields(logrus.Fields{
54 "handler": handler,
Jonathan Hart32fe8812018-08-21 17:10:12 -070055 "out_port": int(data.OutPort),
Stephane Barbarie35595062018-02-08 08:34:39 -050056 "frame": frame.Dump(),
57 }).Info("Constructed frame")
58
Jonathan Hart32fe8812018-08-21 17:10:12 -070059 handler.device.SendOut(int(data.OutPort), frame)
Stephane Barbarie35595062018-02-08 08:34:39 -050060
61 out := new(empty.Empty)
62 return out, nil
63}
64
65/*
66ReceiveFrames handles a stream of INGRESS packets (i.e. OLT to VOLTHA)
67*/
68func (handler *PonSimHandler) ReceiveFrames(empty *empty.Empty, stream voltha.PonSim_ReceiveFramesServer) error {
69 common.Logger().WithFields(logrus.Fields{
70 "handler": handler,
71 }).Info("start-receiving-frames")
72
73 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
74 var data []byte
75 var ok bool
76
77 common.Logger().WithFields(logrus.Fields{
78 "handler": handler,
79 "device": (handler.device).(*core.PonSimOltDevice),
80 }).Info("receiving-frames-from-olt-device")
81
82 for {
83 select {
84 case data, ok = <-(handler.device).(*core.PonSimOltDevice).GetOutgoing():
85 if ok {
86 frame := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
87 common.Logger().WithFields(logrus.Fields{
88 "handler": handler,
89 "frame": frame,
90 }).Info("Received incoming data")
91
92 frameBytes := &voltha.PonSimFrame{Id: handler.device.GetAddress(), Payload: data}
93 if err := stream.Send(frameBytes); err != nil {
94 common.Logger().WithFields(logrus.Fields{
95 "handler": handler,
96 "frame": frame,
97 "error": err,
98 }).Error("Failed to send incoming data")
99 return err
100 }
101 common.Logger().WithFields(logrus.Fields{
102 "handler": handler,
103 "frame": frame,
104 }).Info("Sent incoming data")
105
106 } else {
107 return errors.New("incoming data channel has closed")
108 }
109 }
110 }
111
112 } else {
113 common.Logger().WithFields(logrus.Fields{
114 "handler": handler,
115 }).Error("Not handling an OLT device")
116 }
117
118 return nil
119}
120
121/*
122GetDeviceInfo returns information of a PonSim device (OLT or ONU)
123*/
124func (handler *PonSimHandler) GetDeviceInfo(
125 ctx context.Context,
126 empty *empty.Empty,
127) (*voltha.PonSimDeviceInfo, error) {
128 common.Logger().WithFields(logrus.Fields{
129 "handler": handler,
130 }).Info("Getting device information")
131
Andy Bavierea82b462018-07-27 16:48:13 -0700132 out := &voltha.PonSimDeviceInfo{}
Stephane Barbarie35595062018-02-08 08:34:39 -0500133
134 // Check which device type we're currently handling
135 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
136 common.Logger().WithFields(logrus.Fields{
137 "handler": handler,
138 }).Debug("Handling OLT device")
Andy Bavierea82b462018-07-27 16:48:13 -0700139 onus := (handler.device).(*core.PonSimOltDevice).GetOnus()
140 for k := range onus {
141 out.Onus = append(
142 out.Onus,
143 &voltha.PonSimOnuDeviceInfo {
144 UniPort: k,
145 SerialNumber: onus[k].Device.SerialNumber,
146 },
147 )
Stephane Barbarie35595062018-02-08 08:34:39 -0500148 }
Jonathan Hart32fe8812018-08-21 17:10:12 -0700149 out.NniPort = 2
Stephane Barbarie35595062018-02-08 08:34:39 -0500150 } else {
151 common.Logger().WithFields(logrus.Fields{
152 "handler": handler,
153 }).Debug("Handling ONU/OTHER device")
Stephane Barbarie35595062018-02-08 08:34:39 -0500154 }
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 {
Stephane Barbarie35595062018-02-08 08:34:39 -0500202
203 host := strings.Join([]string{
204 child.Device.Address,
205 strconv.Itoa(int(child.Device.Port)),
206 }, ":")
207
208 conn, err := grpc.Dial(
209 host,
Jeff70e8b2d2018-07-24 13:37:29 -0700210 grpc.WithInsecure(),
Stephane Barbarie35595062018-02-08 08:34:39 -0500211 )
212 if err != nil {
213 common.Logger().WithFields(logrus.Fields{
214 "handler": handler,
215 "error": err.Error(),
216 }).Error("GRPC Connection problem")
217 }
218 defer conn.Close()
219 client := voltha.NewPonSimClient(conn)
220
221 if _, err = client.UpdateFlowTable(ctx, table); err != nil {
222 common.Logger().WithFields(logrus.Fields{
223 "handler": handler,
224 "host": host,
225 "error": err.Error(),
226 }).Error("Problem forwarding update request to ONU")
227 }
228 } else {
229 common.Logger().WithFields(logrus.Fields{
230 "handler": handler,
231 "port": table.Port,
232 }).Warn("Unable to find ONU")
233 }
234
235 }
236 } else if _, ok := (handler.device).(*core.PonSimOnuDevice); ok {
237 if err := (handler.device).(*core.PonSimOnuDevice).InstallFlows(ctx, table.Flows); err != nil {
238 common.Logger().WithFields(logrus.Fields{
239 "handler": handler,
240 "error": err.Error(),
241 "flows": table.Flows,
242 }).Error("Problem updating flows on ONU")
243 } else {
244 common.Logger().WithFields(logrus.Fields{
245 "handler": handler,
246 }).Debug("Updated ONU flows")
247 }
248 } else {
249 common.Logger().WithFields(logrus.Fields{
250 "handler": handler,
251 "port": table.Port,
252 }).Warn("Unknown device")
253 }
254
255 common.Logger().WithFields(logrus.Fields{
256 "handler": handler,
257 "table": table,
258 }).Info("Updated flows")
259
260 out := new(empty.Empty)
261 return out, nil
262}
263
264/*
265GetStats retrieves statistics for a PonSim device
266*/
267func (handler *PonSimHandler) GetStats(
268 ctx context.Context,
Scott Bakerb5be94d2018-10-09 16:13:32 -0700269 req *voltha.PonSimMetricsRequest,
Stephane Barbarie35595062018-02-08 08:34:39 -0500270) (*voltha.PonSimMetrics, error) {
271 common.Logger().WithFields(logrus.Fields{
272 "handler": handler,
273 }).Info("Retrieving stats")
274
275 var metrics *voltha.PonSimMetrics = new(voltha.PonSimMetrics)
276
277 if olt, ok := (handler.device).(*core.PonSimOltDevice); ok {
278 common.Logger().WithFields(logrus.Fields{
279 "handler": handler,
280 "olt": olt,
281 }).Debug("Retrieving stats for OLT")
282
Scott Bakerb5be94d2018-10-09 16:13:32 -0700283 if req.Port == 0 {
284 // port == 0, return the OLT statistics
285 metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
286 } else {
287 common.Logger().WithFields(logrus.Fields{
288 "handler": handler,
289 "port": req.Port,
290 }).Debug("Request is for ONU")
Stephane Barbarie35595062018-02-08 08:34:39 -0500291
Scott Bakerb5be94d2018-10-09 16:13:32 -0700292 // port != 0, contact the ONU, retrieve onu statistics, and return to the caller
293 if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[req.Port]; ok {
294 host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
295 conn, err := grpc.Dial(
296 host,
297 grpc.WithInsecure(),
298 )
299 if err != nil {
300 common.Logger().WithFields(logrus.Fields{
301 "handler": handler,
302 "error": err.Error(),
303 }).Error("GRPC Connection problem")
304 }
305 defer conn.Close()
306 client := voltha.NewPonSimClient(conn)
Stephane Barbarie35595062018-02-08 08:34:39 -0500307
Scott Bakerb5be94d2018-10-09 16:13:32 -0700308 if onu_stats, err := client.GetStats(ctx, req); err != nil {
309 common.Logger().WithFields(logrus.Fields{
310 "handler": handler,
311 "host": host,
312 "error": err.Error(),
313 }).Error("Problem forwarding stats request to ONU")
314 } else {
315 metrics = onu_stats
316 }
317 } else {
Stephane Barbarie35595062018-02-08 08:34:39 -0500318 common.Logger().WithFields(logrus.Fields{
319 "handler": handler,
Scott Bakerb5be94d2018-10-09 16:13:32 -0700320 "port": req.Port,
321 }).Warn("Unable to find ONU")
Stephane Barbarie35595062018-02-08 08:34:39 -0500322 }
323 }
Stephane Barbarie35595062018-02-08 08:34:39 -0500324
325 common.Logger().WithFields(logrus.Fields{
326 "handler": handler,
327 "metrics": metrics,
328 }).Debug("OLT Metrics")
329
330 } else if onu, ok := (handler.device).(*core.PonSimOnuDevice); ok {
331 common.Logger().WithFields(logrus.Fields{
332 "handler": handler,
333 "onu": onu,
334 }).Debug("Retrieving stats for ONU")
Scott Bakerb5be94d2018-10-09 16:13:32 -0700335 metrics = (handler.device).(*core.PonSimOnuDevice).Counter.MakeProto()
336 common.Logger().WithFields(logrus.Fields{
337 "handler": handler,
338 "metrics": metrics,
339 }).Debug("ONU Metrics")
Stephane Barbarie35595062018-02-08 08:34:39 -0500340 } else {
341 common.Logger().WithFields(logrus.Fields{
342 "handler": handler,
343 }).Warn("Unknown device")
344 }
345
346 common.Logger().WithFields(logrus.Fields{
347 "handler": handler,
348 }).Info("Retrieved stats")
349
350 return metrics, nil
351}