blob: 330621a5e00049e4f0a154db5245c648cdbd6eff [file] [log] [blame]
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001/*
2 * Copyright 2018-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 */
16
17package api
18
19import (
20 "context"
21 "fmt"
22 "github.com/opencord/bbsim/api/bbsim"
Matteo Scandolod7cc6d32020-02-26 16:51:12 -080023 "github.com/opencord/bbsim/internal/bbsim/alarmsim"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070024 "github.com/opencord/bbsim/internal/bbsim/devices"
25 log "github.com/sirupsen/logrus"
26 "google.golang.org/grpc/codes"
27)
28
29func (s BBSimServer) GetONUs(ctx context.Context, req *bbsim.Empty) (*bbsim.ONUs, error) {
30 olt := devices.GetOLT()
31 onus := bbsim.ONUs{
32 Items: []*bbsim.ONU{},
33 }
34
35 for _, pon := range olt.Pons {
36 for _, o := range pon.Onus {
37 onu := bbsim.ONU{
38 ID: int32(o.ID),
39 SerialNumber: o.Sn(),
40 OperState: o.OperState.Current(),
41 InternalState: o.InternalState.Current(),
42 PonPortID: int32(o.PonPortID),
43 STag: int32(o.STag),
44 CTag: int32(o.CTag),
45 HwAddress: o.HwAddress.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -070046 PortNo: int32(o.PortNo),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070047 }
48 onus.Items = append(onus.Items, &onu)
49 }
50 }
51 return &onus, nil
52}
53
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070054func (s BBSimServer) GetONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONU, error) {
55 olt := devices.GetOLT()
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070056 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070057
58 if err != nil {
59 res := bbsim.ONU{}
60 return &res, err
61 }
62
63 res := bbsim.ONU{
64 ID: int32(onu.ID),
65 SerialNumber: onu.Sn(),
66 OperState: onu.OperState.Current(),
67 InternalState: onu.InternalState.Current(),
68 PonPortID: int32(onu.PonPortID),
69 STag: int32(onu.STag),
70 CTag: int32(onu.CTag),
71 HwAddress: onu.HwAddress.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -070072 PortNo: int32(onu.PortNo),
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070073 }
74 return &res, nil
75}
76
Pragya Aryabd731ec2020-02-11 16:38:17 +053077// ShutdownONU sends DyingGasp indication for specified ONUs and mark ONUs as disabled.
Matteo Scandolo10f965c2019-09-24 10:40:46 -070078func (s BBSimServer) ShutdownONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Anand S Katti09541352020-01-29 15:54:01 +053079 // NOTE this method is now sending a Dying Gasp and then disabling the device (operState: down, adminState: up),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070080 // is this the only way to do? Should we address other cases?
81 // Investigate what happens when:
82 // - a fiber is pulled
83 // - ONU malfunction
84 // - ONU shutdown
Matteo Scandolo10f965c2019-09-24 10:40:46 -070085 logger.WithFields(log.Fields{
86 "OnuSn": req.SerialNumber,
87 }).Infof("Received request to shutdown ONU")
88
Pragya Aryabd731ec2020-02-11 16:38:17 +053089 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070090 olt := devices.GetOLT()
91
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070092 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070093 if err != nil {
94 res.StatusCode = int32(codes.NotFound)
95 res.Message = err.Error()
96 return res, err
97 }
98
Pragya Aryabd731ec2020-02-11 16:38:17 +053099 return handleShutdownONU(onu)
100}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700101
Pragya Aryabd731ec2020-02-11 16:38:17 +0530102// ShutdownONUsOnPON sends DyingGasp indication for all ONUs under specified PON port
103func (s BBSimServer) ShutdownONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
104 logger.WithFields(log.Fields{
105 "IntfId": req.PonPortId,
106 }).Infof("Received request to shutdown all ONUs on PON")
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800107
Pragya Aryabd731ec2020-02-11 16:38:17 +0530108 res := &bbsim.Response{}
109 olt := devices.GetOLT()
110 pon, _ := olt.GetPonById(req.PonPortId)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800111
Pragya Aryabd731ec2020-02-11 16:38:17 +0530112 go func() {
113 for _, onu := range pon.Onus {
114 res, _ = handleShutdownONU(onu)
115 }
116 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700117 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530118 res.Message = fmt.Sprintf("Request accepted for shutdown all ONUs on PON port %d", pon.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700119
120 return res, nil
121}
122
Pragya Aryabd731ec2020-02-11 16:38:17 +0530123// ShutdownAllONUs sends DyingGasp indication for all ONUs and mark ONUs as disabled.
124func (s BBSimServer) ShutdownAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
125 logger.Infof("Received request to shutdown all ONUs")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700126 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530127 olt := devices.GetOLT()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700128
Pragya Aryabd731ec2020-02-11 16:38:17 +0530129 go func() {
130 for _, pon := range olt.Pons {
131 for _, onu := range pon.Onus {
132 res, _ = handleShutdownONU(onu)
133 }
134 }
135 }()
136 res.StatusCode = int32(codes.OK)
137 res.Message = fmt.Sprintf("Request Accepted for shutdown all ONUs in OLT %d", olt.ID)
138
139 return res, nil
140}
141
142// PoweronONU simulates ONU power on and start sending discovery indications to VOLTHA
143func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700144 logger.WithFields(log.Fields{
145 "OnuSn": req.SerialNumber,
146 }).Infof("Received request to poweron ONU")
147
Pragya Aryabd731ec2020-02-11 16:38:17 +0530148 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700149 olt := devices.GetOLT()
150
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700151 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700152 if err != nil {
153 res.StatusCode = int32(codes.NotFound)
154 res.Message = err.Error()
155 return res, err
156 }
157
Pragya Arya2225f202020-01-29 18:05:01 +0530158 pon, _ := olt.GetPonById(onu.PonPortID)
159 if pon.InternalState.Current() != "enabled" {
160 err := fmt.Errorf("PON port %d not enabled", onu.PonPortID)
161 logger.WithFields(log.Fields{
162 "OnuId": onu.ID,
163 "IntfId": onu.PonPortID,
164 "OnuSn": onu.Sn(),
165 }).Errorf("Cannot poweron ONU: %s", err.Error())
166
167 res.StatusCode = int32(codes.FailedPrecondition)
168 res.Message = err.Error()
169 return res, err
170 }
171
Pragya Aryabd731ec2020-02-11 16:38:17 +0530172 return handlePoweronONU(onu)
173}
174
175// PoweronONUsOnPON simulates ONU power on for all ONUs under specified PON port
176func (s BBSimServer) PoweronONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
177 logger.WithFields(log.Fields{
178 "IntfId": req.PonPortId,
179 }).Infof("Received request to poweron all ONUs on PON")
180
181 res := &bbsim.Response{}
182 olt := devices.GetOLT()
183
184 pon, _ := olt.GetPonById(req.PonPortId)
185 if pon.InternalState.Current() != "enabled" {
186 err := fmt.Errorf("PON port %d not enabled", pon.ID)
187 logger.WithFields(log.Fields{
188 "IntfId": pon.ID,
189 }).Errorf("Cannot poweron ONUs on PON: %s", err.Error())
190
191 res.StatusCode = int32(codes.FailedPrecondition)
192 res.Message = err.Error()
193 return res, err
194 }
195
196 go func() {
197 for _, onu := range pon.Onus {
198 res, _ = handlePoweronONU(onu)
Pragya Arya2225f202020-01-29 18:05:01 +0530199 }
Pragya Aryabd731ec2020-02-11 16:38:17 +0530200 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700201 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530202 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs on PON port %d", pon.ID)
203
204 return res, nil
205}
206
207// PoweronAllONUs simulates ONU power on for all ONUs on all PON ports
208func (s BBSimServer) PoweronAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
209 logger.Infof("Received request to poweron all ONUs")
210
211 res := &bbsim.Response{}
212 olt := devices.GetOLT()
213
214 go func() {
215 for _, pon := range olt.Pons {
216 if pon.InternalState.Current() == "enabled" {
217 for _, onu := range pon.Onus {
218 res, _ = handlePoweronONU(onu)
219 }
220 }
221 }
222 }()
223 res.StatusCode = int32(codes.OK)
224 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs in OLT %d", olt.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700225
226 return res, nil
227}
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700228
Arjun E K57a7fcb2020-01-30 06:44:45 +0000229func (s BBSimServer) ChangeIgmpState(ctx context.Context, req *bbsim.IgmpRequest) (*bbsim.Response, error) {
230 res := &bbsim.Response{}
231
232 logger.WithFields(log.Fields{
233 "OnuSn": req.OnuReq.SerialNumber,
234 "subAction": req.SubActionVal,
235 }).Infof("Received igmp request for ONU")
236
237 olt := devices.GetOLT()
238 onu, err := olt.FindOnuBySn(req.OnuReq.SerialNumber)
239
240 if err != nil {
241 res.StatusCode = int32(codes.NotFound)
242 res.Message = err.Error()
243 fmt.Println("ONU not found for sending igmp packet.")
244 return res, err
245 } else {
246 event := ""
247 switch req.SubActionVal {
248 case bbsim.SubActionTypes_JOIN:
249 event = "igmp_join_start"
250 case bbsim.SubActionTypes_LEAVE:
251 event = "igmp_leave"
Anand S Katti09541352020-01-29 15:54:01 +0530252 case bbsim.SubActionTypes_JOINV3:
253 event = "igmp_join_startv3"
Arjun E K57a7fcb2020-01-30 06:44:45 +0000254 }
255
256 if igmpErr := onu.InternalState.Event(event); igmpErr != nil {
257 logger.WithFields(log.Fields{
258 "OnuId": onu.ID,
259 "IntfId": onu.PonPortID,
260 "OnuSn": onu.Sn(),
261 }).Errorf("IGMP request failed: %s", igmpErr.Error())
262 res.StatusCode = int32(codes.FailedPrecondition)
263 res.Message = err.Error()
264 return res, igmpErr
265 }
266 }
267
268 return res, nil
269}
270
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700271func (s BBSimServer) RestartEapol(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
272 res := &bbsim.Response{}
273
274 logger.WithFields(log.Fields{
275 "OnuSn": req.SerialNumber,
276 }).Infof("Received request to restart authentication ONU")
277
278 olt := devices.GetOLT()
279
280 onu, err := olt.FindOnuBySn(req.SerialNumber)
281
282 if err != nil {
283 res.StatusCode = int32(codes.NotFound)
284 res.Message = err.Error()
285 return res, err
286 }
287
288 if err := onu.InternalState.Event("start_auth"); err != nil {
289 logger.WithFields(log.Fields{
290 "OnuId": onu.ID,
291 "IntfId": onu.PonPortID,
292 "OnuSn": onu.Sn(),
293 }).Errorf("Cannot restart authenticaton for ONU: %s", err.Error())
294 res.StatusCode = int32(codes.FailedPrecondition)
295 res.Message = err.Error()
296 return res, err
297 }
298
299 res.StatusCode = int32(codes.OK)
300 res.Message = fmt.Sprintf("Authentication restarted for ONU %s.", onu.Sn())
301
302 return res, nil
303}
304
305func (s BBSimServer) RestartDhcp(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
306 res := &bbsim.Response{}
307
308 logger.WithFields(log.Fields{
309 "OnuSn": req.SerialNumber,
310 }).Infof("Received request to restart DHCP on ONU")
311
312 olt := devices.GetOLT()
313
314 onu, err := olt.FindOnuBySn(req.SerialNumber)
315
316 if err != nil {
317 res.StatusCode = int32(codes.NotFound)
318 res.Message = err.Error()
319 return res, err
320 }
321
322 if err := onu.InternalState.Event("start_dhcp"); err != nil {
323 logger.WithFields(log.Fields{
324 "OnuId": onu.ID,
325 "IntfId": onu.PonPortID,
326 "OnuSn": onu.Sn(),
327 }).Errorf("Cannot restart DHCP for ONU: %s", err.Error())
328 res.StatusCode = int32(codes.FailedPrecondition)
329 res.Message = err.Error()
330 return res, err
331 }
332
333 res.StatusCode = int32(codes.OK)
334 res.Message = fmt.Sprintf("DHCP restarted for ONU %s.", onu.Sn())
335
336 return res, nil
337}
Anand S Katti09541352020-01-29 15:54:01 +0530338
Pragya Arya8bdb4532020-03-02 17:08:09 +0530339// GetFlows for OLT/ONUs
340func (s BBSimServer) GetFlows(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Flows, error) {
341 logger.WithFields(log.Fields{
342 "OnuSn": req.SerialNumber,
343 }).Info("Received GetFlows request")
344
345 olt := devices.GetOLT()
346 res := &bbsim.Flows{}
347
348 if req.SerialNumber == "" {
349 for flowKey := range olt.Flows {
350 flow := olt.Flows[flowKey]
351 res.Flows = append(res.Flows, &flow)
352 }
353 res.FlowCount = uint32(len(olt.Flows))
354 } else {
355 onu, err := olt.FindOnuBySn(req.SerialNumber)
356 if err != nil {
357 logger.WithFields(log.Fields{
358 "OnuSn": req.SerialNumber,
359 }).Error("Can't get ONU in GetFlows request")
360 return nil, err
361 }
362 for _, flowKey := range onu.Flows {
363 flow := olt.Flows[flowKey]
364 res.Flows = append(res.Flows, &flow)
365 }
366 res.FlowCount = uint32(len(onu.Flows))
367 }
368 return res, nil
369}
370
Anand S Katti09541352020-01-29 15:54:01 +0530371func (s BBSimServer) GetOnuTrafficSchedulers(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONUTrafficSchedulers, error) {
372 olt := devices.GetOLT()
373 ts := bbsim.ONUTrafficSchedulers{}
374
375 onu, err := olt.FindOnuBySn(req.SerialNumber)
376 if err != nil {
377 return &ts, err
378 }
379
380 if onu.TrafficSchedulers != nil {
381 ts.TraffSchedulers = onu.TrafficSchedulers
382 return &ts, nil
383 } else {
384 ts.TraffSchedulers = nil
385 return &ts, nil
386 }
387}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530388
389func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
390 res := &bbsim.Response{}
391 olt := devices.GetOLT()
392 intitalState := onu.InternalState.Current()
393 if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
394 if err := onu.InternalState.Event("initialize"); err != nil {
395 logger.WithFields(log.Fields{
396 "OnuId": onu.ID,
397 "IntfId": onu.PonPortID,
398 "OnuSn": onu.Sn(),
399 }).Errorf("Cannot poweron ONU: %s", err.Error())
400 res.StatusCode = int32(codes.FailedPrecondition)
401 res.Message = err.Error()
402 return res, err
403 }
404 }
405
406 losReq := bbsim.ONUAlarmRequest{
407 AlarmType: "LossOfSignal",
408 SerialNumber: onu.Sn(),
409 Status: "off",
410 }
411
412 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
413 logger.WithFields(log.Fields{
414 "OnuId": onu.ID,
415 "IntfId": onu.PonPortID,
416 "OnuSn": onu.Sn(),
417 }).Errorf("Cannot send LOS: %s", err.Error())
418 res.StatusCode = int32(codes.FailedPrecondition)
419 res.Message = err.Error()
420 return res, err
421 }
422
423 if err := onu.InternalState.Event("discover"); err != nil {
424 logger.WithFields(log.Fields{
425 "OnuId": onu.ID,
426 "IntfId": onu.PonPortID,
427 "OnuSn": onu.Sn(),
428 }).Errorf("Cannot poweron ONU: %s", err.Error())
429 res.StatusCode = int32(codes.FailedPrecondition)
430 res.Message = err.Error()
431 return res, err
432 }
433 // move onu directly to enable state only when its a powercycle case
434 // in case of first time onu poweron onu will be moved to enable on
435 // receiving ActivateOnu request from openolt adapter
436 if intitalState == "disabled" {
437 if err := onu.InternalState.Event("enable"); err != nil {
438 logger.WithFields(log.Fields{
439 "OnuId": onu.ID,
440 "IntfId": onu.PonPortID,
441 "OnuSn": onu.Sn(),
442 }).Errorf("Cannot enable ONU: %s", err.Error())
443 res.StatusCode = int32(codes.FailedPrecondition)
444 res.Message = err.Error()
445 return res, err
446 }
447 }
448
449 res.StatusCode = int32(codes.OK)
450 res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
451
452 return res, nil
453}
454
455func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
456 res := &bbsim.Response{}
457 olt := devices.GetOLT()
458
459 dyingGasp := bbsim.ONUAlarmRequest{
460 AlarmType: "DyingGasp",
461 SerialNumber: onu.Sn(),
462 Status: "on",
463 }
464
465 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
466 logger.WithFields(log.Fields{
467 "OnuId": onu.ID,
468 "IntfId": onu.PonPortID,
469 "OnuSn": onu.Sn(),
470 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
471 res.StatusCode = int32(codes.FailedPrecondition)
472 res.Message = err.Error()
473 return res, err
474 }
475
476 losReq := bbsim.ONUAlarmRequest{
477 AlarmType: "LossOfSignal",
478 SerialNumber: onu.Sn(),
479 Status: "on",
480 }
481
482 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
483 logger.WithFields(log.Fields{
484 "OnuId": onu.ID,
485 "IntfId": onu.PonPortID,
486 "OnuSn": onu.Sn(),
487 }).Errorf("Cannot send LOS: %s", err.Error())
488 res.StatusCode = int32(codes.FailedPrecondition)
489 res.Message = err.Error()
490 return res, err
491 }
492
493 // TODO if it's the last ONU on the PON, then send a PON LOS
494
495 if err := onu.InternalState.Event("disable"); err != nil {
496 logger.WithFields(log.Fields{
497 "OnuId": onu.ID,
498 "IntfId": onu.PonPortID,
499 "OnuSn": onu.Sn(),
500 }).Errorf("Cannot shutdown ONU: %s", err.Error())
501 res.StatusCode = int32(codes.FailedPrecondition)
502 res.Message = err.Error()
503 return res, err
504 }
505
506 res.StatusCode = int32(codes.OK)
507 res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
508
509 return res, nil
510}