blob: 2533fa35287f845add06c9fa821d7b6a215d76d0 [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"
Matteo Scandolof9d43412021-01-12 11:11:34 -080022 "github.com/opencord/bbsim/internal/bbsim/types"
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010023 "github.com/opencord/voltha-protos/v4/go/openolt"
Pragya Arya1d5ffb82020-03-20 18:51:37 +053024
Matteo Scandolo10f965c2019-09-24 10:40:46 -070025 "github.com/opencord/bbsim/api/bbsim"
26 "github.com/opencord/bbsim/internal/bbsim/devices"
27 log "github.com/sirupsen/logrus"
28 "google.golang.org/grpc/codes"
29)
30
31func (s BBSimServer) GetONUs(ctx context.Context, req *bbsim.Empty) (*bbsim.ONUs, error) {
32 olt := devices.GetOLT()
33 onus := bbsim.ONUs{
34 Items: []*bbsim.ONU{},
35 }
36
37 for _, pon := range olt.Pons {
38 for _, o := range pon.Onus {
39 onu := bbsim.ONU{
40 ID: int32(o.ID),
41 SerialNumber: o.Sn(),
42 OperState: o.OperState.Current(),
43 InternalState: o.InternalState.Current(),
44 PonPortID: int32(o.PonPortID),
Matteo Scandolo27428702019-10-11 16:21:16 -070045 PortNo: int32(o.PortNo),
Matteo Scandolo4a036262020-08-17 15:56:13 -070046 Services: convertBBsimServicesToProtoServices(o.Services),
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),
Matteo Scandolo27428702019-10-11 16:21:16 -070069 PortNo: int32(onu.PortNo),
Matteo Scandolo4a036262020-08-17 15:56:13 -070070 Services: convertBBsimServicesToProtoServices(onu.Services),
Matteo Scandolod2ca2c72019-10-04 16:50:22 -070071 }
72 return &res, nil
73}
74
Pragya Aryabd731ec2020-02-11 16:38:17 +053075// ShutdownONU sends DyingGasp indication for specified ONUs and mark ONUs as disabled.
Matteo Scandolo10f965c2019-09-24 10:40:46 -070076func (s BBSimServer) ShutdownONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Anand S Katti09541352020-01-29 15:54:01 +053077 // 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 -070078 // is this the only way to do? Should we address other cases?
79 // Investigate what happens when:
80 // - a fiber is pulled
81 // - ONU malfunction
82 // - ONU shutdown
Matteo Scandolo10f965c2019-09-24 10:40:46 -070083 logger.WithFields(log.Fields{
84 "OnuSn": req.SerialNumber,
85 }).Infof("Received request to shutdown ONU")
86
Pragya Aryabd731ec2020-02-11 16:38:17 +053087 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070088 olt := devices.GetOLT()
89
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070090 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -070091 if err != nil {
92 res.StatusCode = int32(codes.NotFound)
93 res.Message = err.Error()
94 return res, err
95 }
96
Pragya Aryabd731ec2020-02-11 16:38:17 +053097 return handleShutdownONU(onu)
98}
Matteo Scandolo10f965c2019-09-24 10:40:46 -070099
Pragya Aryabd731ec2020-02-11 16:38:17 +0530100// ShutdownONUsOnPON sends DyingGasp indication for all ONUs under specified PON port
101func (s BBSimServer) ShutdownONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
102 logger.WithFields(log.Fields{
103 "IntfId": req.PonPortId,
104 }).Infof("Received request to shutdown all ONUs on PON")
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800105
Pragya Aryabd731ec2020-02-11 16:38:17 +0530106 res := &bbsim.Response{}
107 olt := devices.GetOLT()
108 pon, _ := olt.GetPonById(req.PonPortId)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800109
Pragya Aryabd731ec2020-02-11 16:38:17 +0530110 go func() {
111 for _, onu := range pon.Onus {
112 res, _ = handleShutdownONU(onu)
113 }
114 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700115 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530116 res.Message = fmt.Sprintf("Request accepted for shutdown all ONUs on PON port %d", pon.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700117
118 return res, nil
119}
120
Pragya Aryabd731ec2020-02-11 16:38:17 +0530121// ShutdownAllONUs sends DyingGasp indication for all ONUs and mark ONUs as disabled.
122func (s BBSimServer) ShutdownAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
123 logger.Infof("Received request to shutdown all ONUs")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700124 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530125 olt := devices.GetOLT()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700126
Pragya Aryabd731ec2020-02-11 16:38:17 +0530127 go func() {
128 for _, pon := range olt.Pons {
129 for _, onu := range pon.Onus {
130 res, _ = handleShutdownONU(onu)
131 }
132 }
133 }()
134 res.StatusCode = int32(codes.OK)
135 res.Message = fmt.Sprintf("Request Accepted for shutdown all ONUs in OLT %d", olt.ID)
136
137 return res, nil
138}
139
140// PoweronONU simulates ONU power on and start sending discovery indications to VOLTHA
141func (s BBSimServer) PoweronONU(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700142 logger.WithFields(log.Fields{
143 "OnuSn": req.SerialNumber,
144 }).Infof("Received request to poweron ONU")
145
Pragya Aryabd731ec2020-02-11 16:38:17 +0530146 res := &bbsim.Response{}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700147 olt := devices.GetOLT()
148
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700149 onu, err := olt.FindOnuBySn(req.SerialNumber)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700150 if err != nil {
151 res.StatusCode = int32(codes.NotFound)
152 res.Message = err.Error()
153 return res, err
154 }
155
Pragya Arya2225f202020-01-29 18:05:01 +0530156 pon, _ := olt.GetPonById(onu.PonPortID)
157 if pon.InternalState.Current() != "enabled" {
158 err := fmt.Errorf("PON port %d not enabled", onu.PonPortID)
159 logger.WithFields(log.Fields{
160 "OnuId": onu.ID,
161 "IntfId": onu.PonPortID,
162 "OnuSn": onu.Sn(),
163 }).Errorf("Cannot poweron ONU: %s", err.Error())
164
165 res.StatusCode = int32(codes.FailedPrecondition)
166 res.Message = err.Error()
167 return res, err
168 }
169
Pragya Aryabd731ec2020-02-11 16:38:17 +0530170 return handlePoweronONU(onu)
171}
172
173// PoweronONUsOnPON simulates ONU power on for all ONUs under specified PON port
174func (s BBSimServer) PoweronONUsOnPON(ctx context.Context, req *bbsim.PONRequest) (*bbsim.Response, error) {
175 logger.WithFields(log.Fields{
176 "IntfId": req.PonPortId,
177 }).Infof("Received request to poweron all ONUs on PON")
178
179 res := &bbsim.Response{}
180 olt := devices.GetOLT()
181
182 pon, _ := olt.GetPonById(req.PonPortId)
183 if pon.InternalState.Current() != "enabled" {
184 err := fmt.Errorf("PON port %d not enabled", pon.ID)
185 logger.WithFields(log.Fields{
186 "IntfId": pon.ID,
187 }).Errorf("Cannot poweron ONUs on PON: %s", err.Error())
188
189 res.StatusCode = int32(codes.FailedPrecondition)
190 res.Message = err.Error()
191 return res, err
192 }
193
194 go func() {
195 for _, onu := range pon.Onus {
196 res, _ = handlePoweronONU(onu)
Pragya Arya2225f202020-01-29 18:05:01 +0530197 }
Pragya Aryabd731ec2020-02-11 16:38:17 +0530198 }()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700199 res.StatusCode = int32(codes.OK)
Pragya Aryabd731ec2020-02-11 16:38:17 +0530200 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs on PON port %d", pon.ID)
201
202 return res, nil
203}
204
205// PoweronAllONUs simulates ONU power on for all ONUs on all PON ports
206func (s BBSimServer) PoweronAllONUs(context.Context, *bbsim.Empty) (*bbsim.Response, error) {
207 logger.Infof("Received request to poweron all ONUs")
208
209 res := &bbsim.Response{}
210 olt := devices.GetOLT()
211
212 go func() {
213 for _, pon := range olt.Pons {
214 if pon.InternalState.Current() == "enabled" {
215 for _, onu := range pon.Onus {
216 res, _ = handlePoweronONU(onu)
217 }
218 }
219 }
220 }()
221 res.StatusCode = int32(codes.OK)
222 res.Message = fmt.Sprintf("Request Accepted for power on all ONUs in OLT %d", olt.ID)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700223
224 return res, nil
225}
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700226
Arjun E K57a7fcb2020-01-30 06:44:45 +0000227func (s BBSimServer) ChangeIgmpState(ctx context.Context, req *bbsim.IgmpRequest) (*bbsim.Response, error) {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700228
229 // TODO check that the ONU is enabled and the services are initialized before changing the state
230
Arjun E K57a7fcb2020-01-30 06:44:45 +0000231 res := &bbsim.Response{}
232
233 logger.WithFields(log.Fields{
Onur Kalinagac9f9faca2021-01-21 14:04:34 +0000234 "OnuSn": req.OnuReq.SerialNumber,
235 "subAction": req.SubActionVal,
236 "GroupAddress": req.GroupAddress,
Arjun E K57a7fcb2020-01-30 06:44:45 +0000237 }).Infof("Received igmp request for ONU")
238
239 olt := devices.GetOLT()
240 onu, err := olt.FindOnuBySn(req.OnuReq.SerialNumber)
241
242 if err != nil {
243 res.StatusCode = int32(codes.NotFound)
244 res.Message = err.Error()
245 fmt.Println("ONU not found for sending igmp packet.")
246 return res, err
247 } else {
248 event := ""
249 switch req.SubActionVal {
250 case bbsim.SubActionTypes_JOIN:
251 event = "igmp_join_start"
252 case bbsim.SubActionTypes_LEAVE:
253 event = "igmp_leave"
Anand S Katti09541352020-01-29 15:54:01 +0530254 case bbsim.SubActionTypes_JOINV3:
255 event = "igmp_join_startv3"
Arjun E K57a7fcb2020-01-30 06:44:45 +0000256 }
257
Matteo Scandolo618a6582020-09-09 12:21:29 -0700258 errors := []string{}
259 startedOn := []string{}
260 success := true
261
262 for _, s := range onu.Services {
263 service := s.(*devices.Service)
264 if service.NeedsIgmp {
265
266 logger.WithFields(log.Fields{
267 "OnuId": onu.ID,
268 "IntfId": onu.PonPortID,
269 "OnuSn": onu.Sn(),
270 "Service": service.Name,
271 }).Debugf("Sending %s event on Service %s", event, service.Name)
272
Matteo Scandolof9d43412021-01-12 11:11:34 -0800273 if err := service.IGMPState.Event(event, types.IgmpMessage{GroupAddress: req.GroupAddress}); err != nil {
Matteo Scandolo618a6582020-09-09 12:21:29 -0700274 logger.WithFields(log.Fields{
275 "OnuId": onu.ID,
276 "IntfId": onu.PonPortID,
277 "OnuSn": onu.Sn(),
278 "Service": service.Name,
279 }).Errorf("IGMP request failed: %s", err.Error())
280 errors = append(errors, fmt.Sprintf("%s: %s", service.Name, err.Error()))
281 success = false
282 }
283 startedOn = append(startedOn, service.Name)
284 }
285 }
286
287 if success {
288 res.StatusCode = int32(codes.OK)
289 res.Message = fmt.Sprintf("Authentication restarted on Services %s for ONU %s.",
290 fmt.Sprintf("%v", startedOn), onu.Sn())
291 } else {
Arjun E K57a7fcb2020-01-30 06:44:45 +0000292 res.StatusCode = int32(codes.FailedPrecondition)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700293 res.Message = fmt.Sprintf("%v", errors)
Arjun E K57a7fcb2020-01-30 06:44:45 +0000294 }
295 }
296
297 return res, nil
298}
299
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700300func (s BBSimServer) RestartEapol(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
301 res := &bbsim.Response{}
302
303 logger.WithFields(log.Fields{
304 "OnuSn": req.SerialNumber,
305 }).Infof("Received request to restart authentication ONU")
306
307 olt := devices.GetOLT()
308
309 onu, err := olt.FindOnuBySn(req.SerialNumber)
310
311 if err != nil {
312 res.StatusCode = int32(codes.NotFound)
313 res.Message = err.Error()
314 return res, err
315 }
316
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700317 errors := []string{}
Matteo Scandolo618a6582020-09-09 12:21:29 -0700318 startedOn := []string{}
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700319 success := true
320
321 for _, s := range onu.Services {
322 service := s.(*devices.Service)
323 if service.NeedsEapol {
324 if err := service.EapolState.Event("start_auth"); err != nil {
325 logger.WithFields(log.Fields{
326 "OnuId": onu.ID,
327 "IntfId": onu.PonPortID,
328 "OnuSn": onu.Sn(),
329 "Service": service.Name,
330 }).Errorf("Cannot restart authenticaton for Service: %s", err.Error())
331 errors = append(errors, fmt.Sprintf("%s: %s", service.Name, err.Error()))
332 success = false
333 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700334 startedOn = append(startedOn, service.Name)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700335 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700336 }
337
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700338 if success {
339 res.StatusCode = int32(codes.OK)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700340 res.Message = fmt.Sprintf("Authentication restarted on Services %s for ONU %s.",
341 fmt.Sprintf("%v", startedOn), onu.Sn())
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700342 } else {
343 res.StatusCode = int32(codes.FailedPrecondition)
344 res.Message = fmt.Sprintf("%v", errors)
345 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700346
347 return res, nil
348}
349
350func (s BBSimServer) RestartDhcp(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Response, error) {
351 res := &bbsim.Response{}
352
353 logger.WithFields(log.Fields{
354 "OnuSn": req.SerialNumber,
355 }).Infof("Received request to restart DHCP on ONU")
356
357 olt := devices.GetOLT()
358
359 onu, err := olt.FindOnuBySn(req.SerialNumber)
360
361 if err != nil {
362 res.StatusCode = int32(codes.NotFound)
363 res.Message = err.Error()
364 return res, err
365 }
366
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700367 errors := []string{}
Matteo Scandolo618a6582020-09-09 12:21:29 -0700368 startedOn := []string{}
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700369 success := true
370
371 for _, s := range onu.Services {
372 service := s.(*devices.Service)
373 if service.NeedsDhcp {
374
375 if err := service.DHCPState.Event("start_dhcp"); err != nil {
376 logger.WithFields(log.Fields{
377 "OnuId": onu.ID,
378 "IntfId": onu.PonPortID,
379 "OnuSn": onu.Sn(),
380 "Service": service.Name,
381 }).Errorf("Cannot restart DHCP for Service: %s", err.Error())
382 errors = append(errors, fmt.Sprintf("%s: %s", service.Name, err.Error()))
383 success = false
384 }
Matteo Scandolo618a6582020-09-09 12:21:29 -0700385 startedOn = append(startedOn, service.Name)
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700386 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700387 }
388
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700389 if success {
390 res.StatusCode = int32(codes.OK)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700391 res.Message = fmt.Sprintf("DHCP restarted on Services %s for ONU %s.",
392 fmt.Sprintf("%v", startedOn), onu.Sn())
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700393 } else {
394 res.StatusCode = int32(codes.FailedPrecondition)
395 res.Message = fmt.Sprintf("%v", errors)
396 }
Matteo Scandoloe383d5d2019-10-25 14:47:27 -0700397
398 return res, nil
399}
Anand S Katti09541352020-01-29 15:54:01 +0530400
Pragya Arya8bdb4532020-03-02 17:08:09 +0530401// GetFlows for OLT/ONUs
402func (s BBSimServer) GetFlows(ctx context.Context, req *bbsim.ONURequest) (*bbsim.Flows, error) {
403 logger.WithFields(log.Fields{
404 "OnuSn": req.SerialNumber,
405 }).Info("Received GetFlows request")
406
407 olt := devices.GetOLT()
408 res := &bbsim.Flows{}
409
410 if req.SerialNumber == "" {
Andrea Campanellabe8e12f2020-12-14 18:43:41 +0100411 olt.Flows.Range(func(flowKey, flow interface{}) bool {
412 flowObj := flow.(openolt.Flow)
413 res.Flows = append(res.Flows, &flowObj)
414 return true
415 })
416 res.FlowCount = uint32(len(res.Flows))
Pragya Arya8bdb4532020-03-02 17:08:09 +0530417 } else {
418 onu, err := olt.FindOnuBySn(req.SerialNumber)
419 if err != nil {
420 logger.WithFields(log.Fields{
421 "OnuSn": req.SerialNumber,
422 }).Error("Can't get ONU in GetFlows request")
423 return nil, err
424 }
425 for _, flowKey := range onu.Flows {
Andrea Campanellabe8e12f2020-12-14 18:43:41 +0100426 flow, _ := olt.Flows.Load(flowKey)
427 flowObj := flow.(openolt.Flow)
428 res.Flows = append(res.Flows, &flowObj)
Pragya Arya8bdb4532020-03-02 17:08:09 +0530429 }
430 res.FlowCount = uint32(len(onu.Flows))
431 }
432 return res, nil
433}
434
Anand S Katti09541352020-01-29 15:54:01 +0530435func (s BBSimServer) GetOnuTrafficSchedulers(ctx context.Context, req *bbsim.ONURequest) (*bbsim.ONUTrafficSchedulers, error) {
436 olt := devices.GetOLT()
437 ts := bbsim.ONUTrafficSchedulers{}
438
439 onu, err := olt.FindOnuBySn(req.SerialNumber)
440 if err != nil {
441 return &ts, err
442 }
443
444 if onu.TrafficSchedulers != nil {
445 ts.TraffSchedulers = onu.TrafficSchedulers
446 return &ts, nil
447 } else {
448 ts.TraffSchedulers = nil
449 return &ts, nil
450 }
451}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530452
453func handlePoweronONU(onu *devices.Onu) (*bbsim.Response, error) {
454 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530455
Matteo Scandolof9d43412021-01-12 11:11:34 -0800456 if err := onu.HandlePowerOnONU(); err != nil {
Pragya Aryabd731ec2020-02-11 16:38:17 +0530457 res.StatusCode = int32(codes.FailedPrecondition)
458 res.Message = err.Error()
459 return res, err
460 }
461
Pragya Aryabd731ec2020-02-11 16:38:17 +0530462 res.StatusCode = int32(codes.OK)
463 res.Message = fmt.Sprintf("ONU %s successfully powered on.", onu.Sn())
464
465 return res, nil
466}
467
468func handleShutdownONU(onu *devices.Onu) (*bbsim.Response, error) {
469 res := &bbsim.Response{}
Pragya Aryabd731ec2020-02-11 16:38:17 +0530470
Matteo Scandolof9d43412021-01-12 11:11:34 -0800471 if err := onu.HandleShutdownONU(); err != nil {
Pragya Aryabd731ec2020-02-11 16:38:17 +0530472 res.StatusCode = int32(codes.FailedPrecondition)
473 res.Message = err.Error()
474 return res, err
475 }
476
477 res.StatusCode = int32(codes.OK)
478 res.Message = fmt.Sprintf("ONU %s successfully shut down.", onu.Sn())
479
480 return res, nil
481}