blob: fe42b3540b11578328922a36aaaf74ffe9b5498f [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
285 if err := onu.InternalState.Event("start_auth"); err != nil {
286 logger.WithFields(log.Fields{
287 "OnuId": onu.ID,
288 "IntfId": onu.PonPortID,
289 "OnuSn": onu.Sn(),
290 }).Errorf("Cannot restart authenticaton for ONU: %s", err.Error())
291 res.StatusCode = int32(codes.FailedPrecondition)
292 res.Message = err.Error()
293 return res, err
294 }
295
296 res.StatusCode = int32(codes.OK)
297 res.Message = fmt.Sprintf("Authentication restarted for ONU %s.", onu.Sn())
298
299 return res, nil
300}
301
302func (s BBSimServer) RestartDhcp(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
303 res := &bbsim.Response{}
304
305 logger.WithFields(log.Fields{
306 "OnuSn": req.SerialNumber,
307 }).Infof("Received request to restart DHCP on ONU")
308
309 olt := devices.GetOLT()
310
311 onu, err := olt.FindOnuBySn(req.SerialNumber)
312
313 if err != nil {
314 res.StatusCode = int32(codes.NotFound)
315 res.Message = err.Error()
316 return res, err
317 }
318
319 if err := onu.InternalState.Event("start_dhcp"); err != nil {
320 logger.WithFields(log.Fields{
321 "OnuId": onu.ID,
322 "IntfId": onu.PonPortID,
323 "OnuSn": onu.Sn(),
324 }).Errorf("Cannot restart DHCP for ONU: %s", err.Error())
325 res.StatusCode = int32(codes.FailedPrecondition)
326 res.Message = err.Error()
327 return res, err
328 }
329
330 res.StatusCode = int32(codes.OK)
331 res.Message = fmt.Sprintf("DHCP restarted for ONU %s.", onu.Sn())
332
333 return res, nil
334}
Anand S Katti09541352020-01-29 15:54:01 +0530335
Pragya Arya8bdb4532020-03-02 17:08:09 +0530336// GetFlows for OLT/ONUs
337func (s BBSimServer) GetFlows(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Flows, error) {
338 logger.WithFields(log.Fields{
339 "OnuSn": req.SerialNumber,
340 }).Info("Received GetFlows request")
341
342 olt := devices.GetOLT()
343 res := &bbsim.Flows{}
344
345 if req.SerialNumber == "" {
346 for flowKey := range olt.Flows {
347 flow := olt.Flows[flowKey]
348 res.Flows = append(res.Flows, &flow)
349 }
350 res.FlowCount = uint32(len(olt.Flows))
351 } else {
352 onu, err := olt.FindOnuBySn(req.SerialNumber)
353 if err != nil {
354 logger.WithFields(log.Fields{
355 "OnuSn": req.SerialNumber,
356 }).Error("Can't get ONU in GetFlows request")
357 return nil, err
358 }
359 for _, flowKey := range onu.Flows {
360 flow := olt.Flows[flowKey]
361 res.Flows = append(res.Flows, &flow)
362 }
363 res.FlowCount = uint32(len(onu.Flows))
364 }
365 return res, nil
366}
367
Anand S Katti09541352020-01-29 15:54:01 +0530368func (s BBSimServer) GetOnuTrafficSchedulers(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONUTrafficSchedulers, error) {
369 olt := devices.GetOLT()
370 ts := bbsim.ONUTrafficSchedulers{}
371
372 onu, err := olt.FindOnuBySn(req.SerialNumber)
373 if err != nil {
374 return &ts, err
375 }
376
377 if onu.TrafficSchedulers != nil {
378 ts.TraffSchedulers = onu.TrafficSchedulers
379 return &ts, nil
380 } else {
381 ts.TraffSchedulers = nil
382 return &ts, nil
383 }
384}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530385
386func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
387 res := &bbsim.Response{}
388 olt := devices.GetOLT()
389 intitalState := onu.InternalState.Current()
390 if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
391 if err := onu.InternalState.Event("initialize"); err != nil {
392 logger.WithFields(log.Fields{
393 "OnuId": onu.ID,
394 "IntfId": onu.PonPortID,
395 "OnuSn": onu.Sn(),
396 }).Errorf("Cannot poweron ONU: %s", err.Error())
397 res.StatusCode = int32(codes.FailedPrecondition)
398 res.Message = err.Error()
399 return res, err
400 }
401 }
402
403 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530404 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530405 SerialNumber: onu.Sn(),
406 Status: "off",
407 }
408
409 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
410 logger.WithFields(log.Fields{
411 "OnuId": onu.ID,
412 "IntfId": onu.PonPortID,
413 "OnuSn": onu.Sn(),
414 }).Errorf("Cannot send LOS: %s", err.Error())
415 res.StatusCode = int32(codes.FailedPrecondition)
416 res.Message = err.Error()
417 return res, err
418 }
419
420 if err := onu.InternalState.Event("discover"); err != nil {
421 logger.WithFields(log.Fields{
422 "OnuId": onu.ID,
423 "IntfId": onu.PonPortID,
424 "OnuSn": onu.Sn(),
425 }).Errorf("Cannot poweron ONU: %s", err.Error())
426 res.StatusCode = int32(codes.FailedPrecondition)
427 res.Message = err.Error()
428 return res, err
429 }
430 // move onu directly to enable state only when its a powercycle case
431 // in case of first time onu poweron onu will be moved to enable on
432 // receiving ActivateOnu request from openolt adapter
433 if intitalState == "disabled" {
434 if err := onu.InternalState.Event("enable"); err != nil {
435 logger.WithFields(log.Fields{
436 "OnuId": onu.ID,
437 "IntfId": onu.PonPortID,
438 "OnuSn": onu.Sn(),
439 }).Errorf("Cannot enable ONU: %s", err.Error())
440 res.StatusCode = int32(codes.FailedPrecondition)
441 res.Message = err.Error()
442 return res, err
443 }
444 }
445
446 res.StatusCode = int32(codes.OK)
447 res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
448
449 return res, nil
450}
451
452func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
453 res := &bbsim.Response{}
454 olt := devices.GetOLT()
455
456 dyingGasp := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530457 AlarmType: "DYING_GASP",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530458 SerialNumber: onu.Sn(),
459 Status: "on",
460 }
461
462 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
463 logger.WithFields(log.Fields{
464 "OnuId": onu.ID,
465 "IntfId": onu.PonPortID,
466 "OnuSn": onu.Sn(),
467 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
468 res.StatusCode = int32(codes.FailedPrecondition)
469 res.Message = err.Error()
470 return res, err
471 }
472
473 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530474 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530475 SerialNumber: onu.Sn(),
476 Status: "on",
477 }
478
479 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
480 logger.WithFields(log.Fields{
481 "OnuId": onu.ID,
482 "IntfId": onu.PonPortID,
483 "OnuSn": onu.Sn(),
484 }).Errorf("Cannot send LOS: %s", err.Error())
485 res.StatusCode = int32(codes.FailedPrecondition)
486 res.Message = err.Error()
487 return res, err
488 }
489
490 // TODO if it's the last ONU on the PON, then send a PON LOS
491
492 if err := onu.InternalState.Event("disable"); err != nil {
493 logger.WithFields(log.Fields{
494 "OnuId": onu.ID,
495 "IntfId": onu.PonPortID,
496 "OnuSn": onu.Sn(),
497 }).Errorf("Cannot shutdown ONU: %s", err.Error())
498 res.StatusCode = int32(codes.FailedPrecondition)
499 res.Message = err.Error()
500 return res, err
501 }
502
503 res.StatusCode = int32(codes.OK)
504 res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
505
506 return res, nil
507}