blob: a556256bbf6170817afffd29f727ca045cff4be8 [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
Elia Battistonac63b112022-01-12 18:40:49 +010028 "github.com/opencord/voltha-protos/v5/go/extension"
29
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000030 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
31 "github.com/opencord/bbsim/internal/bbsim/types"
32 omcilib "github.com/opencord/bbsim/internal/common/omci"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000033 "github.com/opencord/voltha-protos/v5/go/ext/config"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000034
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070035 "github.com/google/gopacket"
36 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070038 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010039 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000040 "github.com/opencord/voltha-protos/v5/go/openolt"
41 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042 log "github.com/sirupsen/logrus"
43 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053044 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010045 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053046 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070047)
48
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070049var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070050 "module": "OLT",
51})
52
Matteo Scandolocedde462021-03-09 17:37:16 -080053const (
Elia Battiston67e9e4c2022-02-15 16:38:40 +010054 //InternalState FSM states and transitions
55 OltInternalStateCreated = "created"
56 OltInternalStateInitialized = "initialized"
57 OltInternalStateEnabled = "enabled"
58 OltInternalStateDisabled = "disabled"
59 OltInternalStateDeleted = "deleted"
60
61 OltInternalTxInitialize = "initialize"
62 OltInternalTxEnable = "enable"
63 OltInternalTxDisable = "disable"
64 OltInternalTxDelete = "delete"
Matteo Scandolocedde462021-03-09 17:37:16 -080065)
66
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070067type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000068 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000069 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000070
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070071 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053072 ID int
73 SerialNumber string
74 NumNni int
Elia Battiston420c9092022-02-02 12:17:54 +010075 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053076 NumPon int
77 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070078 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010079 NumPots int
Andrea Campanella6f5f3552022-03-10 17:14:25 +010080 NniDhcpTrapVid int
Pragya Arya2225f202020-01-29 18:05:01 +053081 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080082 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070083 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010084 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053085 Delay int
86 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053087 EventChannel chan common.Event
88 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053089 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080090 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070091
Matteo Scandolo27428702019-10-11 16:21:16 -070092 Pons []*PonPort
93 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070094
95 // OLT Attributes
96 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000097
98 enableContext context.Context
99 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530100
Matteo Scandolo4a036262020-08-17 15:56:13 -0700101 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530102 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800103
104 // Allocated Resources
105 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000106 AllocIDsLock sync.RWMutex
107 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
108 GemPortIDsLock sync.RWMutex
109 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
110 OmciResponseRate uint8
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530111 signature uint32
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{
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100122 "ID": options.Olt.ID,
123 "NumNni": options.Olt.NniPorts,
124 "NniSpeed": options.Olt.NniSpeed,
125 "NumPon": options.Olt.PonPorts,
126 "NumOnuPerPon": options.Olt.OnusPonPort,
127 "NumUni": options.Olt.UniPorts,
128 "NumPots": options.Olt.PotsPorts,
129 "NniDhcpTrapVid": options.Olt.NniDhcpTrapVid,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130 }).Debug("CreateOLT")
131
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700132 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530133 ID: options.Olt.ID,
134 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700135 OperState: getOperStateFSM(func(e *fsm.Event) {
136 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
137 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800138 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100139 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800140 NumPon: int(options.Olt.PonPorts),
141 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700142 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100143 NumPots: int(options.Olt.PotsPorts),
Andrea Campanella6f5f3552022-03-10 17:14:25 +0100144 NniDhcpTrapVid: int(options.Olt.NniDhcpTrapVid),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800145 Pons: []*PonPort{},
146 Nnis: []*NniPort{},
147 Delay: options.BBSim.Delay,
148 enablePerf: options.BBSim.EnablePerf,
149 PublishEvents: options.BBSim.Events,
150 PortStatsInterval: options.Olt.PortStatsInterval,
151 dhcpServer: dhcp.NewDHCPServer(),
152 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800153 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
154 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000155 OmciResponseRate: options.Olt.OmciResponseRate,
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530156 signature: uint32(time.Now().Unix()),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 }
158
Pragya Arya996a0892020-03-09 21:47:52 +0530159 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530160 olt.ControlledActivation = val
161 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700162 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530163 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
164 olt.ControlledActivation = Default
165 }
166
Matteo Scandolo4747d292019-08-05 11:50:18 -0700167 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700168 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700169 olt.InternalState = fsm.NewFSM(
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100170 OltInternalStateCreated,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700171 fsm.Events{
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100172 {Name: OltInternalTxInitialize, Src: []string{OltInternalStateCreated, OltInternalStateDeleted}, Dst: OltInternalStateInitialized},
173 {Name: OltInternalTxEnable, Src: []string{OltInternalStateInitialized, OltInternalStateDisabled}, Dst: OltInternalStateEnabled},
174 {Name: OltInternalTxDisable, Src: []string{OltInternalStateEnabled}, Dst: OltInternalStateDisabled},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700175 // delete event in enabled state below is for reboot OLT case.
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100176 {Name: OltInternalTxDelete, Src: []string{OltInternalStateDisabled, OltInternalStateEnabled}, Dst: OltInternalStateDeleted},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700177 },
178 fsm.Callbacks{
179 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700180 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700181 },
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100182 fmt.Sprintf("enter_%s", OltInternalStateInitialized): func(e *fsm.Event) { olt.InitOlt() },
183 fmt.Sprintf("enter_%s", OltInternalStateDeleted): func(e *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800184 // remove all the resource allocations
185 olt.clearAllResources()
186 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700187 },
188 )
189
Shrey Baid688b4242020-07-10 20:40:10 +0530190 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700191 // create NNI Port
192 nniPort, err := CreateNNI(&olt)
193 if err != nil {
194 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
195 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700196
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700197 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700198 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700199
Matteo Scandolo4a036262020-08-17 15:56:13 -0700200 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700201 nextCtag := map[string]int{}
202 nextStag := map[string]int{}
203
Matteo Scandolo4747d292019-08-05 11:50:18 -0700204 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700205 for i := 0; i < olt.NumPon; i++ {
Elia Battistonb7bea222022-02-18 16:25:00 +0100206 ponConf, err := common.GetPonConfigById(uint32(i))
207 if err != nil {
208 oltLogger.WithFields(log.Fields{
209 "Err": err,
210 "IntfId": i,
211 }).Fatal("cannot-get-pon-configuration")
212 }
213
214 tech, err := common.PonTechnologyFromString(ponConf.Technology)
215 if err != nil {
216 oltLogger.WithFields(log.Fields{
217 "Err": err,
218 "IntfId": i,
219 }).Fatal("unkown-pon-port-technology")
220 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800221
222 // initialize the resource maps for every PON Ports
223 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
224 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
225
Elia Battistonb7bea222022-02-18 16:25:00 +0100226 p := CreatePonPort(&olt, uint32(i), tech)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700227
Matteo Scandolo4a036262020-08-17 15:56:13 -0700228 // create ONU devices
Elia Battistonb7bea222022-02-18 16:25:00 +0100229 if (ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1) < uint32(olt.NumOnuPerPon) {
230 oltLogger.WithFields(log.Fields{
231 "OnuRange": ponConf.OnuRange,
232 "RangeSize": ponConf.OnuRange.EndId - ponConf.OnuRange.StartId + 1,
233 "NumOnuPerPon": olt.NumOnuPerPon,
234 "IntfId": i,
235 }).Fatal("onus-per-pon-bigger-than-resource-range-size")
236 }
237
Matteo Scandolo4a036262020-08-17 15:56:13 -0700238 for j := 0; j < olt.NumOnuPerPon; j++ {
239 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700240 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700241
Matteo Scandolo4a036262020-08-17 15:56:13 -0700242 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700243 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700244 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700245 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246
Shrey Baid688b4242020-07-10 20:40:10 +0530247 if !isMock {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100248 if err := olt.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700249 log.Errorf("Error initializing OLT: %v", err)
250 return nil
251 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100252 }
253
Pragya Arya324337e2020-02-20 14:35:08 +0530254 if olt.PublishEvents {
255 log.Debugf("BBSim event publishing is enabled")
256 // Create a channel to write event messages
257 olt.EventChannel = make(chan common.Event, 100)
258 }
259
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700260 return &olt
261}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700262
Shrey Baid688b4242020-07-10 20:40:10 +0530263func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100264
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000265 if o.OltServer == nil {
266 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100267 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100269 }
270
271 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800272 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100273
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274 // FIXME we are assuming we have only one NNI
275 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800276 // NOTE we want to make sure the state is down when we initialize the OLT,
277 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
278 // in-band management
279 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100280 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800281
282 for ponId := range o.Pons {
283 // initialize the resource maps for every PON Ports
284 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
285 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
286 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700287}
288
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800289func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100290
Matteo Scandolo96f89192021-03-12 13:17:26 -0800291 o.PreviouslyConnected = false
292
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700293 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700294 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800295
296 oltLogger.WithFields(log.Fields{
297 "oltId": o.ID,
298 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
299
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100300 if o.InternalState.Is(OltInternalStateEnabled) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700301 oltLogger.WithFields(log.Fields{
302 "oltId": o.ID,
303 }).Info("This is an OLT soft reboot")
304 softReboot = true
305 }
306
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800307 // transition internal state to deleted
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100308 if err := o.InternalState.Event(OltInternalTxDelete); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800309 oltLogger.WithFields(log.Fields{
310 "oltId": o.ID,
311 }).Errorf("Error deleting OLT: %v", err)
312 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100313 }
314
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700315 if softReboot {
316 for _, pon := range o.Pons {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530317 /* No need to send pon events on olt soft reboot
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700318 if pon.InternalState.Current() == "enabled" {
319 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800320 msg := types.Message{
321 Type: types.PonIndication,
322 Data: types.PonIndicationMessage{
323 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700324 PonPortID: pon.ID,
325 },
326 }
327 o.channel <- msg
328 }
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530329 */
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700330 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100331 err := onu.InternalState.Event(OnuTxDisable)
332 oltLogger.WithFields(log.Fields{
333 "oltId": o.ID,
334 "onuId": onu.ID,
335 }).Errorf("Error disabling ONUs on OLT soft reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700336 }
337 }
338 } else {
339 // PONs are already handled in the Disable call
340 for _, pon := range olt.Pons {
341 // ONUs are not automatically disabled when a PON goes down
342 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
343 for _, onu := range pon.Onus {
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100344 err := onu.InternalState.Event(OnuTxDisable)
345 oltLogger.WithFields(log.Fields{
346 "oltId": o.ID,
347 "onuId": onu.ID,
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700348 "OnuSn": onu.Sn(),
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100349 }).Errorf("Error disabling ONUs on OLT reboot: %v", err)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700350 }
Pragya Arya2225f202020-01-29 18:05:01 +0530351 }
352 }
353
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700354 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
355 o.StopOltServer()
356
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100357 // terminate the OLT's processOltMessages go routine
358 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700359
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100360 oltLogger.WithFields(log.Fields{
361 "oltId": o.ID,
362 }).Infof("Waiting OLT restart for... (%ds)", rebootDelay)
363
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100364 //Prevents Enable to progress before the reboot is completed (VOL-4616)
365 o.Lock()
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700366 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100367 time.Sleep(time.Duration(rebootDelay) * time.Second)
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100368 o.Unlock()
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530369 o.signature = uint32(time.Now().Unix())
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100370
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100371 if err := o.InternalState.Event(OltInternalTxInitialize); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800372 oltLogger.WithFields(log.Fields{
373 "oltId": o.ID,
374 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100375 return err
376 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800377 oltLogger.WithFields(log.Fields{
378 "oltId": o.ID,
379 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100380 return nil
381}
382
383// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800384func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700385 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700386 lis, err := net.Listen("tcp", address)
387 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700388 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700389 }
390 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100391
Matteo Scandolo4747d292019-08-05 11:50:18 -0700392 openolt.RegisterOpenoltServer(grpcServer, o)
393
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100394 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700395
Shrey Baid688b4242020-07-10 20:40:10 +0530396 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100397 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700398
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100399 return grpcServer, nil
400}
401
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800402// StartOltServer will create the grpc server that VOLTHA uses
403// to communicate with the device
404func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
405 oltServer, err := o.newOltServer()
406 if err != nil {
407 oltLogger.WithFields(log.Fields{
408 "err": err,
409 }).Error("Cannot OLT gRPC server")
410 return nil, err
411 }
412 return oltServer, nil
413}
414
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100415// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800416func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000417 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800418 oltLogger.WithFields(log.Fields{
419 "oltId": o.SerialNumber,
420 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000421 o.OltServer.Stop()
422 o.OltServer = nil
Andrea Campanella8ad54a42022-03-09 14:36:55 +0100423 } else {
424 oltLogger.WithFields(log.Fields{
425 "oltId": o.SerialNumber,
426 }).Warnf("OLT gRPC server is already stopped")
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700427 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700428}
429
430// Device Methods
431
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100432// Enable implements the OpenOLT EnableIndicationServer functionality
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100433func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700434 oltLogger.Debug("Enable OLT called")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100435
436 if o.InternalState.Is(OltInternalStateDeleted) {
437 err := fmt.Errorf("Cannot enable OLT while it is rebooting")
438 oltLogger.WithFields(log.Fields{
439 "oltId": o.SerialNumber,
440 "internalState": o.InternalState.Current(),
441 }).Error(err)
442 return err
443 }
444
Pragya Arya2225f202020-01-29 18:05:01 +0530445 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700446
David Bainbridge103cf022019-12-16 20:11:35 +0000447 // If enabled has already been called then an enabled context has
448 // been created. If this is the case then we want to cancel all the
449 // proessing loops associated with that enable before we recreate
450 // new ones
451 o.Lock()
452 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700453 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000454 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530455 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700456 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000457 }
458 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
459 o.Unlock()
460
Matteo Scandolo4747d292019-08-05 11:50:18 -0700461 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700462
Matteo Scandolo4a036262020-08-17 15:56:13 -0700463 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530464
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100465 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700466 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000467 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700468
469 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800470 oltMsg := types.Message{
471 Type: types.OltIndication,
472 Data: types.OltIndicationMessage{
473 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700474 },
475 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100476 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700477
478 // send NNI Port Indications
479 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800480 msg := types.Message{
481 Type: types.NniIndication,
482 Data: types.NniIndicationMessage{
483 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700484 NniPortID: nni.ID,
485 },
486 }
487 o.channel <- msg
488 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100489
Shrey Baid688b4242020-07-10 20:40:10 +0530490 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530491 for _, pon := range o.Pons {
492 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800493 msg := types.Message{
494 Type: types.PonIndication,
495 Data: types.PonIndicationMessage{
496 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530497 PonPortID: pon.ID,
498 },
499 }
500 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000501 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700502 // when the enableContext was canceled the ONUs stopped listening on the channel
503 for _, onu := range pon.Onus {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530504 onu.ReDiscoverOnu(true)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700505 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
506
507 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700508 for _, uni := range onu.UniPorts {
509 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700510 }
511 }
Pragya Arya2225f202020-01-29 18:05:01 +0530512 }
513 } else {
514
515 // 1. controlledActivation == Default: Send both PON and ONUs indications
516 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
517
518 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
519 // send PON Port indications
520 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800521 msg := types.Message{
522 Type: types.PonIndication,
523 Data: types.PonIndicationMessage{
524 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530525 PonPortID: pon.ID,
526 },
527 }
528 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700529 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700530 }
531 }
532
Pragya Arya996a0892020-03-09 21:47:52 +0530533 if !o.enablePerf {
534 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700535 wg.Add(1)
536 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530537 }
538
Matteo Scandolo4747d292019-08-05 11:50:18 -0700539 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700540 oltLogger.WithFields(log.Fields{
541 "stream": stream,
542 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100543
544 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700545}
546
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700547func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530548 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700549
550loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530551 for {
552 select {
553 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
554 // send NNI port stats
555 for _, port := range o.Nnis {
556 incrementStat := true
557 if port.OperState.Current() == "down" {
558 incrementStat = false
559 }
560 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700561 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530562 }
563
564 // send PON port stats
565 for _, port := range o.Pons {
566 incrementStat := true
567 // do not increment port stats if PON port is down or no ONU is activated on PON port
568 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
569 incrementStat = false
570 }
571 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700572 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530573 }
574 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700575 oltLogger.Debug("Stop sending port stats")
576 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530577 }
Pragya Arya996a0892020-03-09 21:47:52 +0530578 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700579 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530580}
581
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582// Helpers method
583
Matteo Scandolof9d43412021-01-12 11:11:34 -0800584func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
585
586 switch interfaceType {
587 case "nni":
588 if !o.HasNni(interfaceId) {
589 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
590 }
591
592 case "pon":
593 if !o.HasPon(interfaceId) {
594 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
595 }
596 }
597
598 alarmIndication := &openolt.AlarmIndication{
599 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
600 Status: alarmStatus,
601 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
602 }},
603 }
604
605 msg := types.Message{
606 Type: types.AlarmIndication,
607 Data: alarmIndication,
608 }
609
610 o.channel <- msg
611
612 return nil
613}
614
615func (o *OltDevice) HasNni(id uint32) bool {
616 for _, intf := range o.Nnis {
617 if intf.ID == id {
618 return true
619 }
620 }
621 return false
622}
623
624func (o *OltDevice) HasPon(id uint32) bool {
625 for _, intf := range o.Pons {
626 if intf.ID == id {
627 return true
628 }
629 }
630 return false
631}
632
Shrey Baid688b4242020-07-10 20:40:10 +0530633func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700634 for _, pon := range o.Pons {
635 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700636 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700637 }
638 }
Shrey Baid688b4242020-07-10 20:40:10 +0530639 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700640}
641
Shrey Baid688b4242020-07-10 20:40:10 +0530642func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700643 for _, nni := range o.Nnis {
644 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700645 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700646 }
647 }
Shrey Baid688b4242020-07-10 20:40:10 +0530648 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649}
650
Scott Baker41724b82020-01-21 19:54:53 -0800651func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
652 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
653 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
654 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
655 return
656 }
657
658 oltLogger.WithFields(log.Fields{
659 "AlarmIndication": alarmInd,
660 }).Debug("Sent Indication_AlarmInd")
661}
662
Matteo Scandolof9d43412021-01-12 11:11:34 -0800663func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
665 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700666 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800667 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700668 }
669
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700670 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700671 "OperState": msg.OperState,
672 }).Debug("Sent Indication_OltInd")
673}
674
Matteo Scandolof9d43412021-01-12 11:11:34 -0800675func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700676 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800677 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800678 if err := nni.OperState.Event("enable"); err != nil {
679 log.WithFields(log.Fields{
680 "Type": nni.Type,
681 "IntfId": nni.ID,
682 "OperState": nni.OperState.Current(),
683 }).Errorf("Can't move NNI Port to enabled state: %v", err)
684 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800685 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800686 if err := nni.OperState.Event("disable"); err != nil {
687 log.WithFields(log.Fields{
688 "Type": nni.Type,
689 "IntfId": nni.ID,
690 "OperState": nni.OperState.Current(),
691 }).Errorf("Can't move NNI Port to disable state: %v", err)
692 }
693 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700694 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700695 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700696 Type: nni.Type,
697 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700698 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100699 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700700 }}
701
702 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700703 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800704 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700705 }
706
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700707 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700708 "Type": nni.Type,
709 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700710 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100711 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700712 }).Debug("Sent Indication_IntfOperInd for NNI")
713}
714
Pragya Arya2225f202020-01-29 18:05:01 +0530715func (o *OltDevice) sendPonIndication(ponPortID uint32) {
716
Matteo Scandolo4a036262020-08-17 15:56:13 -0700717 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530718 pon, _ := o.GetPonById(ponPortID)
719 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700720 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700721 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700722 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700723 }}
724
725 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700726 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800727 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700728 }
729
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700730 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700731 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700732 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700733 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700734
Pragya Arya2225f202020-01-29 18:05:01 +0530735 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700736 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700737 Type: pon.Type,
738 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700739 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700740 }}
741
742 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700743 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800744 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700745 }
746
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700747 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700748 "Type": pon.Type,
749 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700750 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700751 }).Debug("Sent Indication_IntfOperInd for PON")
752}
753
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700754func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100755 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530756 oltLogger.WithFields(log.Fields{
757 "Type": portType,
758 "IntfId": portID,
759 }).Trace("Sending port stats")
760 stats.IntfId = InterfaceIDToPortNo(portID, portType)
761 data := &openolt.Indication_PortStats{
762 PortStats: stats,
763 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700764
Shrey Baid55f328c2020-07-07 19:20:42 +0530765 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
766 oltLogger.Errorf("Failed to send PortStats: %v", err)
767 return
768 }
Pragya Arya996a0892020-03-09 21:47:52 +0530769 }
770}
771
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100772// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700773func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
774 oltLogger.WithFields(log.Fields{
775 "stream": stream,
776 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000777 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700778
David Bainbridge103cf022019-12-16 20:11:35 +0000779loop:
780 for {
781 select {
782 case <-ctx.Done():
783 oltLogger.Debug("OLT Indication processing canceled via context")
784 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700785 // do not terminate this loop if the stream is closed,
786 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
787 //case <-stream.Context().Done():
788 // oltLogger.Debug("OLT Indication processing canceled via stream context")
789 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000790 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700791 if !ok {
792 if ctx.Err() != nil {
793 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
794 }
795 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000796 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700797 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700798
David Bainbridge103cf022019-12-16 20:11:35 +0000799 oltLogger.WithFields(log.Fields{
800 "oltId": o.ID,
801 "messageType": message.Type,
802 }).Trace("Received message")
803
804 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800805 case types.OltIndication:
806 msg, _ := message.Data.(types.OltIndicationMessage)
807 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100808 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530809 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800810 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100811 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530812 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000813 }
814 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800815 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800816 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
817 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800818 case types.NniIndication:
819 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000820 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800821 case types.PonIndication:
822 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530823 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800824 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530825 if err := pon.OperState.Event("enable"); err != nil {
826 oltLogger.WithFields(log.Fields{
827 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800828 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530829 }).Error("Can't Enable Oper state for PON Port")
830 }
831 if err := pon.InternalState.Event("enable"); err != nil {
832 oltLogger.WithFields(log.Fields{
833 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800834 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530835 }).Error("Can't Enable Internal state for PON Port")
836 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800837 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530838 if err := pon.OperState.Event("disable"); err != nil {
839 oltLogger.WithFields(log.Fields{
840 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800841 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530842 }).Error("Can't Disable Oper state for PON Port")
843 }
844 if err := pon.InternalState.Event("disable"); err != nil {
845 oltLogger.WithFields(log.Fields{
846 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800847 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530848 }).Error("Can't Disable Internal state for PON Port")
849 }
Pragya Arya2225f202020-01-29 18:05:01 +0530850 }
David Bainbridge103cf022019-12-16 20:11:35 +0000851 default:
852 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
853 }
854 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700855 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100856 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700857 oltLogger.WithFields(log.Fields{
858 "stream": stream,
859 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700860}
861
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700862// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530863func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700864 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700865 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700866 for _, pon := range o.Pons {
867 for _, onu := range pon.Onus {
868 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700869 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700870 }
871 }
872 }
873
Shrey Baid688b4242020-07-10 20:40:10 +0530874 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700875}
876
William Kurkian9dadc5b2019-10-22 13:51:57 -0400877// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530878func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700879 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400880 // memoizing it will remove the bottleneck
881 for _, pon := range o.Pons {
882 if pon.ID == intfId {
883 for _, onu := range pon.Onus {
884 if onu.ID == onuId {
885 return onu, nil
886 }
887 }
888 }
889 }
Shrey Baid688b4242020-07-10 20:40:10 +0530890 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400891}
892
Matteo Scandolo4a036262020-08-17 15:56:13 -0700893// returns a Service with a given Mac Address
894func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700895 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700896 // memoizing it will remove the bottleneck
897 for _, pon := range o.Pons {
898 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700899 s, err := onu.findServiceByMacAddress(mac)
900 if err == nil {
901 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700902 }
903 }
904 }
905
Matteo Scandolo4a036262020-08-17 15:56:13 -0700906 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700907}
908
Matteo Scandolo4747d292019-08-05 11:50:18 -0700909// GRPC Endpoints
910
Shrey Baid688b4242020-07-10 20:40:10 +0530911func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700912
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700913 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800914
Matteo Scandolo8a574812021-05-20 15:18:53 -0700915 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800916 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
917 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
918
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700919 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700920
921 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
922 oltLogger.WithFields(log.Fields{
923 "OnuSn": _onu.Sn(),
924 }).Info("Received ActivateOnu call from VOLTHA")
925
William Kurkian0418bc82019-11-06 12:16:24 -0500926 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700927
Matteo Scandolocedde462021-03-09 17:37:16 -0800928 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700929 oltLogger.WithFields(log.Fields{
930 "IntfId": _onu.PonPortID,
931 "OnuSn": _onu.Sn(),
932 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800933 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700934 }
935
936 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
937
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700938 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700939}
940
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800941func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700942 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700943 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700944}
945
Shrey Baid688b4242020-07-10 20:40:10 +0530946func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530947 oltLogger.WithFields(log.Fields{
948 "IntfId": onu.IntfId,
949 "OnuId": onu.OnuId,
950 }).Info("Received DeleteOnu call from VOLTHA")
951
952 pon, err := o.GetPonById(onu.IntfId)
953 if err != nil {
954 oltLogger.WithFields(log.Fields{
955 "OnuId": onu.OnuId,
956 "IntfId": onu.IntfId,
957 "err": err,
958 }).Error("Can't find PonPort")
959 }
960 _onu, err := pon.GetOnuById(onu.OnuId)
961 if err != nil {
962 oltLogger.WithFields(log.Fields{
963 "OnuId": onu.OnuId,
964 "IntfId": onu.IntfId,
965 "err": err,
966 }).Error("Can't find Onu")
967 }
968
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530969 if _onu.InternalState.Current() != OnuStateDisabled {
970 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
971 oltLogger.WithFields(log.Fields{
972 "IntfId": _onu.PonPortID,
973 "OnuSn": _onu.Sn(),
974 "OnuId": _onu.ID,
975 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
976 }
Hardik Windlassad790cb2020-06-17 21:26:22 +0530977 }
978
Hardik Windlassad790cb2020-06-17 21:26:22 +0530979 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100980 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530981 go _onu.ReDiscoverOnu(false)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530982 }
983
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700984 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700985}
986
Shrey Baid688b4242020-07-10 20:40:10 +0530987func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700988 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800989 oltLogger.WithFields(log.Fields{
990 "oltId": o.ID,
991 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530992 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800993
Matteo Scandolo401503a2019-12-11 14:48:14 -0800994 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530995 if pon.InternalState.Current() == "enabled" {
996 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800997 msg := types.Message{
998 Type: types.PonIndication,
999 Data: types.PonIndicationMessage{
1000 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +05301001 PonPortID: pon.ID,
1002 },
1003 }
1004 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001005 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001006 }
1007
Matteo Scandolo401503a2019-12-11 14:48:14 -08001008 // Note that we are not disabling the NNI as the real OLT does not.
1009 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001010
1011 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001012 oltMsg := types.Message{
1013 Type: types.OltIndication,
1014 Data: types.OltIndicationMessage{
1015 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001016 },
1017 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001018 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001019
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001020 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001021}
1022
Shrey Baid688b4242020-07-10 20:40:10 +05301023func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301024 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001025 ponID := intf.GetIntfId()
1026 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001027
Matteo Scandolof9d43412021-01-12 11:11:34 -08001028 msg := types.Message{
1029 Type: types.PonIndication,
1030 Data: types.PonIndicationMessage{
1031 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001032 PonPortID: ponID,
1033 },
1034 }
1035 o.channel <- msg
1036
1037 for _, onu := range pon.Onus {
1038
Matteo Scandolof9d43412021-01-12 11:11:34 -08001039 onuIndication := types.OnuIndicationMessage{
1040 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001041 PonPortID: ponID,
1042 OnuID: onu.ID,
1043 OnuSN: onu.SerialNumber,
1044 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001045 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001046
1047 }
1048
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001049 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001050}
1051
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001052func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001053 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301054 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001055 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001056}
1057
Shrey Baid688b4242020-07-10 20:40:10 +05301058func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301059 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301060 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001061 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001062
Matteo Scandolof9d43412021-01-12 11:11:34 -08001063 msg := types.Message{
1064 Type: types.PonIndication,
1065 Data: types.PonIndicationMessage{
1066 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301067 PonPortID: ponID,
1068 },
1069 }
1070 o.channel <- msg
1071
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001072 for _, onu := range pon.Onus {
1073
Matteo Scandolof9d43412021-01-12 11:11:34 -08001074 onuIndication := types.OnuIndicationMessage{
1075 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001076 PonPortID: ponID,
1077 OnuID: onu.ID,
1078 OnuSN: onu.SerialNumber,
1079 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001080 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001081
1082 }
1083
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001084 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001085}
1086
Shrey Baid688b4242020-07-10 20:40:10 +05301087func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001088 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001089 "IntfId": flow.AccessIntfId,
1090 "OnuId": flow.OnuId,
1091 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001092 "InnerVlan": flow.Classifier.IVid,
1093 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001094 "FlowType": flow.FlowType,
1095 "FlowId": flow.FlowId,
1096 "UniID": flow.UniId,
1097 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301098 }).Tracef("OLT receives FlowAdd")
1099
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001100 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301101 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001102 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001103 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301104 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001105
1106 if flow.AccessIntfId == -1 {
1107 oltLogger.WithFields(log.Fields{
1108 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001109 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001110 } else if flow.FlowType == "multicast" {
1111 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001112 "Cookie": flow.Cookie,
1113 "DstPort": flow.Classifier.DstPort,
1114 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1115 "FlowId": flow.FlowId,
1116 "FlowType": flow.FlowType,
1117 "GemportId": flow.GemportId,
1118 "InnerVlan": flow.Classifier.IVid,
1119 "IntfId": flow.AccessIntfId,
1120 "IpProto": flow.Classifier.IpProto,
1121 "OnuId": flow.OnuId,
1122 "OuterVlan": flow.Classifier.OVid,
1123 "PortNo": flow.PortNo,
1124 "SrcPort": flow.Classifier.SrcPort,
1125 "UniID": flow.UniId,
1126 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001127 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001128 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001129 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001130 if err != nil {
1131 oltLogger.WithFields(log.Fields{
1132 "OnuId": flow.OnuId,
1133 "IntfId": flow.AccessIntfId,
1134 "err": err,
1135 }).Error("Can't find PonPort")
1136 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001137 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001138 if err != nil {
1139 oltLogger.WithFields(log.Fields{
1140 "OnuId": flow.OnuId,
1141 "IntfId": flow.AccessIntfId,
1142 "err": err,
1143 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001144 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001145 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001146
1147 // if the ONU is disabled reject the flow
1148 // as per VOL-4061 there is a small window during which the ONU is disabled
1149 // but the port has not been reported as down to ONOS
1150 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1151 oltLogger.WithFields(log.Fields{
1152 "OnuId": flow.OnuId,
1153 "IntfId": flow.AccessIntfId,
1154 "Flow": flow,
1155 "SerialNumber": onu.Sn(),
1156 "InternalState": onu.InternalState.Current(),
1157 }).Error("rejected-flow-because-of-onu-state")
1158 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1159 }
1160
Pragya Arya8bdb4532020-03-02 17:08:09 +05301161 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001162 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301163 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001164 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001165 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301166 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301167 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001168
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001169 // validate that the flow reference correct IDs (Alloc, Gem)
1170 if err := o.validateFlow(flow); err != nil {
1171 oltLogger.WithFields(log.Fields{
1172 "OnuId": flow.OnuId,
1173 "IntfId": flow.AccessIntfId,
1174 "Flow": flow,
1175 "SerialNumber": onu.Sn(),
1176 "err": err,
1177 }).Error("invalid-flow-for-onu")
1178 return nil, err
1179 }
1180
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001181 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001182 o.storeAllocId(flow)
1183
Matteo Scandolof9d43412021-01-12 11:11:34 -08001184 msg := types.Message{
1185 Type: types.FlowAdd,
1186 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001187 PonPortID: pon.ID,
1188 OnuID: onu.ID,
1189 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001190 },
1191 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001192 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001193 }
1194
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001195 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001196}
1197
Pragya Arya8bdb4532020-03-02 17:08:09 +05301198// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301199func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001200
Pragya Arya8bdb4532020-03-02 17:08:09 +05301201 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001202 "AllocId": flow.AllocId,
1203 "Cookie": flow.Cookie,
1204 "FlowId": flow.FlowId,
1205 "FlowType": flow.FlowType,
1206 "GemportId": flow.GemportId,
1207 "IntfId": flow.AccessIntfId,
1208 "OnuId": flow.OnuId,
1209 "PortNo": flow.PortNo,
1210 "UniID": flow.UniId,
1211 "ReplicateFlow": flow.ReplicateFlow,
1212 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001213 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301214
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001215 olt.freeGemPortId(flow)
1216 olt.freeAllocId(flow)
1217
Pragya Arya8bdb4532020-03-02 17:08:09 +05301218 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001219 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301220 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001221 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301222 if !ok {
1223 oltLogger.Errorf("Flow %v not found", flow)
1224 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1225 }
1226
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001227 storedFlow := storedFlowIntf.(openolt.Flow)
1228
Pragya Arya8bdb4532020-03-02 17:08:09 +05301229 // if its ONU flow remove it from ONU also
1230 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001231 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1232 if err != nil {
1233 oltLogger.WithFields(log.Fields{
1234 "OnuId": storedFlow.OnuId,
1235 "IntfId": storedFlow.AccessIntfId,
1236 "PONs": olt.Pons,
1237 "err": err,
1238 }).Error("PON-port-not-found")
1239 return new(openolt.Empty), nil
1240 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301241 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1242 if err != nil {
1243 oltLogger.WithFields(log.Fields{
1244 "OnuId": storedFlow.OnuId,
1245 "IntfId": storedFlow.AccessIntfId,
1246 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001247 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301248 return new(openolt.Empty), nil
1249 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001250 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001251 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301252 }
1253
1254 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001255 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301256 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001257
1258 if flow.AccessIntfId == -1 {
1259 oltLogger.WithFields(log.Fields{
1260 "FlowId": flow.FlowId,
1261 }).Debug("Removing OLT flow")
1262 } else if flow.FlowType == "multicast" {
1263 oltLogger.WithFields(log.Fields{
1264 "FlowId": flow.FlowId,
1265 }).Debug("Removing OLT multicast flow")
1266 } else {
1267
1268 onu, err := o.GetOnuByFlowId(flow.FlowId)
1269 if err != nil {
1270 oltLogger.WithFields(log.Fields{
1271 "OnuId": flow.OnuId,
1272 "IntfId": flow.AccessIntfId,
1273 "err": err,
1274 }).Error("Can't find Onu")
1275 return nil, err
1276 }
1277
Matteo Scandolof9d43412021-01-12 11:11:34 -08001278 msg := types.Message{
1279 Type: types.FlowRemoved,
1280 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301281 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001282 },
1283 }
1284 onu.Channel <- msg
1285 }
1286
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001287 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001288}
1289
Shrey Baid688b4242020-07-10 20:40:10 +05301290func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301291 res := openolt.Heartbeat{HeartbeatSignature: o.signature}
Matteo Scandolo18859852020-01-15 13:33:57 -08001292 oltLogger.WithFields(log.Fields{
1293 "signature": res.HeartbeatSignature,
1294 }).Trace("HeartbeatCheck")
1295 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001296}
1297
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001298func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001299 for _, pon := range o.Pons {
1300 for _, onu := range pon.Onus {
1301 for _, fId := range onu.FlowIds {
1302 if fId == flowId {
1303 return onu, nil
1304 }
1305 }
1306 }
1307 }
Shrey Baid688b4242020-07-10 20:40:10 +05301308 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001309}
1310
Shrey Baid688b4242020-07-10 20:40:10 +05301311func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001312 devinfo := &openolt.DeviceInfo{
1313 Vendor: common.Config.Olt.Vendor,
1314 Model: common.Config.Olt.Model,
1315 HardwareVersion: common.Config.Olt.HardwareVersion,
1316 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001317 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001318 DeviceSerialNumber: o.SerialNumber,
1319 DeviceId: common.Config.Olt.DeviceId,
1320 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001321 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1322 }
1323
1324 for _, resRange := range common.PonsConfig.Ranges {
1325 intfIDs := []uint32{}
1326 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1327 intfIDs = append(intfIDs, uint32(i))
1328 }
1329
1330 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1331 IntfIds: intfIDs,
1332 Technology: resRange.Technology,
1333 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1334 {
1335 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1336 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1337 Start: resRange.OnuRange.StartId,
1338 End: resRange.OnuRange.EndId,
1339 },
1340 {
1341 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1342 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1343 Start: resRange.AllocIdRange.StartId,
1344 End: resRange.AllocIdRange.EndId,
1345 },
1346 {
1347 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1348 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1349 Start: resRange.GemportRange.StartId,
1350 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001351 },
1352 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001353 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001354 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001355
1356 oltLogger.WithFields(log.Fields{
1357 "Vendor": devinfo.Vendor,
1358 "Model": devinfo.Model,
1359 "HardwareVersion": devinfo.HardwareVersion,
1360 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001361 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001362 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1363 "DeviceId": devinfo.DeviceId,
1364 "PreviouslyConnected": devinfo.PreviouslyConnected,
1365 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1366
1367 // once we connect, set the flag
1368 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001369
1370 return devinfo, nil
1371}
1372
Shrey Baid688b4242020-07-10 20:40:10 +05301373func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001374 pon, err := o.GetPonById(omci_msg.IntfId)
1375 if err != nil {
1376 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001377 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001378 "onu_id": omci_msg.OnuId,
1379 "pon_id": omci_msg.IntfId,
1380 }).Error("pon ID not found")
1381 return nil, err
1382 }
1383
1384 onu, err := pon.GetOnuById(omci_msg.OnuId)
1385 if err != nil {
1386 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001387 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001388 "onu_id": omci_msg.OnuId,
1389 "pon_id": omci_msg.IntfId,
1390 }).Error("onu ID not found")
1391 return nil, err
1392 }
1393
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001394 oltLogger.WithFields(log.Fields{
1395 "IntfId": onu.PonPortID,
1396 "OnuId": onu.ID,
1397 "OnuSn": onu.Sn(),
1398 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001399 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1400 if err != nil {
1401 log.WithFields(log.Fields{
1402 "IntfId": onu.PonPortID,
1403 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001404 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001405 "err": err.Error(),
1406 }).Error("cannot-parse-OMCI-packet")
1407 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001408 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001409 if onu.InternalState.Current() == OnuStateDisabled {
1410 // if the ONU is disabled just drop the message
1411 log.WithFields(log.Fields{
1412 "IntfId": onu.PonPortID,
1413 "SerialNumber": onu.Sn(),
1414 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1415 "omciPkt": omciPkt,
1416 "omciMsgType": omciMsg.MessageType,
1417 }).Warn("dropping-omci-message")
1418 } else {
1419 msg := types.Message{
1420 Type: types.OMCI,
1421 Data: types.OmciMessage{
1422 OnuSN: onu.SerialNumber,
1423 OnuID: onu.ID,
1424 OmciMsg: omciMsg,
1425 OmciPkt: omciPkt,
1426 },
1427 }
1428 onu.Channel <- msg
1429 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001430 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001431}
1432
Matteo Scandolo8a574812021-05-20 15:18:53 -07001433// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301434func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001435 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001436 if err != nil {
1437 oltLogger.WithFields(log.Fields{
1438 "OnuId": onuPkt.OnuId,
1439 "IntfId": onuPkt.IntfId,
1440 "err": err,
1441 }).Error("Can't find PonPort")
1442 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001443 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001444 if err != nil {
1445 oltLogger.WithFields(log.Fields{
1446 "OnuId": onuPkt.OnuId,
1447 "IntfId": onuPkt.IntfId,
1448 "err": err,
1449 }).Error("Can't find Onu")
1450 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001451
Matteo Scandolo075b1892019-10-07 12:11:07 -07001452 oltLogger.WithFields(log.Fields{
1453 "IntfId": onu.PonPortID,
1454 "OnuId": onu.ID,
1455 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001456 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001457 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001458
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001459 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001460
1461 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001462 if err != nil {
1463 onuLogger.WithFields(log.Fields{
1464 "IntfId": onu.PonPortID,
1465 "OnuId": onu.ID,
1466 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001467 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001468 }).Error("Can't find pktType in packet, droppint it")
1469 return new(openolt.Empty), nil
1470 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001471
Matteo Scandolo4a036262020-08-17 15:56:13 -07001472 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001473 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001474 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001475 "IntfId": onu.PonPortID,
1476 "OnuId": onu.ID,
1477 "OnuSn": onu.Sn(),
1478 "Pkt": rawpkt.Data(),
1479 }).Error("Can't find Dst MacAddress in packet, droppint it")
1480 return new(openolt.Empty), nil
1481 }
1482
Matteo Scandolof9d43412021-01-12 11:11:34 -08001483 msg := types.Message{
1484 Type: types.OnuPacketOut,
1485 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001486 IntfId: onuPkt.IntfId,
1487 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001488 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001489 Packet: rawpkt,
1490 Type: pktType,
1491 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001492 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001493 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001494
Matteo Scandolo075b1892019-10-07 12:11:07 -07001495 onu.Channel <- msg
1496
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001497 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001498}
1499
Shrey Baid688b4242020-07-10 20:40:10 +05301500func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001501
1502 // OLT Reboot is called in two cases:
1503 // - 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)
1504 // - when an OLT needs to be rebooted (voltcl device reboot)
1505
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001506 oltLogger.WithFields(log.Fields{
1507 "oltId": o.ID,
1508 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301509 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301510 go func() { _ = o.RestartOLT() }()
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) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301515 oltLogger.WithFields(log.Fields{
1516 "oltId": o.ID,
1517 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301518 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301519
Pragya Arya2225f202020-01-29 18:05:01 +05301520 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001521 oltMsg := types.Message{
1522 Type: types.OltIndication,
1523 Data: types.OltIndicationMessage{
1524 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301525 },
Pragya Arya1881df02020-01-29 18:05:01 +05301526 }
Pragya Arya2225f202020-01-29 18:05:01 +05301527 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301528
Pragya Arya2225f202020-01-29 18:05:01 +05301529 for _, pon := range o.Pons {
1530 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001531 msg := types.Message{
1532 Type: types.PonIndication,
1533 Data: types.PonIndicationMessage{
1534 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301535 PonPortID: pon.ID,
1536 },
1537 }
1538 o.channel <- msg
1539 }
1540 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001541
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001542 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001543}
1544
Shrey Baid688b4242020-07-10 20:40:10 +05301545func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001546 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1547
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001548 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1549
1550 if err != nil {
1551 return nil, err
1552 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001553 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001554}
1555
Shrey Baid688b4242020-07-10 20:40:10 +05301556func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001557 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001558 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001559}
1560
Shrey Baid688b4242020-07-10 20:40:10 +05301561func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001562 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001563 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001564}
1565
Shrey Baid688b4242020-07-10 20:40:10 +05301566func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001567 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001568 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001569}
1570
Shrey Baid688b4242020-07-10 20:40:10 +05301571func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001572 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001573 return new(openolt.Empty), nil
1574}
1575
Matteo Scandolo8a574812021-05-20 15:18:53 -07001576func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1577 oltLogger.WithFields(log.Fields{
1578 "OnuId": tq.OnuId,
1579 "IntfId": tq.IntfId,
1580 "OnuPortNo": tq.PortNo,
1581 "UniId": tq.UniId,
1582 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001583 return new(openolt.Empty), nil
1584}
1585
Matteo Scandolo8a574812021-05-20 15:18:53 -07001586func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301587 oltLogger.WithFields(log.Fields{
1588 "OnuId": trafficSchedulers.OnuId,
1589 "IntfId": trafficSchedulers.IntfId,
1590 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001591 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301592 }).Info("received CreateTrafficSchedulers")
1593
1594 if !s.enablePerf {
1595 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1596 if err != nil {
1597 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1598 return new(openolt.Empty), err
1599 }
1600 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1601 if err != nil {
1602 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1603 return new(openolt.Empty), err
1604 }
1605 onu.TrafficSchedulers = trafficSchedulers
1606 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001607 return new(openolt.Empty), nil
1608}
1609
Shrey Baid688b4242020-07-10 20:40:10 +05301610func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301611 oltLogger.WithFields(log.Fields{
1612 "OnuId": trafficSchedulers.OnuId,
1613 "IntfId": trafficSchedulers.IntfId,
1614 "OnuPortNo": trafficSchedulers.PortNo,
1615 }).Info("received RemoveTrafficSchedulers")
1616 if !s.enablePerf {
1617 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1618 if err != nil {
1619 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1620 return new(openolt.Empty), err
1621 }
1622 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1623 if err != nil {
1624 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1625 return new(openolt.Empty), err
1626 }
1627
1628 onu.TrafficSchedulers = nil
1629 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001630 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001631}
Scott Baker41724b82020-01-21 19:54:53 -08001632
Matteo Scandolo618a6582020-09-09 12:21:29 -07001633func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1634 oltLogger.WithFields(log.Fields{
1635 "GroupId": group.GroupId,
1636 "Command": group.Command,
1637 "Members": group.Members,
1638 "Action": group.Action,
1639 }).Debug("received PerformGroupOperation")
1640 return &openolt.Empty{}, nil
1641}
1642
1643func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1644 oltLogger.WithFields(log.Fields{
1645 "GroupId": group.GroupId,
1646 "Command": group.Command,
1647 "Members": group.Members,
1648 "Action": group.Action,
1649 }).Debug("received PerformGroupOperation")
1650 return &openolt.Empty{}, nil
1651}
1652
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001653func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1654 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001655}
1656
1657func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1658 return &openolt.Empty{}, nil
1659}
1660
1661func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1662 return &openolt.OnuLogicalDistance{}, nil
1663}
1664
1665func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1666 return &openolt.OnuLogicalDistance{}, nil
1667}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001668
Girish Gowdra62f24292021-05-12 16:28:39 -07001669func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1670 return &openolt.PonRxPowerData{}, nil
1671}
1672
Matteo Scandolo96f89192021-03-12 13:17:26 -08001673func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1674 return &openolt.GemPortStatistics{}, nil
1675}
1676
1677func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1678 return &openolt.OnuStatistics{}, nil
1679}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001680
1681func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1682 o.AllocIDsLock.Lock()
1683 defer o.AllocIDsLock.Unlock()
1684
Matteo Scandolo21195d62021-04-07 14:31:23 -07001685 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1686 oltLogger.WithFields(log.Fields{
1687 "IntfId": flow.AccessIntfId,
1688 "OnuId": flow.OnuId,
1689 "PortNo": flow.PortNo,
1690 "GemportId": flow.GemportId,
1691 "FlowId": flow.FlowId,
1692 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1693 }
1694
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001695 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001696 "IntfId": flow.AccessIntfId,
1697 "OnuId": flow.OnuId,
1698 "PortNo": flow.PortNo,
1699 "GemportId": flow.GemportId,
1700 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001701 }).Trace("storing-alloc-id-via-flow")
1702
1703 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1704 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1705 }
1706 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1707 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1708 }
1709 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1710}
1711
1712func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1713 // if this is the last flow referencing the AllocId then remove it
1714 o.AllocIDsLock.Lock()
1715 defer o.AllocIDsLock.Unlock()
1716
1717 oltLogger.WithFields(log.Fields{
1718 "IntfId": flow.AccessIntfId,
1719 "OnuId": flow.OnuId,
1720 "PortNo": flow.PortNo,
1721 "GemportId": flow.GemportId,
1722 }).Trace("freeing-alloc-id-via-flow")
1723
1724 // NOTE look at the freeGemPortId implementation for comments and context
1725 for ponId, ponValues := range o.AllocIDs {
1726 for onuId, onuValues := range ponValues {
1727 for uniId, uniValues := range onuValues {
1728 for allocId, flows := range uniValues {
1729 for flowId := range flows {
1730 // if the flow matches, remove it from the map.
1731 if flow.FlowId == flowId {
1732 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1733 }
1734 // if that was the last flow for a particular allocId, remove the entire allocId
1735 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1736 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1737 }
1738 }
1739 }
1740 }
1741 }
1742 }
1743}
1744
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001745func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001746 o.GemPortIDsLock.Lock()
1747 defer o.GemPortIDsLock.Unlock()
1748
1749 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1750 oltLogger.WithFields(log.Fields{
1751 "IntfId": ponId,
1752 "OnuId": onuId,
1753 "PortNo": portNo,
1754 "GemportId": gemId,
1755 "FlowId": flowId,
1756 }).Error("trying-to-store-gemport-for-unknown-onu")
1757 }
1758
1759 oltLogger.WithFields(log.Fields{
1760 "IntfId": ponId,
1761 "OnuId": onuId,
1762 "PortNo": portNo,
1763 "GemportId": gemId,
1764 "FlowId": flowId,
1765 }).Trace("storing-alloc-id-via-flow")
1766
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001767 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1768 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1769 }
1770 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1771 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1772 }
1773 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1774}
1775
1776func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001777 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001778 "IntfId": flow.AccessIntfId,
1779 "OnuId": flow.OnuId,
1780 "PortNo": flow.PortNo,
1781 "GemportId": flow.GemportId,
1782 "FlowId": flow.FlowId,
1783 "ReplicateFlow": flow.ReplicateFlow,
1784 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001785 }).Trace("storing-gem-port-id-via-flow")
1786
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001787 if flow.ReplicateFlow {
1788 for _, gem := range flow.PbitToGemport {
1789 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1790 }
1791 } else {
1792 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001793 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001794}
1795
1796func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1797 // if this is the last flow referencing the GemPort then remove it
1798 o.GemPortIDsLock.Lock()
1799 defer o.GemPortIDsLock.Unlock()
1800
1801 oltLogger.WithFields(log.Fields{
1802 "IntfId": flow.AccessIntfId,
1803 "OnuId": flow.OnuId,
1804 "PortNo": flow.PortNo,
1805 "GemportId": flow.GemportId,
1806 }).Trace("freeing-gem-port-id-via-flow")
1807
1808 // NOTE that this loop is not very performant, it would be better if the flow carries
1809 // the same information that it carries during a FlowAdd. If so we can directly remove
1810 // items from the map
1811
1812 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1813 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1814 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1815 //}
1816
1817 // NOTE this loop assumes that flow IDs are unique per device
1818 for ponId, ponValues := range o.GemPortIDs {
1819 for onuId, onuValues := range ponValues {
1820 for uniId, uniValues := range onuValues {
1821 for gemId, flows := range uniValues {
1822 for flowId := range flows {
1823 // if the flow matches, remove it from the map.
1824 if flow.FlowId == flowId {
1825 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1826 }
1827 // if that was the last flow for a particular gem, remove the entire gem
1828 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1829 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1830 }
1831 }
1832 }
1833 }
1834 }
1835 }
1836}
1837
1838// validateFlow checks that:
1839// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1840// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1841func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001842 // validate gemPort
1843 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001844 defer o.GemPortIDsLock.RUnlock()
1845 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001846 if onuId == uint32(flow.OnuId) {
1847 continue
1848 }
1849 for uniId, uni := range onu {
1850 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001851 if flow.ReplicateFlow {
1852 for _, flowGem := range flow.PbitToGemport {
1853 if gem == int32(flowGem) {
1854 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1855 }
1856 }
1857 } else {
1858 if gem == flow.GemportId {
1859 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1860 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001861 }
1862 }
1863 }
1864 }
1865
1866 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001867 defer o.AllocIDsLock.RUnlock()
1868 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001869 if onuId == uint32(flow.OnuId) {
1870 continue
1871 }
1872 for uniId, uni := range onu {
1873 for allocId := range uni {
1874 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001875 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 -08001876 }
1877 }
1878 }
1879 }
1880
1881 return nil
1882}
1883
1884// clearAllResources is invoked up OLT Reboot to remove all the allocated
1885// GemPorts, AllocId and ONU-IDs across the PONs
1886func (o *OltDevice) clearAllResources() {
1887
1888 // remove the resources received via flows
1889 o.GemPortIDsLock.Lock()
1890 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1891 o.GemPortIDsLock.Unlock()
1892 o.AllocIDsLock.Lock()
1893 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1894 o.AllocIDsLock.Unlock()
1895
1896 // remove the resources received via OMCI
1897 for _, pon := range o.Pons {
1898 pon.removeAllAllocIds()
1899 pon.removeAllGemPorts()
1900 pon.removeAllOnuIds()
1901 }
1902}