blob: cf658eb41fa15f5e61cf70239ef1edea9fb93cd8 [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"
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -080023 "github.com/opencord/voltha-protos/v5/go/extension"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020024 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080025 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010027 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000029 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
30 "github.com/opencord/bbsim/internal/bbsim/types"
31 omcilib "github.com/opencord/bbsim/internal/common/omci"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000032 "github.com/opencord/voltha-protos/v5/go/ext/config"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000033
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070034 "github.com/google/gopacket"
35 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070036 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070037 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010038 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000039 "github.com/opencord/voltha-protos/v5/go/openolt"
40 "github.com/opencord/voltha-protos/v5/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 (
Girish Gowdra3015ff72021-06-28 11:48:56 -070053 onuIdStart = 1
54 // Least pon port on the real OLTs we test with today have 16 ports (not including the pluggable OLTs).
55 // Given that we have to support 512 ONUs per OLT, we have to have up to 32 ONU per PON (could be less
56 // on a higher density port OLT).
57 // We pass just enough limits here to ensure the resource pool is as
58 // compact as possible on the etcd to reduce storage.
59 onuIdEnd = onuIdStart + 31
60 allocIdStart = 1024
61 allocIdPerOnu = 4
62 allocIdEnd = allocIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu // up to 4 alloc-id per ONU
63 gemPortIdPerAllocId = 8
64 gemportIdStart = 1024
65 gemportIdEnd = gemportIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu*gemPortIdPerAllocId // up to 8 gemport-id per tcont/alloc-id
66 // The flow ids are no more necessary by the adapter, but still need to pass something dummy. Pass a very small valid range.
67 flowIdStart = 1
68 flowIdEnd = flowIdStart + 1
Matteo Scandolocedde462021-03-09 17:37:16 -080069)
70
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070071type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000072 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000073 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000074
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070075 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053076 ID int
77 SerialNumber string
78 NumNni int
79 NumPon int
80 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070081 NumUni int
Pragya Arya2225f202020-01-29 18:05:01 +053082 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080083 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070084 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010085 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053086 Delay int
87 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053088 EventChannel chan common.Event
89 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053090 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080091 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070092
Matteo Scandolo27428702019-10-11 16:21:16 -070093 Pons []*PonPort
94 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070095
96 // OLT Attributes
97 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000098
99 enableContext context.Context
100 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530101
Matteo Scandolo4a036262020-08-17 15:56:13 -0700102 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530103 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800104
105 // Allocated Resources
106 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000107 AllocIDsLock sync.RWMutex
108 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
109 GemPortIDsLock sync.RWMutex
110 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
111 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700112}
113
Matteo Scandolo27428702019-10-11 16:21:16 -0700114var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700115
Matteo Scandolo27428702019-10-11 16:21:16 -0700116func GetOLT() *OltDevice {
117 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700118}
119
Matteo Scandolo4a036262020-08-17 15:56:13 -0700120func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700121 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530122 "ID": options.Olt.ID,
123 "NumNni": options.Olt.NniPorts,
124 "NumPon": options.Olt.PonPorts,
125 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700126 "NumUni": options.Olt.UniPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700127 }).Debug("CreateOLT")
128
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700129 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530130 ID: options.Olt.ID,
131 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700132 OperState: getOperStateFSM(func(e *fsm.Event) {
133 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
134 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800135 NumNni: int(options.Olt.NniPorts),
136 NumPon: int(options.Olt.PonPorts),
137 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700138 NumUni: int(options.Olt.UniPorts),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800139 Pons: []*PonPort{},
140 Nnis: []*NniPort{},
141 Delay: options.BBSim.Delay,
142 enablePerf: options.BBSim.EnablePerf,
143 PublishEvents: options.BBSim.Events,
144 PortStatsInterval: options.Olt.PortStatsInterval,
145 dhcpServer: dhcp.NewDHCPServer(),
146 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800147 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
148 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000149 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 }
151
Pragya Arya996a0892020-03-09 21:47:52 +0530152 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530153 olt.ControlledActivation = val
154 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700155 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530156 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
157 olt.ControlledActivation = Default
158 }
159
Matteo Scandolo4747d292019-08-05 11:50:18 -0700160 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700161 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162 olt.InternalState = fsm.NewFSM(
163 "created",
164 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800165 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100166 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700167 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700168 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800169 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700170 },
171 fsm.Callbacks{
172 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700173 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700174 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100175 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800176 "enter_deleted": func(e *fsm.Event) {
177 // remove all the resource allocations
178 olt.clearAllResources()
179 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700180 },
181 )
182
Shrey Baid688b4242020-07-10 20:40:10 +0530183 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700184 // create NNI Port
185 nniPort, err := CreateNNI(&olt)
186 if err != nil {
187 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
188 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700189
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700190 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700191 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700192
Matteo Scandolo4a036262020-08-17 15:56:13 -0700193 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700194 nextCtag := map[string]int{}
195 nextStag := map[string]int{}
196
Matteo Scandolo4747d292019-08-05 11:50:18 -0700197 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800199
200 // initialize the resource maps for every PON Ports
201 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
202 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
203
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 // create ONU devices
207 for j := 0; j < olt.NumOnuPerPon; j++ {
208 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700209 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700210
Matteo Scandolo4a036262020-08-17 15:56:13 -0700211 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700212 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700213 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700214 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100215
Shrey Baid688b4242020-07-10 20:40:10 +0530216 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700217 if err := olt.InternalState.Event("initialize"); err != nil {
218 log.Errorf("Error initializing OLT: %v", err)
219 return nil
220 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100221 }
222
Pragya Arya324337e2020-02-20 14:35:08 +0530223 if olt.PublishEvents {
224 log.Debugf("BBSim event publishing is enabled")
225 // Create a channel to write event messages
226 olt.EventChannel = make(chan common.Event, 100)
227 }
228
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700229 return &olt
230}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700231
Shrey Baid688b4242020-07-10 20:40:10 +0530232func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100233
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000234 if o.OltServer == nil {
235 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100236 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800237 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100238 }
239
240 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800241 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100242
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 // FIXME we are assuming we have only one NNI
244 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800245 // NOTE we want to make sure the state is down when we initialize the OLT,
246 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
247 // in-band management
248 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800250
251 for ponId := range o.Pons {
252 // initialize the resource maps for every PON Ports
253 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
254 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
255 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700256}
257
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800258func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100259
Matteo Scandolo96f89192021-03-12 13:17:26 -0800260 o.PreviouslyConnected = false
261
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700262 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700263 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800264
265 oltLogger.WithFields(log.Fields{
266 "oltId": o.ID,
267 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
268
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700269 if o.InternalState.Is("enabled") {
270 oltLogger.WithFields(log.Fields{
271 "oltId": o.ID,
272 }).Info("This is an OLT soft reboot")
273 softReboot = true
274 }
275
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800276 // transition internal state to deleted
277 if err := o.InternalState.Event("delete"); err != nil {
278 oltLogger.WithFields(log.Fields{
279 "oltId": o.ID,
280 }).Errorf("Error deleting OLT: %v", err)
281 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100282 }
283
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700284 if softReboot {
285 for _, pon := range o.Pons {
286 if pon.InternalState.Current() == "enabled" {
287 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800288 msg := types.Message{
289 Type: types.PonIndication,
290 Data: types.PonIndicationMessage{
291 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700292 PonPortID: pon.ID,
293 },
294 }
295 o.channel <- msg
296 }
297
298 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800299 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700300 }
301 }
302 } else {
303 // PONs are already handled in the Disable call
304 for _, pon := range olt.Pons {
305 // ONUs are not automatically disabled when a PON goes down
306 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
307 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800308 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700309 }
Pragya Arya2225f202020-01-29 18:05:01 +0530310 }
311 }
312
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700313 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
314 o.StopOltServer()
315
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316 // terminate the OLT's processOltMessages go routine
317 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700318
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700319 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100320 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100321
322 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800323 oltLogger.WithFields(log.Fields{
324 "oltId": o.ID,
325 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100326 return err
327 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800328 oltLogger.WithFields(log.Fields{
329 "oltId": o.ID,
330 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100331 return nil
332}
333
334// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800335func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700336 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700337 lis, err := net.Listen("tcp", address)
338 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700339 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700340 }
341 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100342
Matteo Scandolo4747d292019-08-05 11:50:18 -0700343 openolt.RegisterOpenoltServer(grpcServer, o)
344
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100345 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700346
Shrey Baid688b4242020-07-10 20:40:10 +0530347 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100348 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700349
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100350 return grpcServer, nil
351}
352
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800353// StartOltServer will create the grpc server that VOLTHA uses
354// to communicate with the device
355func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
356 oltServer, err := o.newOltServer()
357 if err != nil {
358 oltLogger.WithFields(log.Fields{
359 "err": err,
360 }).Error("Cannot OLT gRPC server")
361 return nil, err
362 }
363 return oltServer, nil
364}
365
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100366// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800367func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000368 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800369 oltLogger.WithFields(log.Fields{
370 "oltId": o.SerialNumber,
371 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000372 o.OltServer.Stop()
373 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700374 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700375}
376
377// Device Methods
378
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100379// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530380func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700381 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530382 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700383
David Bainbridge103cf022019-12-16 20:11:35 +0000384 // If enabled has already been called then an enabled context has
385 // been created. If this is the case then we want to cancel all the
386 // proessing loops associated with that enable before we recreate
387 // new ones
388 o.Lock()
389 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700390 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000391 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530392 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700393 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000394 }
395 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
396 o.Unlock()
397
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700399
Matteo Scandolo4a036262020-08-17 15:56:13 -0700400 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530401
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100402 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700403 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000404 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700405
406 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800407 oltMsg := types.Message{
408 Type: types.OltIndication,
409 Data: types.OltIndicationMessage{
410 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700411 },
412 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100413 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700414
415 // send NNI Port Indications
416 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800417 msg := types.Message{
418 Type: types.NniIndication,
419 Data: types.NniIndicationMessage{
420 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700421 NniPortID: nni.ID,
422 },
423 }
424 o.channel <- msg
425 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100426
Shrey Baid688b4242020-07-10 20:40:10 +0530427 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530428 for _, pon := range o.Pons {
429 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800430 msg := types.Message{
431 Type: types.PonIndication,
432 Data: types.PonIndicationMessage{
433 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530434 PonPortID: pon.ID,
435 },
436 }
437 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000438 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700439 // when the enableContext was canceled the ONUs stopped listening on the channel
440 for _, onu := range pon.Onus {
441 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
442
443 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700444 for _, uni := range onu.UniPorts {
445 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700446 }
447 }
Pragya Arya2225f202020-01-29 18:05:01 +0530448 }
449 } else {
450
451 // 1. controlledActivation == Default: Send both PON and ONUs indications
452 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
453
454 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
455 // send PON Port indications
456 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800457 msg := types.Message{
458 Type: types.PonIndication,
459 Data: types.PonIndicationMessage{
460 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530461 PonPortID: pon.ID,
462 },
463 }
464 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700465 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700466 }
467 }
468
Pragya Arya996a0892020-03-09 21:47:52 +0530469 if !o.enablePerf {
470 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700471 wg.Add(1)
472 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530473 }
474
Matteo Scandolo4747d292019-08-05 11:50:18 -0700475 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700476 oltLogger.WithFields(log.Fields{
477 "stream": stream,
478 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700479}
480
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700481func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530482 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700483
484loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530485 for {
486 select {
487 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
488 // send NNI port stats
489 for _, port := range o.Nnis {
490 incrementStat := true
491 if port.OperState.Current() == "down" {
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
498 // send PON port stats
499 for _, port := range o.Pons {
500 incrementStat := true
501 // do not increment port stats if PON port is down or no ONU is activated on PON port
502 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
503 incrementStat = false
504 }
505 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700506 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530507 }
508 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700509 oltLogger.Debug("Stop sending port stats")
510 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530511 }
Pragya Arya996a0892020-03-09 21:47:52 +0530512 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700513 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530514}
515
Matteo Scandolo4747d292019-08-05 11:50:18 -0700516// Helpers method
517
Matteo Scandolof9d43412021-01-12 11:11:34 -0800518func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
519
520 switch interfaceType {
521 case "nni":
522 if !o.HasNni(interfaceId) {
523 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
524 }
525
526 case "pon":
527 if !o.HasPon(interfaceId) {
528 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
529 }
530 }
531
532 alarmIndication := &openolt.AlarmIndication{
533 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
534 Status: alarmStatus,
535 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
536 }},
537 }
538
539 msg := types.Message{
540 Type: types.AlarmIndication,
541 Data: alarmIndication,
542 }
543
544 o.channel <- msg
545
546 return nil
547}
548
549func (o *OltDevice) HasNni(id uint32) bool {
550 for _, intf := range o.Nnis {
551 if intf.ID == id {
552 return true
553 }
554 }
555 return false
556}
557
558func (o *OltDevice) HasPon(id uint32) bool {
559 for _, intf := range o.Pons {
560 if intf.ID == id {
561 return true
562 }
563 }
564 return false
565}
566
Shrey Baid688b4242020-07-10 20:40:10 +0530567func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700568 for _, pon := range o.Pons {
569 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700570 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700571 }
572 }
Shrey Baid688b4242020-07-10 20:40:10 +0530573 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700574}
575
Shrey Baid688b4242020-07-10 20:40:10 +0530576func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700577 for _, nni := range o.Nnis {
578 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700579 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700580 }
581 }
Shrey Baid688b4242020-07-10 20:40:10 +0530582 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700583}
584
Scott Baker41724b82020-01-21 19:54:53 -0800585func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
586 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
587 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
588 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
589 return
590 }
591
592 oltLogger.WithFields(log.Fields{
593 "AlarmIndication": alarmInd,
594 }).Debug("Sent Indication_AlarmInd")
595}
596
Matteo Scandolof9d43412021-01-12 11:11:34 -0800597func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700598 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
599 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700600 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800601 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700602 }
603
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700604 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 "OperState": msg.OperState,
606 }).Debug("Sent Indication_OltInd")
607}
608
Matteo Scandolof9d43412021-01-12 11:11:34 -0800609func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700610 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800611 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800612 if err := nni.OperState.Event("enable"); err != nil {
613 log.WithFields(log.Fields{
614 "Type": nni.Type,
615 "IntfId": nni.ID,
616 "OperState": nni.OperState.Current(),
617 }).Errorf("Can't move NNI Port to enabled state: %v", err)
618 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800619 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800620 if err := nni.OperState.Event("disable"); err != nil {
621 log.WithFields(log.Fields{
622 "Type": nni.Type,
623 "IntfId": nni.ID,
624 "OperState": nni.OperState.Current(),
625 }).Errorf("Can't move NNI Port to disable state: %v", err)
626 }
627 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700628 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
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 }}
634
635 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700636 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800637 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700638 }
639
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700640 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700641 "Type": nni.Type,
642 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700643 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 }).Debug("Sent Indication_IntfOperInd for NNI")
645}
646
Pragya Arya2225f202020-01-29 18:05:01 +0530647func (o *OltDevice) sendPonIndication(ponPortID uint32) {
648
Matteo Scandolo4a036262020-08-17 15:56:13 -0700649 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530650 pon, _ := o.GetPonById(ponPortID)
651 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700652 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700653 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655 }}
656
657 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700658 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800659 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700660 }
661
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700662 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700663 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700664 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700665 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666
Pragya Arya2225f202020-01-29 18:05:01 +0530667 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700668 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
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 }}
673
674 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700675 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800676 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700677 }
678
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700679 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700680 "Type": pon.Type,
681 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700682 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700683 }).Debug("Sent Indication_IntfOperInd for PON")
684}
685
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700686func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530687 if o.InternalState.Current() == "enabled" {
688 oltLogger.WithFields(log.Fields{
689 "Type": portType,
690 "IntfId": portID,
691 }).Trace("Sending port stats")
692 stats.IntfId = InterfaceIDToPortNo(portID, portType)
693 data := &openolt.Indication_PortStats{
694 PortStats: stats,
695 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700696
Shrey Baid55f328c2020-07-07 19:20:42 +0530697 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
698 oltLogger.Errorf("Failed to send PortStats: %v", err)
699 return
700 }
Pragya Arya996a0892020-03-09 21:47:52 +0530701 }
702}
703
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100704// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700705func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
706 oltLogger.WithFields(log.Fields{
707 "stream": stream,
708 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000709 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700710
David Bainbridge103cf022019-12-16 20:11:35 +0000711loop:
712 for {
713 select {
714 case <-ctx.Done():
715 oltLogger.Debug("OLT Indication processing canceled via context")
716 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700717 // do not terminate this loop if the stream is closed,
718 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
719 //case <-stream.Context().Done():
720 // oltLogger.Debug("OLT Indication processing canceled via stream context")
721 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000722 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700723 if !ok {
724 if ctx.Err() != nil {
725 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
726 }
727 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000728 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700729 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700730
David Bainbridge103cf022019-12-16 20:11:35 +0000731 oltLogger.WithFields(log.Fields{
732 "oltId": o.ID,
733 "messageType": message.Type,
734 }).Trace("Received message")
735
736 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800737 case types.OltIndication:
738 msg, _ := message.Data.(types.OltIndicationMessage)
739 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530740 _ = o.InternalState.Event("enable")
741 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800742 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530743 _ = o.InternalState.Event("disable")
744 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000745 }
746 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800747 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800748 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
749 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800750 case types.NniIndication:
751 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000752 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800753 case types.PonIndication:
754 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530755 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800756 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530757 if err := pon.OperState.Event("enable"); err != nil {
758 oltLogger.WithFields(log.Fields{
759 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800760 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530761 }).Error("Can't Enable Oper state for PON Port")
762 }
763 if err := pon.InternalState.Event("enable"); err != nil {
764 oltLogger.WithFields(log.Fields{
765 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800766 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530767 }).Error("Can't Enable Internal state for PON Port")
768 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800769 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530770 if err := pon.OperState.Event("disable"); err != nil {
771 oltLogger.WithFields(log.Fields{
772 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800773 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530774 }).Error("Can't Disable Oper state for PON Port")
775 }
776 if err := pon.InternalState.Event("disable"); err != nil {
777 oltLogger.WithFields(log.Fields{
778 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800779 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530780 }).Error("Can't Disable Internal state for PON Port")
781 }
Pragya Arya2225f202020-01-29 18:05:01 +0530782 }
David Bainbridge103cf022019-12-16 20:11:35 +0000783 default:
784 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
785 }
786 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700787 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100788 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700789 oltLogger.WithFields(log.Fields{
790 "stream": stream,
791 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700792}
793
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700794// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530795func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700796 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700797 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700798 for _, pon := range o.Pons {
799 for _, onu := range pon.Onus {
800 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700801 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700802 }
803 }
804 }
805
Shrey Baid688b4242020-07-10 20:40:10 +0530806 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700807}
808
William Kurkian9dadc5b2019-10-22 13:51:57 -0400809// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530810func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700811 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400812 // memoizing it will remove the bottleneck
813 for _, pon := range o.Pons {
814 if pon.ID == intfId {
815 for _, onu := range pon.Onus {
816 if onu.ID == onuId {
817 return onu, nil
818 }
819 }
820 }
821 }
Shrey Baid688b4242020-07-10 20:40:10 +0530822 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400823}
824
Matteo Scandolo4a036262020-08-17 15:56:13 -0700825// returns a Service with a given Mac Address
826func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700827 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700828 // memoizing it will remove the bottleneck
829 for _, pon := range o.Pons {
830 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700831 s, err := onu.findServiceByMacAddress(mac)
832 if err == nil {
833 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700834 }
835 }
836 }
837
Matteo Scandolo4a036262020-08-17 15:56:13 -0700838 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700839}
840
Matteo Scandolo4747d292019-08-05 11:50:18 -0700841// GRPC Endpoints
842
Shrey Baid688b4242020-07-10 20:40:10 +0530843func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700844
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700845 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800846
Matteo Scandolo8a574812021-05-20 15:18:53 -0700847 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800848 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
849 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
850
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700851 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700852
853 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
854 oltLogger.WithFields(log.Fields{
855 "OnuSn": _onu.Sn(),
856 }).Info("Received ActivateOnu call from VOLTHA")
857
William Kurkian0418bc82019-11-06 12:16:24 -0500858 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700859
Matteo Scandolocedde462021-03-09 17:37:16 -0800860 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700861 oltLogger.WithFields(log.Fields{
862 "IntfId": _onu.PonPortID,
863 "OnuSn": _onu.Sn(),
864 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800865 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700866 }
867
868 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
869
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700870 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700871}
872
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800873func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700874 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700875 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700876}
877
Shrey Baid688b4242020-07-10 20:40:10 +0530878func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530879 oltLogger.WithFields(log.Fields{
880 "IntfId": onu.IntfId,
881 "OnuId": onu.OnuId,
882 }).Info("Received DeleteOnu call from VOLTHA")
883
884 pon, err := o.GetPonById(onu.IntfId)
885 if err != nil {
886 oltLogger.WithFields(log.Fields{
887 "OnuId": onu.OnuId,
888 "IntfId": onu.IntfId,
889 "err": err,
890 }).Error("Can't find PonPort")
891 }
892 _onu, err := pon.GetOnuById(onu.OnuId)
893 if err != nil {
894 oltLogger.WithFields(log.Fields{
895 "OnuId": onu.OnuId,
896 "IntfId": onu.IntfId,
897 "err": err,
898 }).Error("Can't find Onu")
899 }
900
Matteo Scandolocedde462021-03-09 17:37:16 -0800901 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530902 oltLogger.WithFields(log.Fields{
903 "IntfId": _onu.PonPortID,
904 "OnuSn": _onu.Sn(),
905 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800906 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530907 }
908
Hardik Windlassad790cb2020-06-17 21:26:22 +0530909 // ONU Re-Discovery
910 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530911 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530912 }
913
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700914 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700915}
916
Shrey Baid688b4242020-07-10 20:40:10 +0530917func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700918 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800919 oltLogger.WithFields(log.Fields{
920 "oltId": o.ID,
921 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530922 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800923
Matteo Scandolo401503a2019-12-11 14:48:14 -0800924 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530925 if pon.InternalState.Current() == "enabled" {
926 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800927 msg := types.Message{
928 Type: types.PonIndication,
929 Data: types.PonIndicationMessage{
930 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530931 PonPortID: pon.ID,
932 },
933 }
934 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800935 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800936 }
937
Matteo Scandolo401503a2019-12-11 14:48:14 -0800938 // Note that we are not disabling the NNI as the real OLT does not.
939 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800940
941 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800942 oltMsg := types.Message{
943 Type: types.OltIndication,
944 Data: types.OltIndicationMessage{
945 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700946 },
947 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100948 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700949
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700950 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700951}
952
Shrey Baid688b4242020-07-10 20:40:10 +0530953func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530954 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200955 ponID := intf.GetIntfId()
956 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200957
Matteo Scandolof9d43412021-01-12 11:11:34 -0800958 msg := types.Message{
959 Type: types.PonIndication,
960 Data: types.PonIndicationMessage{
961 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200962 PonPortID: ponID,
963 },
964 }
965 o.channel <- msg
966
967 for _, onu := range pon.Onus {
968
Matteo Scandolof9d43412021-01-12 11:11:34 -0800969 onuIndication := types.OnuIndicationMessage{
970 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200971 PonPortID: ponID,
972 OnuID: onu.ID,
973 OnuSN: onu.SerialNumber,
974 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700975 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200976
977 }
978
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700979 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700980}
981
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100982func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700983 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530984 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700985 o.Enable(stream)
986 return nil
987}
988
Shrey Baid688b4242020-07-10 20:40:10 +0530989func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530990 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530991 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200992 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200993
Matteo Scandolof9d43412021-01-12 11:11:34 -0800994 msg := types.Message{
995 Type: types.PonIndication,
996 Data: types.PonIndicationMessage{
997 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530998 PonPortID: ponID,
999 },
1000 }
1001 o.channel <- msg
1002
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001003 for _, onu := range pon.Onus {
1004
Matteo Scandolof9d43412021-01-12 11:11:34 -08001005 onuIndication := types.OnuIndicationMessage{
1006 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001007 PonPortID: ponID,
1008 OnuID: onu.ID,
1009 OnuSN: onu.SerialNumber,
1010 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001011 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001012
1013 }
1014
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001015 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001016}
1017
Shrey Baid688b4242020-07-10 20:40:10 +05301018func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001019 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001020 "IntfId": flow.AccessIntfId,
1021 "OnuId": flow.OnuId,
1022 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001023 "InnerVlan": flow.Classifier.IVid,
1024 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001025 "FlowType": flow.FlowType,
1026 "FlowId": flow.FlowId,
1027 "UniID": flow.UniId,
1028 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301029 }).Tracef("OLT receives FlowAdd")
1030
1031 flowKey := FlowKey{}
1032 if !o.enablePerf {
1033 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001034 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301035 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001036
1037 if flow.AccessIntfId == -1 {
1038 oltLogger.WithFields(log.Fields{
1039 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001040 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001041 } else if flow.FlowType == "multicast" {
1042 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001043 "Cookie": flow.Cookie,
1044 "DstPort": flow.Classifier.DstPort,
1045 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1046 "FlowId": flow.FlowId,
1047 "FlowType": flow.FlowType,
1048 "GemportId": flow.GemportId,
1049 "InnerVlan": flow.Classifier.IVid,
1050 "IntfId": flow.AccessIntfId,
1051 "IpProto": flow.Classifier.IpProto,
1052 "OnuId": flow.OnuId,
1053 "OuterVlan": flow.Classifier.OVid,
1054 "PortNo": flow.PortNo,
1055 "SrcPort": flow.Classifier.SrcPort,
1056 "UniID": flow.UniId,
1057 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001058 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001059 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001060 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001061 if err != nil {
1062 oltLogger.WithFields(log.Fields{
1063 "OnuId": flow.OnuId,
1064 "IntfId": flow.AccessIntfId,
1065 "err": err,
1066 }).Error("Can't find PonPort")
1067 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001068 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001069 if err != nil {
1070 oltLogger.WithFields(log.Fields{
1071 "OnuId": flow.OnuId,
1072 "IntfId": flow.AccessIntfId,
1073 "err": err,
1074 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001075 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001076 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001077
1078 // if the ONU is disabled reject the flow
1079 // as per VOL-4061 there is a small window during which the ONU is disabled
1080 // but the port has not been reported as down to ONOS
1081 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1082 oltLogger.WithFields(log.Fields{
1083 "OnuId": flow.OnuId,
1084 "IntfId": flow.AccessIntfId,
1085 "Flow": flow,
1086 "SerialNumber": onu.Sn(),
1087 "InternalState": onu.InternalState.Current(),
1088 }).Error("rejected-flow-because-of-onu-state")
1089 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1090 }
1091
Pragya Arya8bdb4532020-03-02 17:08:09 +05301092 if !o.enablePerf {
1093 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301094 // Generate event on first flow for ONU
1095 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001096 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301097 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301098 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001099
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001100 // validate that the flow reference correct IDs (Alloc, Gem)
1101 if err := o.validateFlow(flow); err != nil {
1102 oltLogger.WithFields(log.Fields{
1103 "OnuId": flow.OnuId,
1104 "IntfId": flow.AccessIntfId,
1105 "Flow": flow,
1106 "SerialNumber": onu.Sn(),
1107 "err": err,
1108 }).Error("invalid-flow-for-onu")
1109 return nil, err
1110 }
1111
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001112 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001113 o.storeAllocId(flow)
1114
Matteo Scandolof9d43412021-01-12 11:11:34 -08001115 msg := types.Message{
1116 Type: types.FlowAdd,
1117 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001118 PonPortID: pon.ID,
1119 OnuID: onu.ID,
1120 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001121 },
1122 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001123 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001124 }
1125
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001126 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001127}
1128
Pragya Arya8bdb4532020-03-02 17:08:09 +05301129// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301130func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001131
Pragya Arya8bdb4532020-03-02 17:08:09 +05301132 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001133 "AllocId": flow.AllocId,
1134 "Cookie": flow.Cookie,
1135 "FlowId": flow.FlowId,
1136 "FlowType": flow.FlowType,
1137 "GemportId": flow.GemportId,
1138 "IntfId": flow.AccessIntfId,
1139 "OnuId": flow.OnuId,
1140 "PortNo": flow.PortNo,
1141 "UniID": flow.UniId,
1142 "ReplicateFlow": flow.ReplicateFlow,
1143 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001144 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301145
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001146 olt.freeGemPortId(flow)
1147 olt.freeAllocId(flow)
1148
Pragya Arya8bdb4532020-03-02 17:08:09 +05301149 if !o.enablePerf { // remove only if flow were stored
1150 flowKey := FlowKey{
1151 ID: flow.FlowId,
1152 Direction: flow.FlowType,
1153 }
1154
1155 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001156 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301157 if !ok {
1158 oltLogger.Errorf("Flow %v not found", flow)
1159 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1160 }
1161
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001162 storedFlow := storedFlowIntf.(openolt.Flow)
1163
Pragya Arya8bdb4532020-03-02 17:08:09 +05301164 // if its ONU flow remove it from ONU also
1165 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001166 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1167 if err != nil {
1168 oltLogger.WithFields(log.Fields{
1169 "OnuId": storedFlow.OnuId,
1170 "IntfId": storedFlow.AccessIntfId,
1171 "PONs": olt.Pons,
1172 "err": err,
1173 }).Error("PON-port-not-found")
1174 return new(openolt.Empty), nil
1175 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301176 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1177 if err != nil {
1178 oltLogger.WithFields(log.Fields{
1179 "OnuId": storedFlow.OnuId,
1180 "IntfId": storedFlow.AccessIntfId,
1181 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001182 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301183 return new(openolt.Empty), nil
1184 }
1185 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001186 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301187 }
1188
1189 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001190 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301191 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001192
1193 if flow.AccessIntfId == -1 {
1194 oltLogger.WithFields(log.Fields{
1195 "FlowId": flow.FlowId,
1196 }).Debug("Removing OLT flow")
1197 } else if flow.FlowType == "multicast" {
1198 oltLogger.WithFields(log.Fields{
1199 "FlowId": flow.FlowId,
1200 }).Debug("Removing OLT multicast flow")
1201 } else {
1202
1203 onu, err := o.GetOnuByFlowId(flow.FlowId)
1204 if err != nil {
1205 oltLogger.WithFields(log.Fields{
1206 "OnuId": flow.OnuId,
1207 "IntfId": flow.AccessIntfId,
1208 "err": err,
1209 }).Error("Can't find Onu")
1210 return nil, err
1211 }
1212
Matteo Scandolof9d43412021-01-12 11:11:34 -08001213 msg := types.Message{
1214 Type: types.FlowRemoved,
1215 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301216 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001217 },
1218 }
1219 onu.Channel <- msg
1220 }
1221
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001222 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001223}
1224
Shrey Baid688b4242020-07-10 20:40:10 +05301225func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001226 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1227 oltLogger.WithFields(log.Fields{
1228 "signature": res.HeartbeatSignature,
1229 }).Trace("HeartbeatCheck")
1230 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001231}
1232
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001233func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001234 for _, pon := range o.Pons {
1235 for _, onu := range pon.Onus {
1236 for _, fId := range onu.FlowIds {
1237 if fId == flowId {
1238 return onu, nil
1239 }
1240 }
1241 }
1242 }
Shrey Baid688b4242020-07-10 20:40:10 +05301243 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001244}
1245
Shrey Baid688b4242020-07-10 20:40:10 +05301246func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001247
Matteo Scandolocedde462021-03-09 17:37:16 -08001248 intfIDs := []uint32{}
1249 for i := 0; i < o.NumPon; i++ {
1250 intfIDs = append(intfIDs, uint32(i))
1251 }
1252
1253 devinfo := &openolt.DeviceInfo{
1254 Vendor: common.Config.Olt.Vendor,
1255 Model: common.Config.Olt.Model,
1256 HardwareVersion: common.Config.Olt.HardwareVersion,
1257 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1258 Technology: common.Config.Olt.Technology,
1259 PonPorts: uint32(o.NumPon),
1260 OnuIdStart: onuIdStart,
1261 OnuIdEnd: onuIdEnd,
1262 AllocIdStart: allocIdStart,
1263 AllocIdEnd: allocIdEnd,
1264 GemportIdStart: gemportIdStart,
1265 GemportIdEnd: gemportIdEnd,
1266 FlowIdStart: flowIdStart,
1267 FlowIdEnd: flowIdEnd,
1268 DeviceSerialNumber: o.SerialNumber,
1269 DeviceId: common.Config.Olt.DeviceId,
1270 PreviouslyConnected: o.PreviouslyConnected,
1271 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1272 {
1273 IntfIds: intfIDs,
1274 Technology: common.Config.Olt.Technology,
1275 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1276 {
1277 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1278 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1279 Start: onuIdStart,
1280 End: onuIdEnd,
1281 },
1282 {
1283 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1284 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1285 Start: allocIdStart,
1286 End: allocIdEnd,
1287 },
1288 {
1289 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1290 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1291 Start: gemportIdStart,
1292 End: gemportIdEnd,
1293 },
1294 {
1295 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1296 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1297 Start: flowIdStart,
1298 End: flowIdEnd,
1299 },
1300 },
1301 },
1302 },
1303 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001304
1305 oltLogger.WithFields(log.Fields{
1306 "Vendor": devinfo.Vendor,
1307 "Model": devinfo.Model,
1308 "HardwareVersion": devinfo.HardwareVersion,
1309 "FirmwareVersion": devinfo.FirmwareVersion,
1310 "Technology": devinfo.Technology,
1311 "PonPorts": devinfo.PonPorts,
1312 "OnuIdStart": devinfo.OnuIdStart,
1313 "OnuIdEnd": devinfo.OnuIdEnd,
1314 "AllocIdStart": devinfo.AllocIdStart,
1315 "AllocIdEnd": devinfo.AllocIdEnd,
1316 "GemportIdStart": devinfo.GemportIdStart,
1317 "GemportIdEnd": devinfo.GemportIdEnd,
1318 "FlowIdStart": devinfo.FlowIdStart,
1319 "FlowIdEnd": devinfo.FlowIdEnd,
1320 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1321 "DeviceId": devinfo.DeviceId,
1322 "PreviouslyConnected": devinfo.PreviouslyConnected,
1323 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1324
1325 // once we connect, set the flag
1326 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001327
1328 return devinfo, nil
1329}
1330
Shrey Baid688b4242020-07-10 20:40:10 +05301331func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001332 pon, err := o.GetPonById(omci_msg.IntfId)
1333 if err != nil {
1334 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001335 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001336 "onu_id": omci_msg.OnuId,
1337 "pon_id": omci_msg.IntfId,
1338 }).Error("pon ID not found")
1339 return nil, err
1340 }
1341
1342 onu, err := pon.GetOnuById(omci_msg.OnuId)
1343 if err != nil {
1344 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001345 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001346 "onu_id": omci_msg.OnuId,
1347 "pon_id": omci_msg.IntfId,
1348 }).Error("onu ID not found")
1349 return nil, err
1350 }
1351
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001352 oltLogger.WithFields(log.Fields{
1353 "IntfId": onu.PonPortID,
1354 "OnuId": onu.ID,
1355 "OnuSn": onu.Sn(),
1356 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001357 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1358 if err != nil {
1359 log.WithFields(log.Fields{
1360 "IntfId": onu.PonPortID,
1361 "SerialNumber": onu.Sn(),
1362 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1363 "err": err.Error(),
1364 }).Error("cannot-parse-OMCI-packet")
1365 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001366 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001367 if onu.InternalState.Current() == OnuStateDisabled {
1368 // if the ONU is disabled just drop the message
1369 log.WithFields(log.Fields{
1370 "IntfId": onu.PonPortID,
1371 "SerialNumber": onu.Sn(),
1372 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1373 "omciPkt": omciPkt,
1374 "omciMsgType": omciMsg.MessageType,
1375 }).Warn("dropping-omci-message")
1376 } else {
1377 msg := types.Message{
1378 Type: types.OMCI,
1379 Data: types.OmciMessage{
1380 OnuSN: onu.SerialNumber,
1381 OnuID: onu.ID,
1382 OmciMsg: omciMsg,
1383 OmciPkt: omciPkt,
1384 },
1385 }
1386 onu.Channel <- msg
1387 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001388 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001389}
1390
Matteo Scandolo8a574812021-05-20 15:18:53 -07001391// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301392func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001393 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001394 if err != nil {
1395 oltLogger.WithFields(log.Fields{
1396 "OnuId": onuPkt.OnuId,
1397 "IntfId": onuPkt.IntfId,
1398 "err": err,
1399 }).Error("Can't find PonPort")
1400 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001401 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001402 if err != nil {
1403 oltLogger.WithFields(log.Fields{
1404 "OnuId": onuPkt.OnuId,
1405 "IntfId": onuPkt.IntfId,
1406 "err": err,
1407 }).Error("Can't find Onu")
1408 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001409
Matteo Scandolo075b1892019-10-07 12:11:07 -07001410 oltLogger.WithFields(log.Fields{
1411 "IntfId": onu.PonPortID,
1412 "OnuId": onu.ID,
1413 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001414 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001415 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001416
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001417 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001418
1419 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001420 if err != nil {
1421 onuLogger.WithFields(log.Fields{
1422 "IntfId": onu.PonPortID,
1423 "OnuId": onu.ID,
1424 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001425 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001426 }).Error("Can't find pktType in packet, droppint it")
1427 return new(openolt.Empty), nil
1428 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001429
Matteo Scandolo4a036262020-08-17 15:56:13 -07001430 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001431 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001432 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001433 "IntfId": onu.PonPortID,
1434 "OnuId": onu.ID,
1435 "OnuSn": onu.Sn(),
1436 "Pkt": rawpkt.Data(),
1437 }).Error("Can't find Dst MacAddress in packet, droppint it")
1438 return new(openolt.Empty), nil
1439 }
1440
Matteo Scandolof9d43412021-01-12 11:11:34 -08001441 msg := types.Message{
1442 Type: types.OnuPacketOut,
1443 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001444 IntfId: onuPkt.IntfId,
1445 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001446 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001447 Packet: rawpkt,
1448 Type: pktType,
1449 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001450 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001451 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001452
Matteo Scandolo075b1892019-10-07 12:11:07 -07001453 onu.Channel <- msg
1454
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001455 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001456}
1457
Shrey Baid688b4242020-07-10 20:40:10 +05301458func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001459
1460 // OLT Reboot is called in two cases:
1461 // - 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)
1462 // - when an OLT needs to be rebooted (voltcl device reboot)
1463
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001464 oltLogger.WithFields(log.Fields{
1465 "oltId": o.ID,
1466 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301467 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301468 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001469 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001470}
1471
Shrey Baid688b4242020-07-10 20:40:10 +05301472func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301473 oltLogger.WithFields(log.Fields{
1474 "oltId": o.ID,
1475 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301476 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301477
Pragya Arya2225f202020-01-29 18:05:01 +05301478 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001479 oltMsg := types.Message{
1480 Type: types.OltIndication,
1481 Data: types.OltIndicationMessage{
1482 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301483 },
Pragya Arya1881df02020-01-29 18:05:01 +05301484 }
Pragya Arya2225f202020-01-29 18:05:01 +05301485 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301486
Pragya Arya2225f202020-01-29 18:05:01 +05301487 for _, pon := range o.Pons {
1488 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001489 msg := types.Message{
1490 Type: types.PonIndication,
1491 Data: types.PonIndicationMessage{
1492 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301493 PonPortID: pon.ID,
1494 },
1495 }
1496 o.channel <- msg
1497 }
1498 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001499
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) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001504 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1505
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001506 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1507
1508 if err != nil {
1509 return nil, err
1510 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001511 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001512}
1513
Shrey Baid688b4242020-07-10 20:40:10 +05301514func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001515 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001516 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001517}
1518
Shrey Baid688b4242020-07-10 20:40:10 +05301519func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001520 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001521 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001522}
1523
Shrey Baid688b4242020-07-10 20:40:10 +05301524func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001525 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001526 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001527}
1528
Shrey Baid688b4242020-07-10 20:40:10 +05301529func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001530 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001531 return new(openolt.Empty), nil
1532}
1533
Matteo Scandolo8a574812021-05-20 15:18:53 -07001534func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1535 oltLogger.WithFields(log.Fields{
1536 "OnuId": tq.OnuId,
1537 "IntfId": tq.IntfId,
1538 "OnuPortNo": tq.PortNo,
1539 "UniId": tq.UniId,
1540 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001541 return new(openolt.Empty), nil
1542}
1543
Matteo Scandolo8a574812021-05-20 15:18:53 -07001544func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301545 oltLogger.WithFields(log.Fields{
1546 "OnuId": trafficSchedulers.OnuId,
1547 "IntfId": trafficSchedulers.IntfId,
1548 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001549 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301550 }).Info("received CreateTrafficSchedulers")
1551
1552 if !s.enablePerf {
1553 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1554 if err != nil {
1555 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1556 return new(openolt.Empty), err
1557 }
1558 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1559 if err != nil {
1560 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1561 return new(openolt.Empty), err
1562 }
1563 onu.TrafficSchedulers = trafficSchedulers
1564 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001565 return new(openolt.Empty), nil
1566}
1567
Shrey Baid688b4242020-07-10 20:40:10 +05301568func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301569 oltLogger.WithFields(log.Fields{
1570 "OnuId": trafficSchedulers.OnuId,
1571 "IntfId": trafficSchedulers.IntfId,
1572 "OnuPortNo": trafficSchedulers.PortNo,
1573 }).Info("received RemoveTrafficSchedulers")
1574 if !s.enablePerf {
1575 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1576 if err != nil {
1577 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1578 return new(openolt.Empty), err
1579 }
1580 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1581 if err != nil {
1582 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1583 return new(openolt.Empty), err
1584 }
1585
1586 onu.TrafficSchedulers = nil
1587 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001588 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001589}
Scott Baker41724b82020-01-21 19:54:53 -08001590
Matteo Scandolo618a6582020-09-09 12:21:29 -07001591func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1592 oltLogger.WithFields(log.Fields{
1593 "GroupId": group.GroupId,
1594 "Command": group.Command,
1595 "Members": group.Members,
1596 "Action": group.Action,
1597 }).Debug("received PerformGroupOperation")
1598 return &openolt.Empty{}, nil
1599}
1600
1601func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1602 oltLogger.WithFields(log.Fields{
1603 "GroupId": group.GroupId,
1604 "Command": group.Command,
1605 "Members": group.Members,
1606 "Action": group.Action,
1607 }).Debug("received PerformGroupOperation")
1608 return &openolt.Empty{}, nil
1609}
1610
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001611func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1612 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001613}
1614
1615func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1616 return &openolt.Empty{}, nil
1617}
1618
1619func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1620 return &openolt.OnuLogicalDistance{}, nil
1621}
1622
1623func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1624 return &openolt.OnuLogicalDistance{}, nil
1625}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001626
Girish Gowdra62f24292021-05-12 16:28:39 -07001627func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1628 return &openolt.PonRxPowerData{}, nil
1629}
1630
Matteo Scandolo96f89192021-03-12 13:17:26 -08001631func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1632 return &openolt.GemPortStatistics{}, nil
1633}
1634
1635func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1636 return &openolt.OnuStatistics{}, nil
1637}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001638
1639func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1640 o.AllocIDsLock.Lock()
1641 defer o.AllocIDsLock.Unlock()
1642
Matteo Scandolo21195d62021-04-07 14:31:23 -07001643 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1644 oltLogger.WithFields(log.Fields{
1645 "IntfId": flow.AccessIntfId,
1646 "OnuId": flow.OnuId,
1647 "PortNo": flow.PortNo,
1648 "GemportId": flow.GemportId,
1649 "FlowId": flow.FlowId,
1650 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1651 }
1652
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001653 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001654 "IntfId": flow.AccessIntfId,
1655 "OnuId": flow.OnuId,
1656 "PortNo": flow.PortNo,
1657 "GemportId": flow.GemportId,
1658 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001659 }).Trace("storing-alloc-id-via-flow")
1660
1661 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1662 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1663 }
1664 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1665 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1666 }
1667 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1668}
1669
1670func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1671 // if this is the last flow referencing the AllocId then remove it
1672 o.AllocIDsLock.Lock()
1673 defer o.AllocIDsLock.Unlock()
1674
1675 oltLogger.WithFields(log.Fields{
1676 "IntfId": flow.AccessIntfId,
1677 "OnuId": flow.OnuId,
1678 "PortNo": flow.PortNo,
1679 "GemportId": flow.GemportId,
1680 }).Trace("freeing-alloc-id-via-flow")
1681
1682 // NOTE look at the freeGemPortId implementation for comments and context
1683 for ponId, ponValues := range o.AllocIDs {
1684 for onuId, onuValues := range ponValues {
1685 for uniId, uniValues := range onuValues {
1686 for allocId, flows := range uniValues {
1687 for flowId := range flows {
1688 // if the flow matches, remove it from the map.
1689 if flow.FlowId == flowId {
1690 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1691 }
1692 // if that was the last flow for a particular allocId, remove the entire allocId
1693 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1694 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1695 }
1696 }
1697 }
1698 }
1699 }
1700 }
1701}
1702
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001703func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001704 o.GemPortIDsLock.Lock()
1705 defer o.GemPortIDsLock.Unlock()
1706
1707 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1708 oltLogger.WithFields(log.Fields{
1709 "IntfId": ponId,
1710 "OnuId": onuId,
1711 "PortNo": portNo,
1712 "GemportId": gemId,
1713 "FlowId": flowId,
1714 }).Error("trying-to-store-gemport-for-unknown-onu")
1715 }
1716
1717 oltLogger.WithFields(log.Fields{
1718 "IntfId": ponId,
1719 "OnuId": onuId,
1720 "PortNo": portNo,
1721 "GemportId": gemId,
1722 "FlowId": flowId,
1723 }).Trace("storing-alloc-id-via-flow")
1724
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001725 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1726 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1727 }
1728 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1729 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1730 }
1731 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1732}
1733
1734func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001735 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001736 "IntfId": flow.AccessIntfId,
1737 "OnuId": flow.OnuId,
1738 "PortNo": flow.PortNo,
1739 "GemportId": flow.GemportId,
1740 "FlowId": flow.FlowId,
1741 "ReplicateFlow": flow.ReplicateFlow,
1742 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001743 }).Trace("storing-gem-port-id-via-flow")
1744
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001745 if flow.ReplicateFlow {
1746 for _, gem := range flow.PbitToGemport {
1747 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1748 }
1749 } else {
1750 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001751 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001752}
1753
1754func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1755 // if this is the last flow referencing the GemPort then remove it
1756 o.GemPortIDsLock.Lock()
1757 defer o.GemPortIDsLock.Unlock()
1758
1759 oltLogger.WithFields(log.Fields{
1760 "IntfId": flow.AccessIntfId,
1761 "OnuId": flow.OnuId,
1762 "PortNo": flow.PortNo,
1763 "GemportId": flow.GemportId,
1764 }).Trace("freeing-gem-port-id-via-flow")
1765
1766 // NOTE that this loop is not very performant, it would be better if the flow carries
1767 // the same information that it carries during a FlowAdd. If so we can directly remove
1768 // items from the map
1769
1770 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1771 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1772 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1773 //}
1774
1775 // NOTE this loop assumes that flow IDs are unique per device
1776 for ponId, ponValues := range o.GemPortIDs {
1777 for onuId, onuValues := range ponValues {
1778 for uniId, uniValues := range onuValues {
1779 for gemId, flows := range uniValues {
1780 for flowId := range flows {
1781 // if the flow matches, remove it from the map.
1782 if flow.FlowId == flowId {
1783 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1784 }
1785 // if that was the last flow for a particular gem, remove the entire gem
1786 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1787 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1788 }
1789 }
1790 }
1791 }
1792 }
1793 }
1794}
1795
1796// validateFlow checks that:
1797// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1798// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1799func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001800 // validate gemPort
1801 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001802 defer o.GemPortIDsLock.RUnlock()
1803 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001804 if onuId == uint32(flow.OnuId) {
1805 continue
1806 }
1807 for uniId, uni := range onu {
1808 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001809 if flow.ReplicateFlow {
1810 for _, flowGem := range flow.PbitToGemport {
1811 if gem == int32(flowGem) {
1812 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1813 }
1814 }
1815 } else {
1816 if gem == flow.GemportId {
1817 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1818 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001819 }
1820 }
1821 }
1822 }
1823
1824 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001825 defer o.AllocIDsLock.RUnlock()
1826 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001827 if onuId == uint32(flow.OnuId) {
1828 continue
1829 }
1830 for uniId, uni := range onu {
1831 for allocId := range uni {
1832 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001833 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 -08001834 }
1835 }
1836 }
1837 }
1838
1839 return nil
1840}
1841
1842// clearAllResources is invoked up OLT Reboot to remove all the allocated
1843// GemPorts, AllocId and ONU-IDs across the PONs
1844func (o *OltDevice) clearAllResources() {
1845
1846 // remove the resources received via flows
1847 o.GemPortIDsLock.Lock()
1848 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1849 o.GemPortIDsLock.Unlock()
1850 o.AllocIDsLock.Lock()
1851 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1852 o.AllocIDsLock.Unlock()
1853
1854 // remove the resources received via OMCI
1855 for _, pon := range o.Pons {
1856 pon.removeAllAllocIds()
1857 pon.removeAllGemPorts()
1858 pon.removeAllOnuIds()
1859 }
1860}