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