blob: 116199a1d3bf16cba39c5b860b8558fc82eaa1f1 [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),
44 STag: int32(o.STag),
45 CTag: int32(o.CTag),
46 HwAddress: o.HwAddress.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -070047 PortNo: int32(o.PortNo),
Matteo Scandolo10f965c2019-09-24 10:40:46 -070048 }
49 onus.Items = append(onus.Items, &onu)
50 }
51 }
52 return &onus, nil
53}
54
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070055func (s BBSimServer) GetONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONU, error) {
56 olt := devices.GetOLT()
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070057 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070058
59 if err != nil {
60 res := bbsim.ONU{}
61 return &res, err
62 }
63
64 res := bbsim.ONU{
65 ID: int32(onu.ID),
66 SerialNumber: onu.Sn(),
67 OperState: onu.OperState.Current(),
68 InternalState: onu.InternalState.Current(),
69 PonPortID: int32(onu.PonPortID),
70 STag: int32(onu.STag),
71 CTag: int32(onu.CTag),
72 HwAddress: onu.HwAddress.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -070073 PortNo: int32(onu.PortNo),
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070074 }
75 return &res, nil
76}
77
Pragya Aryabd731ec2020-02-11 16:38:17 +053078// ShutdownONU sends DyingGasp indication for specified ONUs and mark ONUs as disabled.
Matteo Scandolo10f965c2019-09-24 10:40:46 -070079func (s BBSimServer) ShutdownONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Anand S Katti09541352020-01-29 15:54:01 +053080 // 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 -070081 // is this the only way to do? Should we address other cases?
82 // Investigate what happens when:
83 // - a fiber is pulled
84 // - ONU malfunction
85 // - ONU shutdown
Matteo Scandolo10f965c2019-09-24 10:40:46 -070086 logger.WithFields(log.Fields{
87 "OnuSn": req.SerialNumber,
88 }).Infof("Received request to shutdown ONU")
89
Pragya Aryabd731ec2020-02-11 16:38:17 +053090 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070091 olt := devices.GetOLT()
92
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070093 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070094 if err != nil {
95 res.StatusCode = int32(codes.NotFound)
96 res.Message = err.Error()
97 return res, err
98 }
99
Pragya Aryabd731ec2020-02-11 16:38:17 +0530100 return handleShutdownONU(onu)
101}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700102
Pragya Aryabd731ec2020-02-11 16:38:17 +0530103// ShutdownONUsOnPON sends DyingGasp indication for all ONUs under specified PON port
104func (s BBSimServer) ShutdownONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
105 logger.WithFields(log.Fields{
106 "IntfId": req.PonPortId,
107 }).Infof("Received request to shutdown all ONUs on PON")
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800108
Pragya Aryabd731ec2020-02-11 16:38:17 +0530109 res := &bbsim.Response{}
110 olt := devices.GetOLT()
111 pon, _ := olt.GetPonById(req.PonPortId)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800112
Pragya Aryabd731ec2020-02-11 16:38:17 +0530113 go func() {
114 for _, onu := range pon.Onus {
115 res, _ = handleShutdownONU(onu)
116 }
117 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700118 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530119 res.Message = fmt.Sprintf("Request accepted for shutdown all ONUs on PON port %d", pon.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700120
121 return res, nil
122}
123
Pragya Aryabd731ec2020-02-11 16:38:17 +0530124// ShutdownAllONUs sends DyingGasp indication for all ONUs and mark ONUs as disabled.
125func (s BBSimServer) ShutdownAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
126 logger.Infof("Received request to shutdown all ONUs")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700127 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530128 olt := devices.GetOLT()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700129
Pragya Aryabd731ec2020-02-11 16:38:17 +0530130 go func() {
131 for _, pon := range olt.Pons {
132 for _, onu := range pon.Onus {
133 res, _ = handleShutdownONU(onu)
134 }
135 }
136 }()
137 res.StatusCode = int32(codes.OK)
138 res.Message = fmt.Sprintf("Request Accepted for shutdown all ONUs in OLT %d", olt.ID)
139
140 return res, nil
141}
142
143// PoweronONU simulates ONU power on and start sending discovery indications to VOLTHA
144func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700145 logger.WithFields(log.Fields{
146 "OnuSn": req.SerialNumber,
147 }).Infof("Received request to poweron ONU")
148
Pragya Aryabd731ec2020-02-11 16:38:17 +0530149 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700150 olt := devices.GetOLT()
151
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700152 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700153 if err != nil {
154 res.StatusCode = int32(codes.NotFound)
155 res.Message = err.Error()
156 return res, err
157 }
158
Pragya Arya2225f202020-01-29 18:05:01 +0530159 pon, _ := olt.GetPonById(onu.PonPortID)
160 if pon.InternalState.Current() != "enabled" {
161 err := fmt.Errorf("PON port %d not enabled", onu.PonPortID)
162 logger.WithFields(log.Fields{
163 "OnuId": onu.ID,
164 "IntfId": onu.PonPortID,
165 "OnuSn": onu.Sn(),
166 }).Errorf("Cannot poweron ONU: %s", err.Error())
167
168 res.StatusCode = int32(codes.FailedPrecondition)
169 res.Message = err.Error()
170 return res, err
171 }
172
Pragya Aryabd731ec2020-02-11 16:38:17 +0530173 return handlePoweronONU(onu)
174}
175
176// PoweronONUsOnPON simulates ONU power on for all ONUs under specified PON port
177func (s BBSimServer) PoweronONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
178 logger.WithFields(log.Fields{
179 "IntfId": req.PonPortId,
180 }).Infof("Received request to poweron all ONUs on PON")
181
182 res := &bbsim.Response{}
183 olt := devices.GetOLT()
184
185 pon, _ := olt.GetPonById(req.PonPortId)
186 if pon.InternalState.Current() != "enabled" {
187 err := fmt.Errorf("PON port %d not enabled", pon.ID)
188 logger.WithFields(log.Fields{
189 "IntfId": pon.ID,
190 }).Errorf("Cannot poweron ONUs on PON: %s", err.Error())
191
192 res.StatusCode = int32(codes.FailedPrecondition)
193 res.Message = err.Error()
194 return res, err
195 }
196
197 go func() {
198 for _, onu := range pon.Onus {
199 res, _ = handlePoweronONU(onu)
Pragya Arya2225f202020-01-29 18:05:01 +0530200 }
Pragya Aryabd731ec2020-02-11 16:38:17 +0530201 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700202 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530203 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs on PON port %d", pon.ID)
204
205 return res, nil
206}
207
208// PoweronAllONUs simulates ONU power on for all ONUs on all PON ports
209func (s BBSimServer) PoweronAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
210 logger.Infof("Received request to poweron all ONUs")
211
212 res := &bbsim.Response{}
213 olt := devices.GetOLT()
214
215 go func() {
216 for _, pon := range olt.Pons {
217 if pon.InternalState.Current() == "enabled" {
218 for _, onu := range pon.Onus {
219 res, _ = handlePoweronONU(onu)
220 }
221 }
222 }
223 }()
224 res.StatusCode = int32(codes.OK)
225 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs in OLT %d", olt.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700226
227 return res, nil
228}
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700229
Arjun E K57a7fcb2020-01-30 06:44:45 +0000230func (s BBSimServer) ChangeIgmpState(ctx context.Context, req *bbsim.IgmpRequest) (*bbsim.Response, error) {
231 res := &bbsim.Response{}
232
233 logger.WithFields(log.Fields{
234 "OnuSn": req.OnuReq.SerialNumber,
235 "subAction": req.SubActionVal,
236 }).Infof("Received igmp request for ONU")
237
238 olt := devices.GetOLT()
239 onu, err := olt.FindOnuBySn(req.OnuReq.SerialNumber)
240
241 if err != nil {
242 res.StatusCode = int32(codes.NotFound)
243 res.Message = err.Error()
244 fmt.Println("ONU not found for sending igmp packet.")
245 return res, err
246 } else {
247 event := ""
248 switch req.SubActionVal {
249 case bbsim.SubActionTypes_JOIN:
250 event = "igmp_join_start"
251 case bbsim.SubActionTypes_LEAVE:
252 event = "igmp_leave"
Anand S Katti09541352020-01-29 15:54:01 +0530253 case bbsim.SubActionTypes_JOINV3:
254 event = "igmp_join_startv3"
Arjun E K57a7fcb2020-01-30 06:44:45 +0000255 }
256
257 if igmpErr := onu.InternalState.Event(event); igmpErr != nil {
258 logger.WithFields(log.Fields{
259 "OnuId": onu.ID,
260 "IntfId": onu.PonPortID,
261 "OnuSn": onu.Sn(),
262 }).Errorf("IGMP request failed: %s", igmpErr.Error())
263 res.StatusCode = int32(codes.FailedPrecondition)
264 res.Message = err.Error()
265 return res, igmpErr
266 }
267 }
268
269 return res, nil
270}
271
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700272func (s BBSimServer) RestartEapol(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
273 res := &bbsim.Response{}
274
275 logger.WithFields(log.Fields{
276 "OnuSn": req.SerialNumber,
277 }).Infof("Received request to restart authentication ONU")
278
279 olt := devices.GetOLT()
280
281 onu, err := olt.FindOnuBySn(req.SerialNumber)
282
283 if err != nil {
284 res.StatusCode = int32(codes.NotFound)
285 res.Message = err.Error()
286 return res, err
287 }
288
289 if err := onu.InternalState.Event("start_auth"); err != nil {
290 logger.WithFields(log.Fields{
291 "OnuId": onu.ID,
292 "IntfId": onu.PonPortID,
293 "OnuSn": onu.Sn(),
294 }).Errorf("Cannot restart authenticaton for ONU: %s", err.Error())
295 res.StatusCode = int32(codes.FailedPrecondition)
296 res.Message = err.Error()
297 return res, err
298 }
299
300 res.StatusCode = int32(codes.OK)
301 res.Message = fmt.Sprintf("Authentication restarted for ONU %s.", onu.Sn())
302
303 return res, nil
304}
305
306func (s BBSimServer) RestartDhcp(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
307 res := &bbsim.Response{}
308
309 logger.WithFields(log.Fields{
310 "OnuSn": req.SerialNumber,
311 }).Infof("Received request to restart DHCP on ONU")
312
313 olt := devices.GetOLT()
314
315 onu, err := olt.FindOnuBySn(req.SerialNumber)
316
317 if err != nil {
318 res.StatusCode = int32(codes.NotFound)
319 res.Message = err.Error()
320 return res, err
321 }
322
323 if err := onu.InternalState.Event("start_dhcp"); err != nil {
324 logger.WithFields(log.Fields{
325 "OnuId": onu.ID,
326 "IntfId": onu.PonPortID,
327 "OnuSn": onu.Sn(),
328 }).Errorf("Cannot restart DHCP for ONU: %s", err.Error())
329 res.StatusCode = int32(codes.FailedPrecondition)
330 res.Message = err.Error()
331 return res, err
332 }
333
334 res.StatusCode = int32(codes.OK)
335 res.Message = fmt.Sprintf("DHCP restarted for ONU %s.", onu.Sn())
336
337 return res, nil
338}
Anand S Katti09541352020-01-29 15:54:01 +0530339
Pragya Arya8bdb4532020-03-02 17:08:09 +0530340// GetFlows for OLT/ONUs
341func (s BBSimServer) GetFlows(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Flows, error) {
342 logger.WithFields(log.Fields{
343 "OnuSn": req.SerialNumber,
344 }).Info("Received GetFlows request")
345
346 olt := devices.GetOLT()
347 res := &bbsim.Flows{}
348
349 if req.SerialNumber == "" {
350 for flowKey := range olt.Flows {
351 flow := olt.Flows[flowKey]
352 res.Flows = append(res.Flows, &flow)
353 }
354 res.FlowCount = uint32(len(olt.Flows))
355 } else {
356 onu, err := olt.FindOnuBySn(req.SerialNumber)
357 if err != nil {
358 logger.WithFields(log.Fields{
359 "OnuSn": req.SerialNumber,
360 }).Error("Can't get ONU in GetFlows request")
361 return nil, err
362 }
363 for _, flowKey := range onu.Flows {
364 flow := olt.Flows[flowKey]
365 res.Flows = append(res.Flows, &flow)
366 }
367 res.FlowCount = uint32(len(onu.Flows))
368 }
369 return res, nil
370}
371
Anand S Katti09541352020-01-29 15:54:01 +0530372func (s BBSimServer) GetOnuTrafficSchedulers(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONUTrafficSchedulers, error) {
373 olt := devices.GetOLT()
374 ts := bbsim.ONUTrafficSchedulers{}
375
376 onu, err := olt.FindOnuBySn(req.SerialNumber)
377 if err != nil {
378 return &ts, err
379 }
380
381 if onu.TrafficSchedulers != nil {
382 ts.TraffSchedulers = onu.TrafficSchedulers
383 return &ts, nil
384 } else {
385 ts.TraffSchedulers = nil
386 return &ts, nil
387 }
388}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530389
390func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
391 res := &bbsim.Response{}
392 olt := devices.GetOLT()
393 intitalState := onu.InternalState.Current()
394 if onu.InternalState.Current() == "created" || onu.InternalState.Current() == "disabled" {
395 if err := onu.InternalState.Event("initialize"); err != nil {
396 logger.WithFields(log.Fields{
397 "OnuId": onu.ID,
398 "IntfId": onu.PonPortID,
399 "OnuSn": onu.Sn(),
400 }).Errorf("Cannot poweron ONU: %s", err.Error())
401 res.StatusCode = int32(codes.FailedPrecondition)
402 res.Message = err.Error()
403 return res, err
404 }
405 }
406
407 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530408 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530409 SerialNumber: onu.Sn(),
410 Status: "off",
411 }
412
413 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
414 logger.WithFields(log.Fields{
415 "OnuId": onu.ID,
416 "IntfId": onu.PonPortID,
417 "OnuSn": onu.Sn(),
418 }).Errorf("Cannot send LOS: %s", err.Error())
419 res.StatusCode = int32(codes.FailedPrecondition)
420 res.Message = err.Error()
421 return res, err
422 }
423
424 if err := onu.InternalState.Event("discover"); err != nil {
425 logger.WithFields(log.Fields{
426 "OnuId": onu.ID,
427 "IntfId": onu.PonPortID,
428 "OnuSn": onu.Sn(),
429 }).Errorf("Cannot poweron ONU: %s", err.Error())
430 res.StatusCode = int32(codes.FailedPrecondition)
431 res.Message = err.Error()
432 return res, err
433 }
434 // move onu directly to enable state only when its a powercycle case
435 // in case of first time onu poweron onu will be moved to enable on
436 // receiving ActivateOnu request from openolt adapter
437 if intitalState == "disabled" {
438 if err := onu.InternalState.Event("enable"); err != nil {
439 logger.WithFields(log.Fields{
440 "OnuId": onu.ID,
441 "IntfId": onu.PonPortID,
442 "OnuSn": onu.Sn(),
443 }).Errorf("Cannot enable ONU: %s", err.Error())
444 res.StatusCode = int32(codes.FailedPrecondition)
445 res.Message = err.Error()
446 return res, err
447 }
448 }
449
450 res.StatusCode = int32(codes.OK)
451 res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
452
453 return res, nil
454}
455
456func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
457 res := &bbsim.Response{}
458 olt := devices.GetOLT()
459
460 dyingGasp := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530461 AlarmType: "DYING_GASP",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530462 SerialNumber: onu.Sn(),
463 Status: "on",
464 }
465
466 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &dyingGasp, olt); err != nil {
467 logger.WithFields(log.Fields{
468 "OnuId": onu.ID,
469 "IntfId": onu.PonPortID,
470 "OnuSn": onu.Sn(),
471 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
472 res.StatusCode = int32(codes.FailedPrecondition)
473 res.Message = err.Error()
474 return res, err
475 }
476
477 losReq := bbsim.ONUAlarmRequest{
Pragya Arya1d5ffb82020-03-20 18:51:37 +0530478 AlarmType: "ONU_ALARM_LOS",
Pragya Aryabd731ec2020-02-11 16:38:17 +0530479 SerialNumber: onu.Sn(),
480 Status: "on",
481 }
482
483 if err := alarmsim.SimulateOnuAlarm(context.TODO(), &losReq, olt); err != nil {
484 logger.WithFields(log.Fields{
485 "OnuId": onu.ID,
486 "IntfId": onu.PonPortID,
487 "OnuSn": onu.Sn(),
488 }).Errorf("Cannot send LOS: %s", err.Error())
489 res.StatusCode = int32(codes.FailedPrecondition)
490 res.Message = err.Error()
491 return res, err
492 }
493
494 // TODO if it's the last ONU on the PON, then send a PON LOS
495
496 if err := onu.InternalState.Event("disable"); err != nil {
497 logger.WithFields(log.Fields{
498 "OnuId": onu.ID,
499 "IntfId": onu.PonPortID,
500 "OnuSn": onu.Sn(),
501 }).Errorf("Cannot shutdown ONU: %s", err.Error())
502 res.StatusCode = int32(codes.FailedPrecondition)
503 res.Message = err.Error()
504 return res, err
505 }
506
507 res.StatusCode = int32(codes.OK)
508 res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
509
510 return res, nil
511}