blob: 8205386df3372d6b6e89783df301c501973c167b [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
131 var out *voltha.PonSimDeviceInfo
132
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")
138 keys := make([]int32, 0, len((handler.device).(*core.PonSimOltDevice).GetOnus()))
139 for k := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
140 keys = append(keys, k)
141 }
142 out = &voltha.PonSimDeviceInfo{NniPort: 0, UniPorts: []int32(keys)}
143
144 } else {
145 common.Logger().WithFields(logrus.Fields{
146 "handler": handler,
147 }).Debug("Handling ONU/OTHER device")
148
149 out = &voltha.PonSimDeviceInfo{}
150 }
151
152 common.Logger().WithFields(logrus.Fields{
153 "handler": handler,
154 "result": out,
155 }).Info("Device information")
156
157 return out, nil
158}
159
160/*
161UpdateFlowTable populates and cleans up the flows for a PonSim device
162*/
163func (handler *PonSimHandler) UpdateFlowTable(
164 ctx context.Context,
165 table *voltha.FlowTable,
166) (*empty.Empty, error) {
167 common.Logger().WithFields(logrus.Fields{
168 "handler": handler,
169 "table": table,
170 }).Info("Updating flows")
171
172 if _, ok := (handler.device).(*core.PonSimOltDevice); ok {
173 if table.Port == 0 {
174 common.Logger().WithFields(logrus.Fields{
175 "handler": handler,
176 "port": table.Port,
177 }).Debug("Updating OLT flows")
178
179 if err := (handler.device).(*core.PonSimOltDevice).InstallFlows(ctx, table.Flows); err != nil {
180 common.Logger().WithFields(logrus.Fields{
181 "handler": handler,
182 "error": err.Error(),
183 "flows": table.Flows,
184 }).Error("Problem updating flows on OLT")
185 } else {
186 common.Logger().WithFields(logrus.Fields{
187 "handler": handler,
188 }).Debug("Updated OLT flows")
189 }
190
191 } else {
192 common.Logger().WithFields(logrus.Fields{
193 "handler": handler,
194 "port": table.Port,
195 }).Debug("Updating ONU flows")
196
197 if child, ok := (handler.device).(*core.PonSimOltDevice).GetOnus()[table.Port]; ok {
Stephane Barbarie35595062018-02-08 08:34:39 -0500198
199 host := strings.Join([]string{
200 child.Device.Address,
201 strconv.Itoa(int(child.Device.Port)),
202 }, ":")
203
204 conn, err := grpc.Dial(
205 host,
Jeff70e8b2d2018-07-24 13:37:29 -0700206 grpc.WithInsecure(),
Stephane Barbarie35595062018-02-08 08:34:39 -0500207 )
208 if err != nil {
209 common.Logger().WithFields(logrus.Fields{
210 "handler": handler,
211 "error": err.Error(),
212 }).Error("GRPC Connection problem")
213 }
214 defer conn.Close()
215 client := voltha.NewPonSimClient(conn)
216
217 if _, err = client.UpdateFlowTable(ctx, table); err != nil {
218 common.Logger().WithFields(logrus.Fields{
219 "handler": handler,
220 "host": host,
221 "error": err.Error(),
222 }).Error("Problem forwarding update request to ONU")
223 }
224 } else {
225 common.Logger().WithFields(logrus.Fields{
226 "handler": handler,
227 "port": table.Port,
228 }).Warn("Unable to find ONU")
229 }
230
231 }
232 } else if _, ok := (handler.device).(*core.PonSimOnuDevice); ok {
233 if err := (handler.device).(*core.PonSimOnuDevice).InstallFlows(ctx, table.Flows); err != nil {
234 common.Logger().WithFields(logrus.Fields{
235 "handler": handler,
236 "error": err.Error(),
237 "flows": table.Flows,
238 }).Error("Problem updating flows on ONU")
239 } else {
240 common.Logger().WithFields(logrus.Fields{
241 "handler": handler,
242 }).Debug("Updated ONU flows")
243 }
244 } else {
245 common.Logger().WithFields(logrus.Fields{
246 "handler": handler,
247 "port": table.Port,
248 }).Warn("Unknown device")
249 }
250
251 common.Logger().WithFields(logrus.Fields{
252 "handler": handler,
253 "table": table,
254 }).Info("Updated flows")
255
256 out := new(empty.Empty)
257 return out, nil
258}
259
260/*
261GetStats retrieves statistics for a PonSim device
262*/
263func (handler *PonSimHandler) GetStats(
264 ctx context.Context,
265 empty *empty.Empty,
266) (*voltha.PonSimMetrics, error) {
267 common.Logger().WithFields(logrus.Fields{
268 "handler": handler,
269 }).Info("Retrieving stats")
270
271 var metrics *voltha.PonSimMetrics = new(voltha.PonSimMetrics)
272
273 if olt, ok := (handler.device).(*core.PonSimOltDevice); ok {
274 common.Logger().WithFields(logrus.Fields{
275 "handler": handler,
276 "olt": olt,
277 }).Debug("Retrieving stats for OLT")
278
279 // Get stats for current device
280
281 // Loop through each onus to get stats from those as well?
282 // send grpc request to each onu
283 for _, child := range (handler.device).(*core.PonSimOltDevice).GetOnus() {
Stephane Barbarie35595062018-02-08 08:34:39 -0500284
285 host := strings.Join([]string{child.Device.Address, strconv.Itoa(int(child.Device.Port))}, ":")
286 conn, err := grpc.Dial(
287 host,
Jeff70e8b2d2018-07-24 13:37:29 -0700288 grpc.WithInsecure(),
Stephane Barbarie35595062018-02-08 08:34:39 -0500289 )
290 if err != nil {
291 common.Logger().WithFields(logrus.Fields{
292 "handler": handler,
293 "error": err.Error(),
294 }).Error("GRPC Connection problem")
295 }
296 defer conn.Close()
297 client := voltha.NewPonSimClient(conn)
298
299 if _, err = client.GetStats(ctx, empty); err != nil {
300 common.Logger().WithFields(logrus.Fields{
301 "handler": handler,
302 "host": host,
303 "error": err.Error(),
304 }).Error("Problem forwarding stats request to ONU")
305 }
306 }
307 metrics = (handler.device).(*core.PonSimOltDevice).Counter.MakeProto()
308
309 common.Logger().WithFields(logrus.Fields{
310 "handler": handler,
311 "metrics": metrics,
312 }).Debug("OLT Metrics")
313
314 } else if onu, ok := (handler.device).(*core.PonSimOnuDevice); ok {
315 common.Logger().WithFields(logrus.Fields{
316 "handler": handler,
317 "onu": onu,
318 }).Debug("Retrieving stats for ONU")
319 } else {
320 common.Logger().WithFields(logrus.Fields{
321 "handler": handler,
322 }).Warn("Unknown device")
323 }
324
325 common.Logger().WithFields(logrus.Fields{
326 "handler": handler,
327 }).Info("Retrieved stats")
328
329 return metrics, nil
330}