blob: 58c7fab4ac9d345d4d2c15ef378c4138c27cffc9 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29: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
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
20 "context"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "encoding/hex"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "fmt"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010026 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020027
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000028 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
29 "github.com/opencord/bbsim/internal/bbsim/types"
30 omcilib "github.com/opencord/bbsim/internal/common/omci"
31 "github.com/opencord/voltha-protos/v4/go/ext/config"
32
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070033 "github.com/google/gopacket"
34 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070035 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070036 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010037 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070038 common_protos "github.com/opencord/voltha-protos/v4/go/common"
39 "github.com/opencord/voltha-protos/v4/go/openolt"
40 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070041 log "github.com/sirupsen/logrus"
42 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053043 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010044 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053045 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070046)
47
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070048var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070049 "module": "OLT",
50})
51
Matteo Scandolocedde462021-03-09 17:37:16 -080052const (
53 onuIdStart = 1
54 onuIdEnd = 127
55 allocIdStart = 1024
56 allocIdEnd = 16383
57 gemportIdStart = 1024
58 gemportIdEnd = 65535
59 flowIdStart = 1
60 flowIdEnd = 65535
61)
62
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070063type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000064 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000065 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000066
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070067 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053068 ID int
69 SerialNumber string
70 NumNni int
71 NumPon int
72 NumOnuPerPon int
73 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080074 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070075 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010076 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053077 Delay int
78 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053079 EventChannel chan common.Event
80 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053081 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080082 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070083
Matteo Scandolo27428702019-10-11 16:21:16 -070084 Pons []*PonPort
85 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070086
87 // OLT Attributes
88 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000089
90 enableContext context.Context
91 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053092
Matteo Scandolo4a036262020-08-17 15:56:13 -070093 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053094 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080095
96 // Allocated Resources
97 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000098 AllocIDsLock sync.RWMutex
99 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
100 GemPortIDsLock sync.RWMutex
101 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
102 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700103}
104
Matteo Scandolo27428702019-10-11 16:21:16 -0700105var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700106
Matteo Scandolo27428702019-10-11 16:21:16 -0700107func GetOLT() *OltDevice {
108 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700109}
110
Matteo Scandolo4a036262020-08-17 15:56:13 -0700111func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700112 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530113 "ID": options.Olt.ID,
114 "NumNni": options.Olt.NniPorts,
115 "NumPon": options.Olt.PonPorts,
116 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700117 }).Debug("CreateOLT")
118
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700119 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530120 ID: options.Olt.ID,
121 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700122 OperState: getOperStateFSM(func(e *fsm.Event) {
123 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
124 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800125 NumNni: int(options.Olt.NniPorts),
126 NumPon: int(options.Olt.PonPorts),
127 NumOnuPerPon: int(options.Olt.OnusPonPort),
128 Pons: []*PonPort{},
129 Nnis: []*NniPort{},
130 Delay: options.BBSim.Delay,
131 enablePerf: options.BBSim.EnablePerf,
132 PublishEvents: options.BBSim.Events,
133 PortStatsInterval: options.Olt.PortStatsInterval,
134 dhcpServer: dhcp.NewDHCPServer(),
135 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800136 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
137 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000138 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139 }
140
Pragya Arya996a0892020-03-09 21:47:52 +0530141 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530142 olt.ControlledActivation = val
143 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700144 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530145 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
146 olt.ControlledActivation = Default
147 }
148
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700150 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700151 olt.InternalState = fsm.NewFSM(
152 "created",
153 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800154 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100155 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700156 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700157 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800158 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 },
160 fsm.Callbacks{
161 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700162 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700163 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100164 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800165 "enter_deleted": func(e *fsm.Event) {
166 // remove all the resource allocations
167 olt.clearAllResources()
168 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700169 },
170 )
171
Shrey Baid688b4242020-07-10 20:40:10 +0530172 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700173 // create NNI Port
174 nniPort, err := CreateNNI(&olt)
175 if err != nil {
176 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
177 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700178
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700179 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700180 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700181
Matteo Scandolo4a036262020-08-17 15:56:13 -0700182 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700183 nextCtag := map[string]int{}
184 nextStag := map[string]int{}
185
Matteo Scandolo4747d292019-08-05 11:50:18 -0700186 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700187 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800188
189 // initialize the resource maps for every PON Ports
190 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
191 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
192
Matteo Scandolo4a036262020-08-17 15:56:13 -0700193 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700194
Matteo Scandolo4a036262020-08-17 15:56:13 -0700195 // create ONU devices
196 for j := 0; j < olt.NumOnuPerPon; j++ {
197 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700198 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700199
Matteo Scandolo4a036262020-08-17 15:56:13 -0700200 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700201 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700203 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100204
Shrey Baid688b4242020-07-10 20:40:10 +0530205 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700206 if err := olt.InternalState.Event("initialize"); err != nil {
207 log.Errorf("Error initializing OLT: %v", err)
208 return nil
209 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210 }
211
Pragya Arya324337e2020-02-20 14:35:08 +0530212 if olt.PublishEvents {
213 log.Debugf("BBSim event publishing is enabled")
214 // Create a channel to write event messages
215 olt.EventChannel = make(chan common.Event, 100)
216 }
217
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700218 return &olt
219}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700220
Shrey Baid688b4242020-07-10 20:40:10 +0530221func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100222
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000223 if o.OltServer == nil {
224 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800226 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100227 }
228
229 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800230 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100232 // FIXME we are assuming we have only one NNI
233 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800234 // NOTE we want to make sure the state is down when we initialize the OLT,
235 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
236 // in-band management
237 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100238 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800239
240 for ponId := range o.Pons {
241 // initialize the resource maps for every PON Ports
242 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
243 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
244 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700245}
246
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800247func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100248
Matteo Scandolo96f89192021-03-12 13:17:26 -0800249 o.PreviouslyConnected = false
250
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700251 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700252 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800253
254 oltLogger.WithFields(log.Fields{
255 "oltId": o.ID,
256 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
257
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700258 if o.InternalState.Is("enabled") {
259 oltLogger.WithFields(log.Fields{
260 "oltId": o.ID,
261 }).Info("This is an OLT soft reboot")
262 softReboot = true
263 }
264
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800265 // transition internal state to deleted
266 if err := o.InternalState.Event("delete"); err != nil {
267 oltLogger.WithFields(log.Fields{
268 "oltId": o.ID,
269 }).Errorf("Error deleting OLT: %v", err)
270 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271 }
272
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700273 if softReboot {
274 for _, pon := range o.Pons {
275 if pon.InternalState.Current() == "enabled" {
276 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800277 msg := types.Message{
278 Type: types.PonIndication,
279 Data: types.PonIndicationMessage{
280 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700281 PonPortID: pon.ID,
282 },
283 }
284 o.channel <- msg
285 }
286
287 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800288 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700289 }
290 }
291 } else {
292 // PONs are already handled in the Disable call
293 for _, pon := range olt.Pons {
294 // ONUs are not automatically disabled when a PON goes down
295 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
296 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800297 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700298 }
Pragya Arya2225f202020-01-29 18:05:01 +0530299 }
300 }
301
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700302 time.Sleep(1 * time.Second) // we need to give the OLT the time to respond to all the pending gRPC request before stopping the server
303 o.StopOltServer()
304
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100305 // terminate the OLT's processOltMessages go routine
306 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700307
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700308 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100309 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310
311 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800312 oltLogger.WithFields(log.Fields{
313 "oltId": o.ID,
314 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100315 return err
316 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800317 oltLogger.WithFields(log.Fields{
318 "oltId": o.ID,
319 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320 return nil
321}
322
323// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800324func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700325 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700326 lis, err := net.Listen("tcp", address)
327 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700328 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700329 }
330 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100331
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332 openolt.RegisterOpenoltServer(grpcServer, o)
333
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100334 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700335
Shrey Baid688b4242020-07-10 20:40:10 +0530336 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100337 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700338
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100339 return grpcServer, nil
340}
341
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800342// StartOltServer will create the grpc server that VOLTHA uses
343// to communicate with the device
344func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
345 oltServer, err := o.newOltServer()
346 if err != nil {
347 oltLogger.WithFields(log.Fields{
348 "err": err,
349 }).Error("Cannot OLT gRPC server")
350 return nil, err
351 }
352 return oltServer, nil
353}
354
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100355// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800356func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000357 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800358 oltLogger.WithFields(log.Fields{
359 "oltId": o.SerialNumber,
360 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000361 o.OltServer.Stop()
362 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700363 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700364}
365
366// Device Methods
367
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100368// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530369func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700370 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530371 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700372
David Bainbridge103cf022019-12-16 20:11:35 +0000373 // If enabled has already been called then an enabled context has
374 // been created. If this is the case then we want to cancel all the
375 // proessing loops associated with that enable before we recreate
376 // new ones
377 o.Lock()
378 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700379 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000380 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530381 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700382 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000383 }
384 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
385 o.Unlock()
386
Matteo Scandolo4747d292019-08-05 11:50:18 -0700387 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700388
Matteo Scandolo4a036262020-08-17 15:56:13 -0700389 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530390
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100391 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700392 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000393 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394
395 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800396 oltMsg := types.Message{
397 Type: types.OltIndication,
398 Data: types.OltIndicationMessage{
399 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700400 },
401 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100402 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403
404 // send NNI Port Indications
405 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800406 msg := types.Message{
407 Type: types.NniIndication,
408 Data: types.NniIndicationMessage{
409 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700410 NniPortID: nni.ID,
411 },
412 }
413 o.channel <- msg
414 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100415
Shrey Baid688b4242020-07-10 20:40:10 +0530416 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530417 for _, pon := range o.Pons {
418 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800419 msg := types.Message{
420 Type: types.PonIndication,
421 Data: types.PonIndicationMessage{
422 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530423 PonPortID: pon.ID,
424 },
425 }
426 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000427 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700428 // when the enableContext was canceled the ONUs stopped listening on the channel
429 for _, onu := range pon.Onus {
430 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
431
432 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700433 for _, uni := range onu.UniPorts {
434 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700435 }
436 }
Pragya Arya2225f202020-01-29 18:05:01 +0530437 }
438 } else {
439
440 // 1. controlledActivation == Default: Send both PON and ONUs indications
441 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
442
443 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
444 // send PON Port indications
445 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800446 msg := types.Message{
447 Type: types.PonIndication,
448 Data: types.PonIndicationMessage{
449 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530450 PonPortID: pon.ID,
451 },
452 }
453 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700454 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700455 }
456 }
457
Pragya Arya996a0892020-03-09 21:47:52 +0530458 if !o.enablePerf {
459 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700460 wg.Add(1)
461 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530462 }
463
Matteo Scandolo4747d292019-08-05 11:50:18 -0700464 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700465 oltLogger.WithFields(log.Fields{
466 "stream": stream,
467 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700468}
469
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700470func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530471 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700472
473loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530474 for {
475 select {
476 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
477 // send NNI port stats
478 for _, port := range o.Nnis {
479 incrementStat := true
480 if port.OperState.Current() == "down" {
481 incrementStat = false
482 }
483 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700484 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530485 }
486
487 // send PON port stats
488 for _, port := range o.Pons {
489 incrementStat := true
490 // do not increment port stats if PON port is down or no ONU is activated on PON port
491 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
492 incrementStat = false
493 }
494 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700495 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530496 }
497 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700498 oltLogger.Debug("Stop sending port stats")
499 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530500 }
Pragya Arya996a0892020-03-09 21:47:52 +0530501 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700502 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530503}
504
Matteo Scandolo4747d292019-08-05 11:50:18 -0700505// Helpers method
506
Matteo Scandolof9d43412021-01-12 11:11:34 -0800507func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
508
509 switch interfaceType {
510 case "nni":
511 if !o.HasNni(interfaceId) {
512 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
513 }
514
515 case "pon":
516 if !o.HasPon(interfaceId) {
517 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
518 }
519 }
520
521 alarmIndication := &openolt.AlarmIndication{
522 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
523 Status: alarmStatus,
524 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
525 }},
526 }
527
528 msg := types.Message{
529 Type: types.AlarmIndication,
530 Data: alarmIndication,
531 }
532
533 o.channel <- msg
534
535 return nil
536}
537
538func (o *OltDevice) HasNni(id uint32) bool {
539 for _, intf := range o.Nnis {
540 if intf.ID == id {
541 return true
542 }
543 }
544 return false
545}
546
547func (o *OltDevice) HasPon(id uint32) bool {
548 for _, intf := range o.Pons {
549 if intf.ID == id {
550 return true
551 }
552 }
553 return false
554}
555
Shrey Baid688b4242020-07-10 20:40:10 +0530556func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700557 for _, pon := range o.Pons {
558 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700559 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560 }
561 }
Shrey Baid688b4242020-07-10 20:40:10 +0530562 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700563}
564
Shrey Baid688b4242020-07-10 20:40:10 +0530565func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700566 for _, nni := range o.Nnis {
567 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700568 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700569 }
570 }
Shrey Baid688b4242020-07-10 20:40:10 +0530571 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572}
573
Scott Baker41724b82020-01-21 19:54:53 -0800574func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
575 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
576 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
577 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
578 return
579 }
580
581 oltLogger.WithFields(log.Fields{
582 "AlarmIndication": alarmInd,
583 }).Debug("Sent Indication_AlarmInd")
584}
585
Matteo Scandolof9d43412021-01-12 11:11:34 -0800586func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
588 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700589 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800590 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700591 }
592
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700593 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594 "OperState": msg.OperState,
595 }).Debug("Sent Indication_OltInd")
596}
597
Matteo Scandolof9d43412021-01-12 11:11:34 -0800598func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800600 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800601 if err := nni.OperState.Event("enable"); err != nil {
602 log.WithFields(log.Fields{
603 "Type": nni.Type,
604 "IntfId": nni.ID,
605 "OperState": nni.OperState.Current(),
606 }).Errorf("Can't move NNI Port to enabled state: %v", err)
607 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800608 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800609 if err := nni.OperState.Event("disable"); err != nil {
610 log.WithFields(log.Fields{
611 "Type": nni.Type,
612 "IntfId": nni.ID,
613 "OperState": nni.OperState.Current(),
614 }).Errorf("Can't move NNI Port to disable state: %v", err)
615 }
616 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700617 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700618 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700619 Type: nni.Type,
620 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700621 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700622 }}
623
624 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700625 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800626 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700627 }
628
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700629 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700630 "Type": nni.Type,
631 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700633 }).Debug("Sent Indication_IntfOperInd for NNI")
634}
635
Pragya Arya2225f202020-01-29 18:05:01 +0530636func (o *OltDevice) sendPonIndication(ponPortID uint32) {
637
Matteo Scandolo4a036262020-08-17 15:56:13 -0700638 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530639 pon, _ := o.GetPonById(ponPortID)
640 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700641 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700642 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700643 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }}
645
646 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700647 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800648 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649 }
650
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700652 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700653 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700654 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655
Pragya Arya2225f202020-01-29 18:05:01 +0530656 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700657 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700658 Type: pon.Type,
659 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700660 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700661 }}
662
663 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700664 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800665 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 }
667
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700668 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700669 "Type": pon.Type,
670 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700671 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700672 }).Debug("Sent Indication_IntfOperInd for PON")
673}
674
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700675func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530676 if o.InternalState.Current() == "enabled" {
677 oltLogger.WithFields(log.Fields{
678 "Type": portType,
679 "IntfId": portID,
680 }).Trace("Sending port stats")
681 stats.IntfId = InterfaceIDToPortNo(portID, portType)
682 data := &openolt.Indication_PortStats{
683 PortStats: stats,
684 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700685
Shrey Baid55f328c2020-07-07 19:20:42 +0530686 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
687 oltLogger.Errorf("Failed to send PortStats: %v", err)
688 return
689 }
Pragya Arya996a0892020-03-09 21:47:52 +0530690 }
691}
692
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100693// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700694func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
695 oltLogger.WithFields(log.Fields{
696 "stream": stream,
697 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000698 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700699
David Bainbridge103cf022019-12-16 20:11:35 +0000700loop:
701 for {
702 select {
703 case <-ctx.Done():
704 oltLogger.Debug("OLT Indication processing canceled via context")
705 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700706 // do not terminate this loop if the stream is closed,
707 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
708 //case <-stream.Context().Done():
709 // oltLogger.Debug("OLT Indication processing canceled via stream context")
710 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000711 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700712 if !ok {
713 if ctx.Err() != nil {
714 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
715 }
716 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000717 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700718 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700719
David Bainbridge103cf022019-12-16 20:11:35 +0000720 oltLogger.WithFields(log.Fields{
721 "oltId": o.ID,
722 "messageType": message.Type,
723 }).Trace("Received message")
724
725 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800726 case types.OltIndication:
727 msg, _ := message.Data.(types.OltIndicationMessage)
728 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530729 _ = o.InternalState.Event("enable")
730 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800731 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530732 _ = o.InternalState.Event("disable")
733 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000734 }
735 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800736 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800737 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
738 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800739 case types.NniIndication:
740 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000741 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800742 case types.PonIndication:
743 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530744 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800745 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530746 if err := pon.OperState.Event("enable"); err != nil {
747 oltLogger.WithFields(log.Fields{
748 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800749 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530750 }).Error("Can't Enable Oper state for PON Port")
751 }
752 if err := pon.InternalState.Event("enable"); err != nil {
753 oltLogger.WithFields(log.Fields{
754 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800755 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530756 }).Error("Can't Enable Internal state for PON Port")
757 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800758 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530759 if err := pon.OperState.Event("disable"); err != nil {
760 oltLogger.WithFields(log.Fields{
761 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800762 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530763 }).Error("Can't Disable Oper state for PON Port")
764 }
765 if err := pon.InternalState.Event("disable"); err != nil {
766 oltLogger.WithFields(log.Fields{
767 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800768 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530769 }).Error("Can't Disable Internal state for PON Port")
770 }
Pragya Arya2225f202020-01-29 18:05:01 +0530771 }
David Bainbridge103cf022019-12-16 20:11:35 +0000772 default:
773 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
774 }
775 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700776 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100777 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700778 oltLogger.WithFields(log.Fields{
779 "stream": stream,
780 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700781}
782
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700783// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530784func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700785 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700786 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700787 for _, pon := range o.Pons {
788 for _, onu := range pon.Onus {
789 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700790 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700791 }
792 }
793 }
794
Shrey Baid688b4242020-07-10 20:40:10 +0530795 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700796}
797
William Kurkian9dadc5b2019-10-22 13:51:57 -0400798// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530799func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700800 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400801 // memoizing it will remove the bottleneck
802 for _, pon := range o.Pons {
803 if pon.ID == intfId {
804 for _, onu := range pon.Onus {
805 if onu.ID == onuId {
806 return onu, nil
807 }
808 }
809 }
810 }
Shrey Baid688b4242020-07-10 20:40:10 +0530811 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400812}
813
Matteo Scandolo4a036262020-08-17 15:56:13 -0700814// returns a Service with a given Mac Address
815func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700816 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700817 // memoizing it will remove the bottleneck
818 for _, pon := range o.Pons {
819 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700820 s, err := onu.findServiceByMacAddress(mac)
821 if err == nil {
822 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700823 }
824 }
825 }
826
Matteo Scandolo4a036262020-08-17 15:56:13 -0700827 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700828}
829
Matteo Scandolo4747d292019-08-05 11:50:18 -0700830// GRPC Endpoints
831
Shrey Baid688b4242020-07-10 20:40:10 +0530832func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700833
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700834 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800835
Matteo Scandolo8a574812021-05-20 15:18:53 -0700836 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800837 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
838 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
839
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700840 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700841
842 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
843 oltLogger.WithFields(log.Fields{
844 "OnuSn": _onu.Sn(),
845 }).Info("Received ActivateOnu call from VOLTHA")
846
William Kurkian0418bc82019-11-06 12:16:24 -0500847 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700848
Matteo Scandolocedde462021-03-09 17:37:16 -0800849 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700850 oltLogger.WithFields(log.Fields{
851 "IntfId": _onu.PonPortID,
852 "OnuSn": _onu.Sn(),
853 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800854 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700855 }
856
857 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
858
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700859 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700860}
861
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800862func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700863 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700864 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700865}
866
Shrey Baid688b4242020-07-10 20:40:10 +0530867func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530868 oltLogger.WithFields(log.Fields{
869 "IntfId": onu.IntfId,
870 "OnuId": onu.OnuId,
871 }).Info("Received DeleteOnu call from VOLTHA")
872
873 pon, err := o.GetPonById(onu.IntfId)
874 if err != nil {
875 oltLogger.WithFields(log.Fields{
876 "OnuId": onu.OnuId,
877 "IntfId": onu.IntfId,
878 "err": err,
879 }).Error("Can't find PonPort")
880 }
881 _onu, err := pon.GetOnuById(onu.OnuId)
882 if err != nil {
883 oltLogger.WithFields(log.Fields{
884 "OnuId": onu.OnuId,
885 "IntfId": onu.IntfId,
886 "err": err,
887 }).Error("Can't find Onu")
888 }
889
Matteo Scandolocedde462021-03-09 17:37:16 -0800890 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530891 oltLogger.WithFields(log.Fields{
892 "IntfId": _onu.PonPortID,
893 "OnuSn": _onu.Sn(),
894 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800895 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530896 }
897
Hardik Windlassad790cb2020-06-17 21:26:22 +0530898 // ONU Re-Discovery
899 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530900 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530901 }
902
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700903 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700904}
905
Shrey Baid688b4242020-07-10 20:40:10 +0530906func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700907 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800908 oltLogger.WithFields(log.Fields{
909 "oltId": o.ID,
910 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530911 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800912
Matteo Scandolo401503a2019-12-11 14:48:14 -0800913 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530914 if pon.InternalState.Current() == "enabled" {
915 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800916 msg := types.Message{
917 Type: types.PonIndication,
918 Data: types.PonIndicationMessage{
919 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530920 PonPortID: pon.ID,
921 },
922 }
923 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800924 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800925 }
926
Matteo Scandolo401503a2019-12-11 14:48:14 -0800927 // Note that we are not disabling the NNI as the real OLT does not.
928 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800929
930 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800931 oltMsg := types.Message{
932 Type: types.OltIndication,
933 Data: types.OltIndicationMessage{
934 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700935 },
936 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100937 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700938
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700939 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700940}
941
Shrey Baid688b4242020-07-10 20:40:10 +0530942func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530943 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200944 ponID := intf.GetIntfId()
945 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200946
Matteo Scandolof9d43412021-01-12 11:11:34 -0800947 msg := types.Message{
948 Type: types.PonIndication,
949 Data: types.PonIndicationMessage{
950 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200951 PonPortID: ponID,
952 },
953 }
954 o.channel <- msg
955
956 for _, onu := range pon.Onus {
957
Matteo Scandolof9d43412021-01-12 11:11:34 -0800958 onuIndication := types.OnuIndicationMessage{
959 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200960 PonPortID: ponID,
961 OnuID: onu.ID,
962 OnuSN: onu.SerialNumber,
963 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700964 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200965
966 }
967
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700968 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700969}
970
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100971func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700972 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530973 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700974 o.Enable(stream)
975 return nil
976}
977
Shrey Baid688b4242020-07-10 20:40:10 +0530978func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530979 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530980 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200981 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200982
Matteo Scandolof9d43412021-01-12 11:11:34 -0800983 msg := types.Message{
984 Type: types.PonIndication,
985 Data: types.PonIndicationMessage{
986 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530987 PonPortID: ponID,
988 },
989 }
990 o.channel <- msg
991
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200992 for _, onu := range pon.Onus {
993
Matteo Scandolof9d43412021-01-12 11:11:34 -0800994 onuIndication := types.OnuIndicationMessage{
995 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200996 PonPortID: ponID,
997 OnuID: onu.ID,
998 OnuSN: onu.SerialNumber,
999 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001000 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001001
1002 }
1003
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001004 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001005}
1006
Shrey Baid688b4242020-07-10 20:40:10 +05301007func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001008 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001009 "IntfId": flow.AccessIntfId,
1010 "OnuId": flow.OnuId,
1011 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001012 "InnerVlan": flow.Classifier.IVid,
1013 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001014 "FlowType": flow.FlowType,
1015 "FlowId": flow.FlowId,
1016 "UniID": flow.UniId,
1017 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301018 }).Tracef("OLT receives FlowAdd")
1019
1020 flowKey := FlowKey{}
1021 if !o.enablePerf {
1022 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001023 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301024 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001025
1026 if flow.AccessIntfId == -1 {
1027 oltLogger.WithFields(log.Fields{
1028 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001029 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001030 } else if flow.FlowType == "multicast" {
1031 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001032 "Cookie": flow.Cookie,
1033 "DstPort": flow.Classifier.DstPort,
1034 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1035 "FlowId": flow.FlowId,
1036 "FlowType": flow.FlowType,
1037 "GemportId": flow.GemportId,
1038 "InnerVlan": flow.Classifier.IVid,
1039 "IntfId": flow.AccessIntfId,
1040 "IpProto": flow.Classifier.IpProto,
1041 "OnuId": flow.OnuId,
1042 "OuterVlan": flow.Classifier.OVid,
1043 "PortNo": flow.PortNo,
1044 "SrcPort": flow.Classifier.SrcPort,
1045 "UniID": flow.UniId,
1046 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001047 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001048 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001049 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001050 if err != nil {
1051 oltLogger.WithFields(log.Fields{
1052 "OnuId": flow.OnuId,
1053 "IntfId": flow.AccessIntfId,
1054 "err": err,
1055 }).Error("Can't find PonPort")
1056 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001057 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001058 if err != nil {
1059 oltLogger.WithFields(log.Fields{
1060 "OnuId": flow.OnuId,
1061 "IntfId": flow.AccessIntfId,
1062 "err": err,
1063 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001064 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001065 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001066
1067 // if the ONU is disabled reject the flow
1068 // as per VOL-4061 there is a small window during which the ONU is disabled
1069 // but the port has not been reported as down to ONOS
1070 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1071 oltLogger.WithFields(log.Fields{
1072 "OnuId": flow.OnuId,
1073 "IntfId": flow.AccessIntfId,
1074 "Flow": flow,
1075 "SerialNumber": onu.Sn(),
1076 "InternalState": onu.InternalState.Current(),
1077 }).Error("rejected-flow-because-of-onu-state")
1078 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1079 }
1080
Pragya Arya8bdb4532020-03-02 17:08:09 +05301081 if !o.enablePerf {
1082 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301083 // Generate event on first flow for ONU
1084 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001085 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301086 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301087 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001088
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001089 // validate that the flow reference correct IDs (Alloc, Gem)
1090 if err := o.validateFlow(flow); err != nil {
1091 oltLogger.WithFields(log.Fields{
1092 "OnuId": flow.OnuId,
1093 "IntfId": flow.AccessIntfId,
1094 "Flow": flow,
1095 "SerialNumber": onu.Sn(),
1096 "err": err,
1097 }).Error("invalid-flow-for-onu")
1098 return nil, err
1099 }
1100
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001101 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001102 o.storeAllocId(flow)
1103
Matteo Scandolof9d43412021-01-12 11:11:34 -08001104 msg := types.Message{
1105 Type: types.FlowAdd,
1106 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001107 PonPortID: pon.ID,
1108 OnuID: onu.ID,
1109 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001110 },
1111 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001112 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001113 }
1114
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001115 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001116}
1117
Pragya Arya8bdb4532020-03-02 17:08:09 +05301118// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301119func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001120
Pragya Arya8bdb4532020-03-02 17:08:09 +05301121 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001122 "AllocId": flow.AllocId,
1123 "Cookie": flow.Cookie,
1124 "FlowId": flow.FlowId,
1125 "FlowType": flow.FlowType,
1126 "GemportId": flow.GemportId,
1127 "IntfId": flow.AccessIntfId,
1128 "OnuId": flow.OnuId,
1129 "PortNo": flow.PortNo,
1130 "UniID": flow.UniId,
1131 "ReplicateFlow": flow.ReplicateFlow,
1132 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001133 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301134
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001135 olt.freeGemPortId(flow)
1136 olt.freeAllocId(flow)
1137
Pragya Arya8bdb4532020-03-02 17:08:09 +05301138 if !o.enablePerf { // remove only if flow were stored
1139 flowKey := FlowKey{
1140 ID: flow.FlowId,
1141 Direction: flow.FlowType,
1142 }
1143
1144 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001145 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301146 if !ok {
1147 oltLogger.Errorf("Flow %v not found", flow)
1148 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1149 }
1150
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001151 storedFlow := storedFlowIntf.(openolt.Flow)
1152
Pragya Arya8bdb4532020-03-02 17:08:09 +05301153 // if its ONU flow remove it from ONU also
1154 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001155 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1156 if err != nil {
1157 oltLogger.WithFields(log.Fields{
1158 "OnuId": storedFlow.OnuId,
1159 "IntfId": storedFlow.AccessIntfId,
1160 "PONs": olt.Pons,
1161 "err": err,
1162 }).Error("PON-port-not-found")
1163 return new(openolt.Empty), nil
1164 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301165 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1166 if err != nil {
1167 oltLogger.WithFields(log.Fields{
1168 "OnuId": storedFlow.OnuId,
1169 "IntfId": storedFlow.AccessIntfId,
1170 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001171 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301172 return new(openolt.Empty), nil
1173 }
1174 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001175 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301176 }
1177
1178 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001179 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301180 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001181
1182 if flow.AccessIntfId == -1 {
1183 oltLogger.WithFields(log.Fields{
1184 "FlowId": flow.FlowId,
1185 }).Debug("Removing OLT flow")
1186 } else if flow.FlowType == "multicast" {
1187 oltLogger.WithFields(log.Fields{
1188 "FlowId": flow.FlowId,
1189 }).Debug("Removing OLT multicast flow")
1190 } else {
1191
1192 onu, err := o.GetOnuByFlowId(flow.FlowId)
1193 if err != nil {
1194 oltLogger.WithFields(log.Fields{
1195 "OnuId": flow.OnuId,
1196 "IntfId": flow.AccessIntfId,
1197 "err": err,
1198 }).Error("Can't find Onu")
1199 return nil, err
1200 }
1201
Matteo Scandolof9d43412021-01-12 11:11:34 -08001202 msg := types.Message{
1203 Type: types.FlowRemoved,
1204 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301205 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001206 },
1207 }
1208 onu.Channel <- msg
1209 }
1210
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001211 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001212}
1213
Shrey Baid688b4242020-07-10 20:40:10 +05301214func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001215 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1216 oltLogger.WithFields(log.Fields{
1217 "signature": res.HeartbeatSignature,
1218 }).Trace("HeartbeatCheck")
1219 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001220}
1221
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001222func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001223 for _, pon := range o.Pons {
1224 for _, onu := range pon.Onus {
1225 for _, fId := range onu.FlowIds {
1226 if fId == flowId {
1227 return onu, nil
1228 }
1229 }
1230 }
1231 }
Shrey Baid688b4242020-07-10 20:40:10 +05301232 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001233}
1234
Shrey Baid688b4242020-07-10 20:40:10 +05301235func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001236
Matteo Scandolocedde462021-03-09 17:37:16 -08001237 intfIDs := []uint32{}
1238 for i := 0; i < o.NumPon; i++ {
1239 intfIDs = append(intfIDs, uint32(i))
1240 }
1241
1242 devinfo := &openolt.DeviceInfo{
1243 Vendor: common.Config.Olt.Vendor,
1244 Model: common.Config.Olt.Model,
1245 HardwareVersion: common.Config.Olt.HardwareVersion,
1246 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1247 Technology: common.Config.Olt.Technology,
1248 PonPorts: uint32(o.NumPon),
1249 OnuIdStart: onuIdStart,
1250 OnuIdEnd: onuIdEnd,
1251 AllocIdStart: allocIdStart,
1252 AllocIdEnd: allocIdEnd,
1253 GemportIdStart: gemportIdStart,
1254 GemportIdEnd: gemportIdEnd,
1255 FlowIdStart: flowIdStart,
1256 FlowIdEnd: flowIdEnd,
1257 DeviceSerialNumber: o.SerialNumber,
1258 DeviceId: common.Config.Olt.DeviceId,
1259 PreviouslyConnected: o.PreviouslyConnected,
1260 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1261 {
1262 IntfIds: intfIDs,
1263 Technology: common.Config.Olt.Technology,
1264 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1265 {
1266 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1267 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1268 Start: onuIdStart,
1269 End: onuIdEnd,
1270 },
1271 {
1272 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1273 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1274 Start: allocIdStart,
1275 End: allocIdEnd,
1276 },
1277 {
1278 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1279 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1280 Start: gemportIdStart,
1281 End: gemportIdEnd,
1282 },
1283 {
1284 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1285 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1286 Start: flowIdStart,
1287 End: flowIdEnd,
1288 },
1289 },
1290 },
1291 },
1292 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001293
1294 oltLogger.WithFields(log.Fields{
1295 "Vendor": devinfo.Vendor,
1296 "Model": devinfo.Model,
1297 "HardwareVersion": devinfo.HardwareVersion,
1298 "FirmwareVersion": devinfo.FirmwareVersion,
1299 "Technology": devinfo.Technology,
1300 "PonPorts": devinfo.PonPorts,
1301 "OnuIdStart": devinfo.OnuIdStart,
1302 "OnuIdEnd": devinfo.OnuIdEnd,
1303 "AllocIdStart": devinfo.AllocIdStart,
1304 "AllocIdEnd": devinfo.AllocIdEnd,
1305 "GemportIdStart": devinfo.GemportIdStart,
1306 "GemportIdEnd": devinfo.GemportIdEnd,
1307 "FlowIdStart": devinfo.FlowIdStart,
1308 "FlowIdEnd": devinfo.FlowIdEnd,
1309 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1310 "DeviceId": devinfo.DeviceId,
1311 "PreviouslyConnected": devinfo.PreviouslyConnected,
1312 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1313
1314 // once we connect, set the flag
1315 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001316
1317 return devinfo, nil
1318}
1319
Shrey Baid688b4242020-07-10 20:40:10 +05301320func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001321 pon, err := o.GetPonById(omci_msg.IntfId)
1322 if err != nil {
1323 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001324 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001325 "onu_id": omci_msg.OnuId,
1326 "pon_id": omci_msg.IntfId,
1327 }).Error("pon ID not found")
1328 return nil, err
1329 }
1330
1331 onu, err := pon.GetOnuById(omci_msg.OnuId)
1332 if err != nil {
1333 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001334 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001335 "onu_id": omci_msg.OnuId,
1336 "pon_id": omci_msg.IntfId,
1337 }).Error("onu ID not found")
1338 return nil, err
1339 }
1340
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001341 oltLogger.WithFields(log.Fields{
1342 "IntfId": onu.PonPortID,
1343 "OnuId": onu.ID,
1344 "OnuSn": onu.Sn(),
1345 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001346 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1347 if err != nil {
1348 log.WithFields(log.Fields{
1349 "IntfId": onu.PonPortID,
1350 "SerialNumber": onu.Sn(),
1351 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1352 "err": err.Error(),
1353 }).Error("cannot-parse-OMCI-packet")
1354 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001355 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001356 if onu.InternalState.Current() == OnuStateDisabled {
1357 // if the ONU is disabled just drop the message
1358 log.WithFields(log.Fields{
1359 "IntfId": onu.PonPortID,
1360 "SerialNumber": onu.Sn(),
1361 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1362 "omciPkt": omciPkt,
1363 "omciMsgType": omciMsg.MessageType,
1364 }).Warn("dropping-omci-message")
1365 } else {
1366 msg := types.Message{
1367 Type: types.OMCI,
1368 Data: types.OmciMessage{
1369 OnuSN: onu.SerialNumber,
1370 OnuID: onu.ID,
1371 OmciMsg: omciMsg,
1372 OmciPkt: omciPkt,
1373 },
1374 }
1375 onu.Channel <- msg
1376 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001377 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001378}
1379
Matteo Scandolo8a574812021-05-20 15:18:53 -07001380// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301381func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001382 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001383 if err != nil {
1384 oltLogger.WithFields(log.Fields{
1385 "OnuId": onuPkt.OnuId,
1386 "IntfId": onuPkt.IntfId,
1387 "err": err,
1388 }).Error("Can't find PonPort")
1389 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001390 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001391 if err != nil {
1392 oltLogger.WithFields(log.Fields{
1393 "OnuId": onuPkt.OnuId,
1394 "IntfId": onuPkt.IntfId,
1395 "err": err,
1396 }).Error("Can't find Onu")
1397 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001398
Matteo Scandolo075b1892019-10-07 12:11:07 -07001399 oltLogger.WithFields(log.Fields{
1400 "IntfId": onu.PonPortID,
1401 "OnuId": onu.ID,
1402 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001403 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001404 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001405
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001406 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001407
1408 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001409 if err != nil {
1410 onuLogger.WithFields(log.Fields{
1411 "IntfId": onu.PonPortID,
1412 "OnuId": onu.ID,
1413 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001414 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001415 }).Error("Can't find pktType in packet, droppint it")
1416 return new(openolt.Empty), nil
1417 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001418
Matteo Scandolo4a036262020-08-17 15:56:13 -07001419 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001420 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001421 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001422 "IntfId": onu.PonPortID,
1423 "OnuId": onu.ID,
1424 "OnuSn": onu.Sn(),
1425 "Pkt": rawpkt.Data(),
1426 }).Error("Can't find Dst MacAddress in packet, droppint it")
1427 return new(openolt.Empty), nil
1428 }
1429
Matteo Scandolof9d43412021-01-12 11:11:34 -08001430 msg := types.Message{
1431 Type: types.OnuPacketOut,
1432 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001433 IntfId: onuPkt.IntfId,
1434 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001435 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001436 Packet: rawpkt,
1437 Type: pktType,
1438 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001439 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001440 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001441
Matteo Scandolo075b1892019-10-07 12:11:07 -07001442 onu.Channel <- msg
1443
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001444 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001445}
1446
Shrey Baid688b4242020-07-10 20:40:10 +05301447func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001448
1449 // OLT Reboot is called in two cases:
1450 // - when an OLT is being removed (voltctl device disable -> voltctl device delete are called, then a new voltctl device create -> voltctl device enable will be issued)
1451 // - when an OLT needs to be rebooted (voltcl device reboot)
1452
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001453 oltLogger.WithFields(log.Fields{
1454 "oltId": o.ID,
1455 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301456 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301457 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001458 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001459}
1460
Shrey Baid688b4242020-07-10 20:40:10 +05301461func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301462 oltLogger.WithFields(log.Fields{
1463 "oltId": o.ID,
1464 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301465 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301466
Pragya Arya2225f202020-01-29 18:05:01 +05301467 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001468 oltMsg := types.Message{
1469 Type: types.OltIndication,
1470 Data: types.OltIndicationMessage{
1471 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301472 },
Pragya Arya1881df02020-01-29 18:05:01 +05301473 }
Pragya Arya2225f202020-01-29 18:05:01 +05301474 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301475
Pragya Arya2225f202020-01-29 18:05:01 +05301476 for _, pon := range o.Pons {
1477 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001478 msg := types.Message{
1479 Type: types.PonIndication,
1480 Data: types.PonIndicationMessage{
1481 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301482 PonPortID: pon.ID,
1483 },
1484 }
1485 o.channel <- msg
1486 }
1487 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001488
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001489 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001490}
1491
Shrey Baid688b4242020-07-10 20:40:10 +05301492func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001493 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1494
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001495 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1496
1497 if err != nil {
1498 return nil, err
1499 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001500 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001501}
1502
Shrey Baid688b4242020-07-10 20:40:10 +05301503func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001504 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001505 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001506}
1507
Shrey Baid688b4242020-07-10 20:40:10 +05301508func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001509 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001510 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001511}
1512
Shrey Baid688b4242020-07-10 20:40:10 +05301513func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001514 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001515 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001516}
1517
Shrey Baid688b4242020-07-10 20:40:10 +05301518func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001519 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001520 return new(openolt.Empty), nil
1521}
1522
Matteo Scandolo8a574812021-05-20 15:18:53 -07001523func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1524 oltLogger.WithFields(log.Fields{
1525 "OnuId": tq.OnuId,
1526 "IntfId": tq.IntfId,
1527 "OnuPortNo": tq.PortNo,
1528 "UniId": tq.UniId,
1529 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001530 return new(openolt.Empty), nil
1531}
1532
Matteo Scandolo8a574812021-05-20 15:18:53 -07001533func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301534 oltLogger.WithFields(log.Fields{
1535 "OnuId": trafficSchedulers.OnuId,
1536 "IntfId": trafficSchedulers.IntfId,
1537 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001538 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301539 }).Info("received CreateTrafficSchedulers")
1540
1541 if !s.enablePerf {
1542 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1543 if err != nil {
1544 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1545 return new(openolt.Empty), err
1546 }
1547 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1548 if err != nil {
1549 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1550 return new(openolt.Empty), err
1551 }
1552 onu.TrafficSchedulers = trafficSchedulers
1553 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001554 return new(openolt.Empty), nil
1555}
1556
Shrey Baid688b4242020-07-10 20:40:10 +05301557func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301558 oltLogger.WithFields(log.Fields{
1559 "OnuId": trafficSchedulers.OnuId,
1560 "IntfId": trafficSchedulers.IntfId,
1561 "OnuPortNo": trafficSchedulers.PortNo,
1562 }).Info("received RemoveTrafficSchedulers")
1563 if !s.enablePerf {
1564 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1565 if err != nil {
1566 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1567 return new(openolt.Empty), err
1568 }
1569 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1570 if err != nil {
1571 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1572 return new(openolt.Empty), err
1573 }
1574
1575 onu.TrafficSchedulers = nil
1576 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001577 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001578}
Scott Baker41724b82020-01-21 19:54:53 -08001579
Matteo Scandolo618a6582020-09-09 12:21:29 -07001580func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1581 oltLogger.WithFields(log.Fields{
1582 "GroupId": group.GroupId,
1583 "Command": group.Command,
1584 "Members": group.Members,
1585 "Action": group.Action,
1586 }).Debug("received PerformGroupOperation")
1587 return &openolt.Empty{}, nil
1588}
1589
1590func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1591 oltLogger.WithFields(log.Fields{
1592 "GroupId": group.GroupId,
1593 "Command": group.Command,
1594 "Members": group.Members,
1595 "Action": group.Action,
1596 }).Debug("received PerformGroupOperation")
1597 return &openolt.Empty{}, nil
1598}
1599
1600func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1601 return &common_protos.ReturnValues{}, nil
1602}
1603
1604func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1605 return &openolt.Empty{}, nil
1606}
1607
1608func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1609 return &openolt.OnuLogicalDistance{}, nil
1610}
1611
1612func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1613 return &openolt.OnuLogicalDistance{}, nil
1614}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001615
Girish Gowdra62f24292021-05-12 16:28:39 -07001616func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1617 return &openolt.PonRxPowerData{}, nil
1618}
1619
Matteo Scandolo96f89192021-03-12 13:17:26 -08001620func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1621 return &openolt.GemPortStatistics{}, nil
1622}
1623
1624func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1625 return &openolt.OnuStatistics{}, nil
1626}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001627
1628func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1629 o.AllocIDsLock.Lock()
1630 defer o.AllocIDsLock.Unlock()
1631
Matteo Scandolo21195d62021-04-07 14:31:23 -07001632 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1633 oltLogger.WithFields(log.Fields{
1634 "IntfId": flow.AccessIntfId,
1635 "OnuId": flow.OnuId,
1636 "PortNo": flow.PortNo,
1637 "GemportId": flow.GemportId,
1638 "FlowId": flow.FlowId,
1639 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1640 }
1641
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001642 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001643 "IntfId": flow.AccessIntfId,
1644 "OnuId": flow.OnuId,
1645 "PortNo": flow.PortNo,
1646 "GemportId": flow.GemportId,
1647 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001648 }).Trace("storing-alloc-id-via-flow")
1649
1650 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1651 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1652 }
1653 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1654 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1655 }
1656 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1657}
1658
1659func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1660 // if this is the last flow referencing the AllocId then remove it
1661 o.AllocIDsLock.Lock()
1662 defer o.AllocIDsLock.Unlock()
1663
1664 oltLogger.WithFields(log.Fields{
1665 "IntfId": flow.AccessIntfId,
1666 "OnuId": flow.OnuId,
1667 "PortNo": flow.PortNo,
1668 "GemportId": flow.GemportId,
1669 }).Trace("freeing-alloc-id-via-flow")
1670
1671 // NOTE look at the freeGemPortId implementation for comments and context
1672 for ponId, ponValues := range o.AllocIDs {
1673 for onuId, onuValues := range ponValues {
1674 for uniId, uniValues := range onuValues {
1675 for allocId, flows := range uniValues {
1676 for flowId := range flows {
1677 // if the flow matches, remove it from the map.
1678 if flow.FlowId == flowId {
1679 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1680 }
1681 // if that was the last flow for a particular allocId, remove the entire allocId
1682 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1683 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1684 }
1685 }
1686 }
1687 }
1688 }
1689 }
1690}
1691
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001692func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001693 o.GemPortIDsLock.Lock()
1694 defer o.GemPortIDsLock.Unlock()
1695
1696 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1697 oltLogger.WithFields(log.Fields{
1698 "IntfId": ponId,
1699 "OnuId": onuId,
1700 "PortNo": portNo,
1701 "GemportId": gemId,
1702 "FlowId": flowId,
1703 }).Error("trying-to-store-gemport-for-unknown-onu")
1704 }
1705
1706 oltLogger.WithFields(log.Fields{
1707 "IntfId": ponId,
1708 "OnuId": onuId,
1709 "PortNo": portNo,
1710 "GemportId": gemId,
1711 "FlowId": flowId,
1712 }).Trace("storing-alloc-id-via-flow")
1713
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001714 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1715 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1716 }
1717 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1718 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1719 }
1720 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1721}
1722
1723func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001724 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001725 "IntfId": flow.AccessIntfId,
1726 "OnuId": flow.OnuId,
1727 "PortNo": flow.PortNo,
1728 "GemportId": flow.GemportId,
1729 "FlowId": flow.FlowId,
1730 "ReplicateFlow": flow.ReplicateFlow,
1731 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001732 }).Trace("storing-gem-port-id-via-flow")
1733
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001734 if flow.ReplicateFlow {
1735 for _, gem := range flow.PbitToGemport {
1736 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1737 }
1738 } else {
1739 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001740 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001741}
1742
1743func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1744 // if this is the last flow referencing the GemPort then remove it
1745 o.GemPortIDsLock.Lock()
1746 defer o.GemPortIDsLock.Unlock()
1747
1748 oltLogger.WithFields(log.Fields{
1749 "IntfId": flow.AccessIntfId,
1750 "OnuId": flow.OnuId,
1751 "PortNo": flow.PortNo,
1752 "GemportId": flow.GemportId,
1753 }).Trace("freeing-gem-port-id-via-flow")
1754
1755 // NOTE that this loop is not very performant, it would be better if the flow carries
1756 // the same information that it carries during a FlowAdd. If so we can directly remove
1757 // items from the map
1758
1759 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1760 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1761 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1762 //}
1763
1764 // NOTE this loop assumes that flow IDs are unique per device
1765 for ponId, ponValues := range o.GemPortIDs {
1766 for onuId, onuValues := range ponValues {
1767 for uniId, uniValues := range onuValues {
1768 for gemId, flows := range uniValues {
1769 for flowId := range flows {
1770 // if the flow matches, remove it from the map.
1771 if flow.FlowId == flowId {
1772 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1773 }
1774 // if that was the last flow for a particular gem, remove the entire gem
1775 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1776 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1777 }
1778 }
1779 }
1780 }
1781 }
1782 }
1783}
1784
1785// validateFlow checks that:
1786// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1787// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1788func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001789 // validate gemPort
1790 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001791 defer o.GemPortIDsLock.RUnlock()
1792 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001793 if onuId == uint32(flow.OnuId) {
1794 continue
1795 }
1796 for uniId, uni := range onu {
1797 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001798 if flow.ReplicateFlow {
1799 for _, flowGem := range flow.PbitToGemport {
1800 if gem == int32(flowGem) {
1801 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1802 }
1803 }
1804 } else {
1805 if gem == flow.GemportId {
1806 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1807 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001808 }
1809 }
1810 }
1811 }
1812
1813 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001814 defer o.AllocIDsLock.RUnlock()
1815 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001816 if onuId == uint32(flow.OnuId) {
1817 continue
1818 }
1819 for uniId, uni := range onu {
1820 for allocId := range uni {
1821 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001822 return fmt.Errorf("allocId-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", allocId, uniId, onuId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001823 }
1824 }
1825 }
1826 }
1827
1828 return nil
1829}
1830
1831// clearAllResources is invoked up OLT Reboot to remove all the allocated
1832// GemPorts, AllocId and ONU-IDs across the PONs
1833func (o *OltDevice) clearAllResources() {
1834
1835 // remove the resources received via flows
1836 o.GemPortIDsLock.Lock()
1837 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1838 o.GemPortIDsLock.Unlock()
1839 o.AllocIDsLock.Lock()
1840 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1841 o.AllocIDsLock.Unlock()
1842
1843 // remove the resources received via OMCI
1844 for _, pon := range o.Pons {
1845 pon.removeAllAllocIds()
1846 pon.removeAllGemPorts()
1847 pon.removeAllOnuIds()
1848 }
1849}