blob: 332f237475bc6a164ca0b6d36af0c34ee4632792 [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"
Pragya Arya1d5ffb82020-03-20 18:51:37 +053022
Matteo Scandolo10f965c2019-09-24 10:40:46 -070023 "github.com/opencord/bbsim/api/bbsim"
Matteo Scandolod7cc6d32020-02-26 16:51:12 -080024 "github.com/opencord/bbsim/internal/bbsim/alarmsim"
Matteo Scandolo10f965c2019-09-24 10:40:46 -070025 "github.com/opencord/bbsim/internal/bbsim/devices"
26 log "github.com/sirupsen/logrus"
27 "google.golang.org/grpc/codes"
28)
29
30func (s BBSimServer) GetONUs(ctx context.Context, req *bbsim.Empty) (*bbsim.ONUs, error) {
31 olt := devices.GetOLT()
32 onus := bbsim.ONUs{
33 Items: []*bbsim.ONU{},
34 }
35
36 for _, pon := range olt.Pons {
37 for _, o := range pon.Onus {
38 onu := bbsim.ONU{
39 ID: int32(o.ID),
40 SerialNumber: o.Sn(),
41 OperState: o.OperState.Current(),
42 InternalState: o.InternalState.Current(),
43 PonPortID: int32(o.PonPortID),
Matteo Scandolo27428702019-10-11 16:21:16 -070044 PortNo: int32(o.PortNo),
Matteo Scandolo4a036262020-08-17 15:56:13 -070045 Services: convertBBsimServicesToProtoServices(o.Services),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070046 }
47 onus.Items = append(onus.Items, &onu)
48 }
49 }
50 return &onus, nil
51}
52
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070053func (s BBSimServer) GetONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONU, error) {
54 olt := devices.GetOLT()
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070055 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070056
57 if err != nil {
58 res := bbsim.ONU{}
59 return &res, err
60 }
61
62 res := bbsim.ONU{
63 ID: int32(onu.ID),
64 SerialNumber: onu.Sn(),
65 OperState: onu.OperState.Current(),
66 InternalState: onu.InternalState.Current(),
67 PonPortID: int32(onu.PonPortID),
Matteo Scandolo27428702019-10-11 16:21:16 -070068 PortNo: int32(onu.PortNo),
Matteo Scandolo4a036262020-08-17 15:56:13 -070069 Services: convertBBsimServicesToProtoServices(onu.Services),
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070070 }
71 return &res, nil
72}
73
Pragya Aryabd731ec2020-02-11 16:38:17 +053074// ShutdownONU sends DyingGasp indication for specified ONUs and mark ONUs as disabled.
Matteo Scandolo10f965c2019-09-24 10:40:46 -070075func (s BBSimServer) ShutdownONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Anand S Katti09541352020-01-29 15:54:01 +053076 // 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 -070077 // is this the only way to do? Should we address other cases?
78 // Investigate what happens when:
79 // - a fiber is pulled
80 // - ONU malfunction
81 // - ONU shutdown
Matteo Scandolo10f965c2019-09-24 10:40:46 -070082 logger.WithFields(log.Fields{
83 "OnuSn": req.SerialNumber,
84 }).Infof("Received request to shutdown ONU")
85
Pragya Aryabd731ec2020-02-11 16:38:17 +053086 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070087 olt := devices.GetOLT()
88
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070089 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070090 if err != nil {
91 res.StatusCode = int32(codes.NotFound)
92 res.Message = err.Error()
93 return res, err
94 }
95
Pragya Aryabd731ec2020-02-11 16:38:17 +053096 return handleShutdownONU(onu)
97}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070098
Pragya Aryabd731ec2020-02-11 16:38:17 +053099// ShutdownONUsOnPON sends DyingGasp indication for all ONUs under specified PON port
100func (s BBSimServer) ShutdownONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
101 logger.WithFields(log.Fields{
102 "IntfId": req.PonPortId,
103 }).Infof("Received request to shutdown all ONUs on PON")
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800104
Pragya Aryabd731ec2020-02-11 16:38:17 +0530105 res := &bbsim.Response{}
106 olt := devices.GetOLT()
107 pon, _ := olt.GetPonById(req.PonPortId)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800108
Pragya Aryabd731ec2020-02-11 16:38:17 +0530109 go func() {
110 for _, onu := range pon.Onus {
111 res, _ = handleShutdownONU(onu)
112 }
113 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700114 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530115 res.Message = fmt.Sprintf("Request accepted for shutdown all ONUs on PON port %d", pon.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700116
117 return res, nil
118}
119
Pragya Aryabd731ec2020-02-11 16:38:17 +0530120// ShutdownAllONUs sends DyingGasp indication for all ONUs and mark ONUs as disabled.
121func (s BBSimServer) ShutdownAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
122 logger.Infof("Received request to shutdown all ONUs")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700123 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530124 olt := devices.GetOLT()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700125
Pragya Aryabd731ec2020-02-11 16:38:17 +0530126 go func() {
127 for _, pon := range olt.Pons {
128 for _, onu := range pon.Onus {
129 res, _ = handleShutdownONU(onu)
130 }
131 }
132 }()
133 res.StatusCode = int32(codes.OK)
134 res.Message = fmt.Sprintf("Request Accepted for shutdown all ONUs in OLT %d", olt.ID)
135
136 return res, nil
137}
138
139// PoweronONU simulates ONU power on and start sending discovery indications to VOLTHA
140func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700141 logger.WithFields(log.Fields{
142 "OnuSn": req.SerialNumber,
143 }).Infof("Received request to poweron ONU")
144
Pragya Aryabd731ec2020-02-11 16:38:17 +0530145 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700146 olt := devices.GetOLT()
147
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700148 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700149 if err != nil {
150 res.StatusCode = int32(codes.NotFound)
151 res.Message = err.Error()
152 return res, err
153 }
154
Pragya Arya2225f202020-01-29 18:05:01 +0530155 pon, _ := olt.GetPonById(onu.PonPortID)
156 if pon.InternalState.Current() != "enabled" {
157 err := fmt.Errorf("PON port %d not enabled", onu.PonPortID)
158 logger.WithFields(log.Fields{
159 "OnuId": onu.ID,
160 "IntfId": onu.PonPortID,
161 "OnuSn": onu.Sn(),
162 }).Errorf("Cannot poweron ONU: %s", err.Error())
163
164 res.StatusCode = int32(codes.FailedPrecondition)
165 res.Message = err.Error()
166 return res, err
167 }
168
Pragya Aryabd731ec2020-02-11 16:38:17 +0530169 return handlePoweronONU(onu)
170}
171
172// PoweronONUsOnPON simulates ONU power on for all ONUs under specified PON port
173func (s BBSimServer) PoweronONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
174 logger.WithFields(log.Fields{
175 "IntfId": req.PonPortId,
176 }).Infof("Received request to poweron all ONUs on PON")
177
178 res := &bbsim.Response{}
179 olt := devices.GetOLT()
180
181 pon, _ := olt.GetPonById(req.PonPortId)
182 if pon.InternalState.Current() != "enabled" {
183 err := fmt.Errorf("PON port %d not enabled", pon.ID)
184 logger.WithFields(log.Fields{
185 "IntfId": pon.ID,
186 }).Errorf("Cannot poweron ONUs on PON: %s", err.Error())
187
188 res.StatusCode = int32(codes.FailedPrecondition)
189 res.Message = err.Error()
190 return res, err
191 }
192
193 go func() {
194 for _, onu := range pon.Onus {
195 res, _ = handlePoweronONU(onu)
Pragya Arya2225f202020-01-29 18:05:01 +0530196 }
Pragya Aryabd731ec2020-02-11 16:38:17 +0530197 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700198 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530199 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs on PON port %d", pon.ID)
200
201 return res, nil
202}
203
204// PoweronAllONUs simulates ONU power on for all ONUs on all PON ports
205func (s BBSimServer) PoweronAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
206 logger.Infof("Received request to poweron all ONUs")
207
208 res := &bbsim.Response{}
209 olt := devices.GetOLT()
210
211 go func() {
212 for _, pon := range olt.Pons {
213 if pon.InternalState.Current() == "enabled" {
214 for _, onu := range pon.Onus {
215 res, _ = handlePoweronONU(onu)
216 }
217 }
218 }
219 }()
220 res.StatusCode = int32(codes.OK)
221 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs in OLT %d", olt.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700222
223 return res, nil
224}
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700225
Arjun E K57a7fcb2020-01-30 06:44:45 +0000226func (s BBSimServer) ChangeIgmpState(ctx context.Context, req *bbsim.IgmpRequest) (*bbsim.Response, error) {
227 res := &bbsim.Response{}
228
229 logger.WithFields(log.Fields{
230 "OnuSn": req.OnuReq.SerialNumber,
231 "subAction": req.SubActionVal,
232 }).Infof("Received igmp request for ONU")
233
234 olt := devices.GetOLT()
235 onu, err := olt.FindOnuBySn(req.OnuReq.SerialNumber)
236
237 if err != nil {
238 res.StatusCode = int32(codes.NotFound)
239 res.Message = err.Error()
240 fmt.Println("ONU not found for sending igmp packet.")
241 return res, err
242 } else {
243 event := ""
244 switch req.SubActionVal {
245 case bbsim.SubActionTypes_JOIN:
246 event = "igmp_join_start"
247 case bbsim.SubActionTypes_LEAVE:
248 event = "igmp_leave"
Anand S Katti09541352020-01-29 15:54:01 +0530249 case bbsim.SubActionTypes_JOINV3:
250 event = "igmp_join_startv3"
Arjun E K57a7fcb2020-01-30 06:44:45 +0000251 }
252
253 if igmpErr := onu.InternalState.Event(event); igmpErr != nil {
254 logger.WithFields(log.Fields{
255 "OnuId": onu.ID,
256 "IntfId": onu.PonPortID,
257 "OnuSn": onu.Sn(),
258 }).Errorf("IGMP request failed: %s", igmpErr.Error())
259 res.StatusCode = int32(codes.FailedPrecondition)
Jonathan Hartacfa20e2020-03-31 15:20:14 -0700260 res.Message = igmpErr.Error()
Arjun E K57a7fcb2020-01-30 06:44:45 +0000261 return res, igmpErr
262 }
263 }
264
265 return res, nil
266}
267
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700268func (s BBSimServer) RestartEapol(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
269 res := &bbsim.Response{}
270
271 logger.WithFields(log.Fields{
272 "OnuSn": req.SerialNumber,
273 }).Infof("Received request to restart authentication ONU")
274
275 olt := devices.GetOLT()
276
277 onu, err := olt.FindOnuBySn(req.SerialNumber)
278
279 if err != nil {
280 res.StatusCode = int32(codes.NotFound)
281 res.Message = err.Error()
282 return res, err
283 }
284
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700285 errors := []string{}
286 success := true
287
288 for _, s := range onu.Services {
289 service := s.(*devices.Service)
290 if service.NeedsEapol {
291 if err := service.EapolState.Event("start_auth"); err != nil {
292 logger.WithFields(log.Fields{
293 "OnuId": onu.ID,
294 "IntfId": onu.PonPortID,
295 "OnuSn": onu.Sn(),
296 "Service": service.Name,
297 }).Errorf("Cannot restart authenticaton for Service: %s", err.Error())
298 errors = append(errors, fmt.Sprintf("%s: %s", service.Name, err.Error()))
299 success = false
300 }
301 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700302 }
303
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700304 if success {
305 res.StatusCode = int32(codes.OK)
306 res.Message = fmt.Sprintf("Authentication restarted for ONU %s.", onu.Sn())
307 } else {
308 res.StatusCode = int32(codes.FailedPrecondition)
309 res.Message = fmt.Sprintf("%v", errors)
310 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700311
312 return res, nil
313}
314
315func (s BBSimServer) RestartDhcp(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
316 res := &bbsim.Response{}
317
318 logger.WithFields(log.Fields{
319 "OnuSn": req.SerialNumber,
320 }).Infof("Received request to restart DHCP on ONU")
321
322 olt := devices.GetOLT()
323
324 onu, err := olt.FindOnuBySn(req.SerialNumber)
325
326 if err != nil {
327 res.StatusCode = int32(codes.NotFound)
328 res.Message = err.Error()
329 return res, err
330 }
331
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700332 errors := []string{}
333 success := true
334
335 for _, s := range onu.Services {
336 service := s.(*devices.Service)
337 if service.NeedsDhcp {
338
339 if err := service.DHCPState.Event("start_dhcp"); err != nil {
340 logger.WithFields(log.Fields{
341 "OnuId": onu.ID,
342 "IntfId": onu.PonPortID,
343 "OnuSn": onu.Sn(),
344 "Service": service.Name,
345 }).Errorf("Cannot restart DHCP for Service: %s", err.Error())
346 errors = append(errors, fmt.Sprintf("%s: %s", service.Name, err.Error()))
347 success = false
348 }
349 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700350 }
351
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700352 if success {
353 res.StatusCode = int32(codes.OK)
354 res.Message = fmt.Sprintf("DHCP restarted for ONU %s.", onu.Sn())
355 } else {
356 res.StatusCode = int32(codes.FailedPrecondition)
357 res.Message = fmt.Sprintf("%v", errors)
358 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700359
360 return res, nil
361}
Anand S Katti09541352020-01-29 15:54:01 +0530362
Pragya Arya8bdb4532020-03-02 17:08:09 +0530363// GetFlows for OLT/ONUs
364func (s BBSimServer) GetFlows(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Flows, error) {
365 logger.WithFields(log.Fields{
366 "OnuSn": req.SerialNumber,
367 }).Info("Received GetFlows request")
368
369 olt := devices.GetOLT()
370 res := &bbsim.Flows{}
371
372 if req.SerialNumber == "" {
373 for flowKey := range olt.Flows {
374 flow := olt.Flows[flowKey]
375 res.Flows = append(res.Flows, &flow)
376 }
377 res.FlowCount = uint32(len(olt.Flows))
378 } else {
379 onu, err := olt.FindOnuBySn(req.SerialNumber)
380 if err != nil {
381 logger.WithFields(log.Fields{
382 "OnuSn": req.SerialNumber,
383 }).Error("Can't get ONU in GetFlows request")
384 return nil, err
385 }
386 for _, flowKey := range onu.Flows {
387 flow := olt.Flows[flowKey]
388 res.Flows = append(res.Flows, &flow)
389 }
390 res.FlowCount = uint32(len(onu.Flows))
391 }
392 return res, nil
393}
394
Anand S Katti09541352020-01-29 15:54:01 +0530395func (s BBSimServer) GetOnuTrafficSchedulers(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONUTrafficSchedulers, error) {
396 olt := devices.GetOLT()
397 ts := bbsim.ONUTrafficSchedulers{}
398
399 onu, err := olt.FindOnuBySn(req.SerialNumber)
400 if err != nil {
401 return &ts, err
402 }
403
404 if onu.TrafficSchedulers != nil {
405 ts.TraffSchedulers = onu.TrafficSchedulers
406 return &ts, nil
407 } else {
408 ts.TraffSchedulers = nil
409 return &ts, nil
410 }
411}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530412
413func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
414 res := &bbsim.Response{}
415 olt := devices.GetOLT()
416 intitalState := onu.InternalState.Current()
417 if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
418 if err := onu.InternalState.Event("initialize"); err != nil {
419 logger.WithFields(log.Fields{
420 "OnuId": onu.ID,
421 "IntfId": onu.PonPortID,
422 "OnuSn": onu.Sn(),
423 }).Errorf("Cannot poweron ONU: %s", err.Error())
424 res.StatusCode = int32(codes.FailedPrecondition)
425 res.Message = err.Error()
426 return res, err
427 }
428 }
429
430 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530431 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530432 SerialNumber: onu.Sn(),
433 Status: "off",
434 }
435
436 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
437 logger.WithFields(log.Fields{
438 "OnuId": onu.ID,
439 "IntfId": onu.PonPortID,
440 "OnuSn": onu.Sn(),
441 }).Errorf("Cannot send LOS: %s", err.Error())
442 res.StatusCode = int32(codes.FailedPrecondition)
443 res.Message = err.Error()
444 return res, err
445 }
446
447 if err := onu.InternalState.Event("discover"); err != nil {
448 logger.WithFields(log.Fields{
449 "OnuId": onu.ID,
450 "IntfId": onu.PonPortID,
451 "OnuSn": onu.Sn(),
452 }).Errorf("Cannot poweron ONU: %s", err.Error())
453 res.StatusCode = int32(codes.FailedPrecondition)
454 res.Message = err.Error()
455 return res, err
456 }
457 // move onu directly to enable state only when its a powercycle case
458 // in case of first time onu poweron onu will be moved to enable on
459 // receiving ActivateOnu request from openolt adapter
460 if intitalState == "disabled" {
461 if err := onu.InternalState.Event("enable"); err != nil {
462 logger.WithFields(log.Fields{
463 "OnuId": onu.ID,
464 "IntfId": onu.PonPortID,
465 "OnuSn": onu.Sn(),
466 }).Errorf("Cannot enable ONU: %s", err.Error())
467 res.StatusCode = int32(codes.FailedPrecondition)
468 res.Message = err.Error()
469 return res, err
470 }
471 }
472
473 res.StatusCode = int32(codes.OK)
474 res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
475
476 return res, nil
477}
478
479func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
480 res := &bbsim.Response{}
481 olt := devices.GetOLT()
482
483 dyingGasp := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530484 AlarmType: "DYING_GASP",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530485 SerialNumber: onu.Sn(),
486 Status: "on",
487 }
488
489 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
490 logger.WithFields(log.Fields{
491 "OnuId": onu.ID,
492 "IntfId": onu.PonPortID,
493 "OnuSn": onu.Sn(),
494 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
495 res.StatusCode = int32(codes.FailedPrecondition)
496 res.Message = err.Error()
497 return res, err
498 }
499
500 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530501 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530502 SerialNumber: onu.Sn(),
503 Status: "on",
504 }
505
506 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
507 logger.WithFields(log.Fields{
508 "OnuId": onu.ID,
509 "IntfId": onu.PonPortID,
510 "OnuSn": onu.Sn(),
511 }).Errorf("Cannot send LOS: %s", err.Error())
512 res.StatusCode = int32(codes.FailedPrecondition)
513 res.Message = err.Error()
514 return res, err
515 }
516
517 // TODO if it's the last ONU on the PON, then send a PON LOS
518
519 if err := onu.InternalState.Event("disable"); err != nil {
520 logger.WithFields(log.Fields{
521 "OnuId": onu.ID,
522 "IntfId": onu.PonPortID,
523 "OnuSn": onu.Sn(),
524 }).Errorf("Cannot shutdown ONU: %s", err.Error())
525 res.StatusCode = int32(codes.FailedPrecondition)
526 res.Message = err.Error()
527 return res, err
528 }
529
530 res.StatusCode = int32(codes.OK)
531 res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
532
533 return res, nil
534}