blob: 49fd71aec086d7830233fb58b1234e20e96b897b [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,
55 "frame": frame.Dump(),
56 }).Info("Constructed frame")
57
58 handler.device.Forward(context.Background(), 2, frame)
59
60 out := new(empty.Empty)
61 return out, nil
62}
63
64/*
65ReceiveFrames handles a stream of INGRESS packets (i.e. OLT to VOLTHA)
66*/
67func (handler *PonSimHandler) ReceiveFrames(empty *empty.Empty, stream voltha.PonSim_ReceiveFramesServer) error {
68 common.Logger().WithFields(logrus.Fields{
69 "handler": handler,
70 }).Info("start-receiving-frames")
71
72 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
73 var data []byte
74 var ok bool
75
76 common.Logger().WithFields(logrus.Fields{
77 "handler": handler,
78 "device": (handler.device).(*core.PonSimOltDevice),
79 }).Info("receiving-frames-from-olt-device")
80
81 for {
82 select {
83 case data, ok = <-(handler.device).(*core.PonSimOltDevice).GetOutgoing():
84 if ok {
85 frame := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)
86 common.Logger().WithFields(logrus.Fields{
87 "handler": handler,
88 "frame": frame,
89 }).Info("Received incoming data")
90
91 frameBytes := &voltha.PonSimFrame{Id: handler.device.GetAddress(), Payload: data}
92 if err := stream.Send(frameBytes); err != nil {
93 common.Logger().WithFields(logrus.Fields{
94 "handler": handler,
95 "frame": frame,
96 "error": err,
97 }).Error("Failed to send incoming data")
98 return err
99 }
100 common.Logger().WithFields(logrus.Fields{
101 "handler": handler,
102 "frame": frame,
103 }).Info("Sent incoming data")
104
105 } else {
106 return errors.New("incoming data channel has closed")
107 }
108 }
109 }
110
111 } else {
112 common.Logger().WithFields(logrus.Fields{
113 "handler": handler,
114 }).Error("Not handling an OLT device")
115 }
116
117 return nil
118}
119
120/*
121GetDeviceInfo returns information of a PonSim device (OLT or ONU)
122*/
123func (handler *PonSimHandler) GetDeviceInfo(
124 ctx context.Context,
125 empty *empty.Empty,
126) (*voltha.PonSimDeviceInfo, error) {
127 common.Logger().WithFields(logrus.Fields{
128 "handler": handler,
129 }).Info("Getting device information")
130
Andy Bavierea82b462018-07-27 16:48:13 -0700131 out := &voltha.PonSimDeviceInfo{}
Stephane Barbarie35595062018-02-08 08:34:39 -0500132
133 // Check which device type we're currently handling
134 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
135 common.Logger().WithFields(logrus.Fields{
136 "handler": handler,
137 }).Debug("Handling OLT device")
Andy Bavierea82b462018-07-27 16:48:13 -0700138 onus := (handler.device).(*core.PonSimOltDevice).GetOnus()
139 for k := range onus {
140 out.Onus = append(
141 out.Onus,
142 &voltha.PonSimOnuDeviceInfo {
143 UniPort: k,
144 SerialNumber: onus[k].Device.SerialNumber,
145 },
146 )
Stephane Barbarie35595062018-02-08 08:34:39 -0500147 }
Andy Bavierea82b462018-07-27 16:48:13 -0700148 out.NniPort = 0
Stephane Barbarie35595062018-02-08 08:34:39 -0500149 } else {
150 common.Logger().WithFields(logrus.Fields{
151 "handler": handler,
152 }).Debug("Handling ONU/OTHER device")
Stephane Barbarie35595062018-02-08 08:34:39 -0500153 }
154
155 common.Logger().WithFields(logrus.Fields{
156 "handler": handler,
157 "result": out,
158 }).Info("Device information")
159
160 return out, nil
161}
162
163/*
164UpdateFlowTable populates and cleans up the flows for a PonSim device
165*/
166func (handler *PonSimHandler) UpdateFlowTable(
167 ctx context.Context,
168 table *voltha.FlowTable,
169) (*empty.Empty, error) {
170 common.Logger().WithFields(logrus.Fields{
171 "handler": handler,
172 "table": table,
173 }).Info("Updating flows")
174
175 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
176 if table.Port == 0 {
177 common.Logger().WithFields(logrus.Fields{
178 "handler": handler,
179 "port": table.Port,
180 }).Debug("Updating OLT flows")
181
182 if err := (handler.device).(*core.PonSimOltDevice).InstallFlows(ctx, table.Flows); err != nil {
183 common.Logger().WithFields(logrus.Fields{
184 "handler": handler,
185 "error": err.Error(),
186 "flows": table.Flows,
187 }).Error("Problem updating flows on OLT")
188 } else {
189 common.Logger().WithFields(logrus.Fields{
190 "handler": handler,
191 }).Debug("Updated OLT flows")
192 }
193
194 } else {
195 common.Logger().WithFields(logrus.Fields{
196 "handler": handler,
197 "port": table.Port,
198 }).Debug("Updating ONU flows")
199
200 if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[table.Port]; ok {
Stephane Barbarie35595062018-02-08 08:34:39 -0500201
202 host := strings.Join([]string{
203 child.Device.Address,
204 strconv.Itoa(int(child.Device.Port)),
205 }, ":")
206
207 conn, err := grpc.Dial(
208 host,
Jeff70e8b2d2018-07-24 13:37:29 -0700209 grpc.WithInsecure(),
Stephane Barbarie35595062018-02-08 08:34:39 -0500210 )
211 if err != nil {
212 common.Logger().WithFields(logrus.Fields{
213 "handler": handler,
214 "error": err.Error(),
215 }).Error("GRPC Connection problem")
216 }
217 defer conn.Close()
218 client := voltha.NewPonSimClient(conn)
219
220 if _, err = client.UpdateFlowTable(ctx, table); err != nil {
221 common.Logger().WithFields(logrus.Fields{
222 "handler": handler,
223 "host": host,
224 "error": err.Error(),
225 }).Error("Problem forwarding update request to ONU")
226 }
227 } else {
228 common.Logger().WithFields(logrus.Fields{
229 "handler": handler,
230 "port": table.Port,
231 }).Warn("Unable to find ONU")
232 }
233
234 }
235 } else if _, ok := (handler.device).(*core.PonSimOnuDevice); ok {
236 if err := (handler.device).(*core.PonSimOnuDevice).InstallFlows(ctx, table.Flows); err != nil {
237 common.Logger().WithFields(logrus.Fields{
238 "handler": handler,
239 "error": err.Error(),
240 "flows": table.Flows,
241 }).Error("Problem updating flows on ONU")
242 } else {
243 common.Logger().WithFields(logrus.Fields{
244 "handler": handler,
245 }).Debug("Updated ONU flows")
246 }
247 } else {
248 common.Logger().WithFields(logrus.Fields{
249 "handler": handler,
250 "port": table.Port,
251 }).Warn("Unknown device")
252 }
253
254 common.Logger().WithFields(logrus.Fields{
255 "handler": handler,
256 "table": table,
257 }).Info("Updated flows")
258
259 out := new(empty.Empty)
260 return out, nil
261}
262
263/*
264GetStats retrieves statistics for a PonSim device
265*/
266func (handler *PonSimHandler) GetStats(
267 ctx context.Context,
268 empty *empty.Empty,
269) (*voltha.PonSimMetrics, error) {
270 common.Logger().WithFields(logrus.Fields{
271 "handler": handler,
272 }).Info("Retrieving stats")
273
274 var metrics *voltha.PonSimMetrics = new(voltha.PonSimMetrics)
275
276 if olt, ok := (handler.device).(*core.PonSimOltDevice); ok {
277 common.Logger().WithFields(logrus.Fields{
278 "handler": handler,
279 "olt": olt,
280 }).Debug("Retrieving stats for OLT")
281
282 // Get stats for current device
283
284 // Loop through each onus to get stats from those as well?
285 // send grpc request to each onu
286 for _, child := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
Stephane Barbarie35595062018-02-08 08:34:39 -0500287
288 host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
289 conn, err := grpc.Dial(
290 host,
Jeff70e8b2d2018-07-24 13:37:29 -0700291 grpc.WithInsecure(),
Stephane Barbarie35595062018-02-08 08:34:39 -0500292 )
293 if err != nil {
294 common.Logger().WithFields(logrus.Fields{
295 "handler": handler,
296 "error": err.Error(),
297 }).Error("GRPC Connection problem")
298 }
299 defer conn.Close()
300 client := voltha.NewPonSimClient(conn)
301
302 if _, err = client.GetStats(ctx, empty); err != nil {
303 common.Logger().WithFields(logrus.Fields{
304 "handler": handler,
305 "host": host,
306 "error": err.Error(),
307 }).Error("Problem forwarding stats request to ONU")
308 }
309 }
310 metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
311
312 common.Logger().WithFields(logrus.Fields{
313 "handler": handler,
314 "metrics": metrics,
315 }).Debug("OLT Metrics")
316
317 } else if onu, ok := (handler.device).(*core.PonSimOnuDevice); ok {
318 common.Logger().WithFields(logrus.Fields{
319 "handler": handler,
320 "onu": onu,
321 }).Debug("Retrieving stats for ONU")
322 } else {
323 common.Logger().WithFields(logrus.Fields{
324 "handler": handler,
325 }).Warn("Unknown device")
326 }
327
328 common.Logger().WithFields(logrus.Fields{
329 "handler": handler,
330 }).Info("Retrieved stats")
331
332 return metrics, nil
333}