blob: bbe49bcbf1794ca360adcf5c7ca1de82e06b84e8 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
Joey Armstrong14628cd2023-01-10 08:38:31 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo11006992019-08-28 11:29:46 -07003
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 {
TorstenThieme37ddd392022-07-13 12:56:24 +0000504 if o.ControlledActivation != OnlyONU {
505 onu.ReDiscoverOnu(true)
506 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700507 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
508
509 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700510 for _, uni := range onu.UniPorts {
511 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700512 }
513 }
Pragya Arya2225f202020-01-29 18:05:01 +0530514 }
515 } else {
516
517 // 1. controlledActivation == Default: Send both PON and ONUs indications
518 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
519
520 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
521 // send PON Port indications
522 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800523 msg := types.Message{
524 Type: types.PonIndication,
525 Data: types.PonIndicationMessage{
526 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530527 PonPortID: pon.ID,
528 },
529 }
530 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700531 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700532 }
533 }
534
Pragya Arya996a0892020-03-09 21:47:52 +0530535 if !o.enablePerf {
536 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700537 wg.Add(1)
538 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530539 }
540
Matteo Scandolo4747d292019-08-05 11:50:18 -0700541 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700542 oltLogger.WithFields(log.Fields{
543 "stream": stream,
544 }).Debug("OpenOLT Stream closed")
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100545
546 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547}
548
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700549func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530550 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700551
552loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530553 for {
554 select {
555 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
556 // send NNI port stats
557 for _, port := range o.Nnis {
558 incrementStat := true
559 if port.OperState.Current() == "down" {
560 incrementStat = false
561 }
562 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700563 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530564 }
565
566 // send PON port stats
567 for _, port := range o.Pons {
568 incrementStat := true
569 // do not increment port stats if PON port is down or no ONU is activated on PON port
570 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
571 incrementStat = false
572 }
573 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700574 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530575 }
576 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700577 oltLogger.Debug("Stop sending port stats")
578 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530579 }
Pragya Arya996a0892020-03-09 21:47:52 +0530580 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700581 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530582}
583
Matteo Scandolo4747d292019-08-05 11:50:18 -0700584// Helpers method
585
Matteo Scandolof9d43412021-01-12 11:11:34 -0800586func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
587
588 switch interfaceType {
589 case "nni":
590 if !o.HasNni(interfaceId) {
591 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
592 }
593
594 case "pon":
595 if !o.HasPon(interfaceId) {
596 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
597 }
598 }
599
600 alarmIndication := &openolt.AlarmIndication{
601 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
602 Status: alarmStatus,
603 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
604 }},
605 }
606
607 msg := types.Message{
608 Type: types.AlarmIndication,
609 Data: alarmIndication,
610 }
611
612 o.channel <- msg
613
614 return nil
615}
616
617func (o *OltDevice) HasNni(id uint32) bool {
618 for _, intf := range o.Nnis {
619 if intf.ID == id {
620 return true
621 }
622 }
623 return false
624}
625
626func (o *OltDevice) HasPon(id uint32) bool {
627 for _, intf := range o.Pons {
628 if intf.ID == id {
629 return true
630 }
631 }
632 return false
633}
634
Shrey Baid688b4242020-07-10 20:40:10 +0530635func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636 for _, pon := range o.Pons {
637 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700638 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639 }
640 }
Shrey Baid688b4242020-07-10 20:40:10 +0530641 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642}
643
Shrey Baid688b4242020-07-10 20:40:10 +0530644func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700645 for _, nni := range o.Nnis {
646 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700647 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700648 }
649 }
Shrey Baid688b4242020-07-10 20:40:10 +0530650 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700651}
652
Scott Baker41724b82020-01-21 19:54:53 -0800653func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
654 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
655 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
656 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
657 return
658 }
659
660 oltLogger.WithFields(log.Fields{
661 "AlarmIndication": alarmInd,
662 }).Debug("Sent Indication_AlarmInd")
663}
664
Matteo Scandolof9d43412021-01-12 11:11:34 -0800665func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700666 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
667 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700668 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800669 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700670 }
671
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700672 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700673 "OperState": msg.OperState,
674 }).Debug("Sent Indication_OltInd")
675}
676
Matteo Scandolof9d43412021-01-12 11:11:34 -0800677func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700678 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800679 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800680 if err := nni.OperState.Event("enable"); err != nil {
681 log.WithFields(log.Fields{
682 "Type": nni.Type,
683 "IntfId": nni.ID,
684 "OperState": nni.OperState.Current(),
685 }).Errorf("Can't move NNI Port to enabled state: %v", err)
686 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800687 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800688 if err := nni.OperState.Event("disable"); err != nil {
689 log.WithFields(log.Fields{
690 "Type": nni.Type,
691 "IntfId": nni.ID,
692 "OperState": nni.OperState.Current(),
693 }).Errorf("Can't move NNI Port to disable state: %v", err)
694 }
695 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700696 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700697 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700698 Type: nni.Type,
699 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700700 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100701 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700702 }}
703
704 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700705 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800706 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700707 }
708
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700709 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700710 "Type": nni.Type,
711 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700712 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100713 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700714 }).Debug("Sent Indication_IntfOperInd for NNI")
715}
716
Pragya Arya2225f202020-01-29 18:05:01 +0530717func (o *OltDevice) sendPonIndication(ponPortID uint32) {
718
Matteo Scandolo4a036262020-08-17 15:56:13 -0700719 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530720 pon, _ := o.GetPonById(ponPortID)
721 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700722 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700723 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700724 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700725 }}
726
727 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700728 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800729 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700730 }
731
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700732 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700733 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700734 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700735 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700736
Pragya Arya2225f202020-01-29 18:05:01 +0530737 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700738 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700739 Type: pon.Type,
740 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700741 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700742 }}
743
744 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700745 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800746 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700747 }
748
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700749 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700750 "Type": pon.Type,
751 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700752 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700753 }).Debug("Sent Indication_IntfOperInd for PON")
754}
755
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700756func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100757 if o.InternalState.Current() == OltInternalStateEnabled {
Shrey Baid55f328c2020-07-07 19:20:42 +0530758 oltLogger.WithFields(log.Fields{
759 "Type": portType,
760 "IntfId": portID,
761 }).Trace("Sending port stats")
762 stats.IntfId = InterfaceIDToPortNo(portID, portType)
763 data := &openolt.Indication_PortStats{
764 PortStats: stats,
765 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700766
Shrey Baid55f328c2020-07-07 19:20:42 +0530767 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
768 oltLogger.Errorf("Failed to send PortStats: %v", err)
769 return
770 }
Pragya Arya996a0892020-03-09 21:47:52 +0530771 }
772}
773
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100774// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700775func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
776 oltLogger.WithFields(log.Fields{
777 "stream": stream,
778 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000779 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700780
David Bainbridge103cf022019-12-16 20:11:35 +0000781loop:
782 for {
783 select {
784 case <-ctx.Done():
785 oltLogger.Debug("OLT Indication processing canceled via context")
786 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700787 // do not terminate this loop if the stream is closed,
788 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
789 //case <-stream.Context().Done():
790 // oltLogger.Debug("OLT Indication processing canceled via stream context")
791 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000792 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700793 if !ok {
794 if ctx.Err() != nil {
795 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
796 }
797 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000798 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700799 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700800
David Bainbridge103cf022019-12-16 20:11:35 +0000801 oltLogger.WithFields(log.Fields{
802 "oltId": o.ID,
803 "messageType": message.Type,
804 }).Trace("Received message")
805
806 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800807 case types.OltIndication:
808 msg, _ := message.Data.(types.OltIndicationMessage)
809 if msg.OperState == types.UP {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100810 _ = o.InternalState.Event(OltInternalTxEnable)
Shrey Baid688b4242020-07-10 20:40:10 +0530811 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800812 } else if msg.OperState == types.DOWN {
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100813 _ = o.InternalState.Event(OltInternalTxDisable)
Shrey Baid688b4242020-07-10 20:40:10 +0530814 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000815 }
816 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800817 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800818 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
819 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800820 case types.NniIndication:
821 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000822 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800823 case types.PonIndication:
824 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530825 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800826 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530827 if err := pon.OperState.Event("enable"); err != nil {
828 oltLogger.WithFields(log.Fields{
829 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800830 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530831 }).Error("Can't Enable Oper state for PON Port")
832 }
833 if err := pon.InternalState.Event("enable"); err != nil {
834 oltLogger.WithFields(log.Fields{
835 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800836 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530837 }).Error("Can't Enable Internal state for PON Port")
838 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800839 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530840 if err := pon.OperState.Event("disable"); err != nil {
841 oltLogger.WithFields(log.Fields{
842 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800843 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530844 }).Error("Can't Disable Oper state for PON Port")
845 }
846 if err := pon.InternalState.Event("disable"); err != nil {
847 oltLogger.WithFields(log.Fields{
848 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800849 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530850 }).Error("Can't Disable Internal state for PON Port")
851 }
Pragya Arya2225f202020-01-29 18:05:01 +0530852 }
David Bainbridge103cf022019-12-16 20:11:35 +0000853 default:
854 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
855 }
856 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700857 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100858 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700859 oltLogger.WithFields(log.Fields{
860 "stream": stream,
861 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700862}
863
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700864// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530865func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700866 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700867 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700868 for _, pon := range o.Pons {
869 for _, onu := range pon.Onus {
870 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700871 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700872 }
873 }
874 }
875
Shrey Baid688b4242020-07-10 20:40:10 +0530876 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700877}
878
William Kurkian9dadc5b2019-10-22 13:51:57 -0400879// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530880func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700881 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400882 // memoizing it will remove the bottleneck
883 for _, pon := range o.Pons {
884 if pon.ID == intfId {
885 for _, onu := range pon.Onus {
886 if onu.ID == onuId {
887 return onu, nil
888 }
889 }
890 }
891 }
Shrey Baid688b4242020-07-10 20:40:10 +0530892 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400893}
894
Matteo Scandolo4a036262020-08-17 15:56:13 -0700895// returns a Service with a given Mac Address
896func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700897 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700898 // memoizing it will remove the bottleneck
899 for _, pon := range o.Pons {
900 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700901 s, err := onu.findServiceByMacAddress(mac)
902 if err == nil {
903 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700904 }
905 }
906 }
907
Matteo Scandolo4a036262020-08-17 15:56:13 -0700908 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700909}
910
Matteo Scandolo4747d292019-08-05 11:50:18 -0700911// GRPC Endpoints
912
Shrey Baid688b4242020-07-10 20:40:10 +0530913func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700914
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700915 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800916
Matteo Scandolo8a574812021-05-20 15:18:53 -0700917 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800918 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
919 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
920
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700921 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700922
923 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
924 oltLogger.WithFields(log.Fields{
925 "OnuSn": _onu.Sn(),
926 }).Info("Received ActivateOnu call from VOLTHA")
927
William Kurkian0418bc82019-11-06 12:16:24 -0500928 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700929
Matteo Scandolocedde462021-03-09 17:37:16 -0800930 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700931 oltLogger.WithFields(log.Fields{
932 "IntfId": _onu.PonPortID,
933 "OnuSn": _onu.Sn(),
934 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800935 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700936 }
937
938 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
939
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700940 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700941}
942
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800943func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700944 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700945 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700946}
947
Shrey Baid688b4242020-07-10 20:40:10 +0530948func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530949 oltLogger.WithFields(log.Fields{
950 "IntfId": onu.IntfId,
951 "OnuId": onu.OnuId,
952 }).Info("Received DeleteOnu call from VOLTHA")
953
954 pon, err := o.GetPonById(onu.IntfId)
955 if err != nil {
956 oltLogger.WithFields(log.Fields{
957 "OnuId": onu.OnuId,
958 "IntfId": onu.IntfId,
959 "err": err,
960 }).Error("Can't find PonPort")
961 }
962 _onu, err := pon.GetOnuById(onu.OnuId)
963 if err != nil {
964 oltLogger.WithFields(log.Fields{
965 "OnuId": onu.OnuId,
966 "IntfId": onu.IntfId,
967 "err": err,
968 }).Error("Can't find Onu")
969 }
970
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530971 if _onu.InternalState.Current() != OnuStateDisabled {
972 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
973 oltLogger.WithFields(log.Fields{
974 "IntfId": _onu.PonPortID,
975 "OnuSn": _onu.Sn(),
976 "OnuId": _onu.ID,
977 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
978 }
Hardik Windlassad790cb2020-06-17 21:26:22 +0530979 }
980
Hardik Windlassad790cb2020-06-17 21:26:22 +0530981 // ONU Re-Discovery
Elia Battiston67e9e4c2022-02-15 16:38:40 +0100982 if o.InternalState.Current() == OltInternalStateEnabled && pon.InternalState.Current() == "enabled" {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +0530983 go _onu.ReDiscoverOnu(false)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530984 }
985
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700986 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700987}
988
Shrey Baid688b4242020-07-10 20:40:10 +0530989func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700990 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800991 oltLogger.WithFields(log.Fields{
992 "oltId": o.ID,
993 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530994 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800995
Matteo Scandolo401503a2019-12-11 14:48:14 -0800996 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530997 if pon.InternalState.Current() == "enabled" {
998 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800999 msg := types.Message{
1000 Type: types.PonIndication,
1001 Data: types.PonIndicationMessage{
1002 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +05301003 PonPortID: pon.ID,
1004 },
1005 }
1006 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001007 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001008 }
1009
Matteo Scandolo401503a2019-12-11 14:48:14 -08001010 // Note that we are not disabling the NNI as the real OLT does not.
1011 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001012
1013 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001014 oltMsg := types.Message{
1015 Type: types.OltIndication,
1016 Data: types.OltIndicationMessage{
1017 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001018 },
1019 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001020 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001021
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001022 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001023}
1024
Shrey Baid688b4242020-07-10 20:40:10 +05301025func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301026 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001027 ponID := intf.GetIntfId()
1028 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001029
Matteo Scandolof9d43412021-01-12 11:11:34 -08001030 msg := types.Message{
1031 Type: types.PonIndication,
1032 Data: types.PonIndicationMessage{
1033 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001034 PonPortID: ponID,
1035 },
1036 }
1037 o.channel <- msg
1038
1039 for _, onu := range pon.Onus {
1040
Matteo Scandolof9d43412021-01-12 11:11:34 -08001041 onuIndication := types.OnuIndicationMessage{
1042 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001043 PonPortID: ponID,
1044 OnuID: onu.ID,
1045 OnuSN: onu.SerialNumber,
1046 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001047 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001048
1049 }
1050
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001051 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001052}
1053
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001054func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001055 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301056 publishEvent("OLT-enable-received", -1, -1, "")
Elia Battiston67e9e4c2022-02-15 16:38:40 +01001057 return o.Enable(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001058}
1059
Shrey Baid688b4242020-07-10 20:40:10 +05301060func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301061 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301062 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001063 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001064
Matteo Scandolof9d43412021-01-12 11:11:34 -08001065 msg := types.Message{
1066 Type: types.PonIndication,
1067 Data: types.PonIndicationMessage{
1068 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301069 PonPortID: ponID,
1070 },
1071 }
1072 o.channel <- msg
1073
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001074 for _, onu := range pon.Onus {
1075
Matteo Scandolof9d43412021-01-12 11:11:34 -08001076 onuIndication := types.OnuIndicationMessage{
1077 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001078 PonPortID: ponID,
1079 OnuID: onu.ID,
1080 OnuSN: onu.SerialNumber,
1081 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001082 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001083
1084 }
1085
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001086 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001087}
1088
Shrey Baid688b4242020-07-10 20:40:10 +05301089func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001090 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001091 "IntfId": flow.AccessIntfId,
1092 "OnuId": flow.OnuId,
1093 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001094 "InnerVlan": flow.Classifier.IVid,
1095 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001096 "FlowType": flow.FlowType,
1097 "FlowId": flow.FlowId,
1098 "UniID": flow.UniId,
1099 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301100 }).Tracef("OLT receives FlowAdd")
1101
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001102 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301103 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001104 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001105 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301106 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001107
1108 if flow.AccessIntfId == -1 {
1109 oltLogger.WithFields(log.Fields{
1110 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001111 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001112 } else if flow.FlowType == "multicast" {
1113 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001114 "Cookie": flow.Cookie,
1115 "DstPort": flow.Classifier.DstPort,
1116 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1117 "FlowId": flow.FlowId,
1118 "FlowType": flow.FlowType,
1119 "GemportId": flow.GemportId,
1120 "InnerVlan": flow.Classifier.IVid,
1121 "IntfId": flow.AccessIntfId,
1122 "IpProto": flow.Classifier.IpProto,
1123 "OnuId": flow.OnuId,
1124 "OuterVlan": flow.Classifier.OVid,
1125 "PortNo": flow.PortNo,
1126 "SrcPort": flow.Classifier.SrcPort,
1127 "UniID": flow.UniId,
1128 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001129 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001130 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001131 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001132 if err != nil {
1133 oltLogger.WithFields(log.Fields{
1134 "OnuId": flow.OnuId,
1135 "IntfId": flow.AccessIntfId,
1136 "err": err,
1137 }).Error("Can't find PonPort")
1138 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001139 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001140 if err != nil {
1141 oltLogger.WithFields(log.Fields{
1142 "OnuId": flow.OnuId,
1143 "IntfId": flow.AccessIntfId,
1144 "err": err,
1145 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001146 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001147 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001148
1149 // if the ONU is disabled reject the flow
1150 // as per VOL-4061 there is a small window during which the ONU is disabled
1151 // but the port has not been reported as down to ONOS
1152 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1153 oltLogger.WithFields(log.Fields{
1154 "OnuId": flow.OnuId,
1155 "IntfId": flow.AccessIntfId,
1156 "Flow": flow,
1157 "SerialNumber": onu.Sn(),
1158 "InternalState": onu.InternalState.Current(),
1159 }).Error("rejected-flow-because-of-onu-state")
1160 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1161 }
1162
Pragya Arya8bdb4532020-03-02 17:08:09 +05301163 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001164 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301165 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001166 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001167 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301168 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301169 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001170
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001171 // validate that the flow reference correct IDs (Alloc, Gem)
1172 if err := o.validateFlow(flow); err != nil {
1173 oltLogger.WithFields(log.Fields{
1174 "OnuId": flow.OnuId,
1175 "IntfId": flow.AccessIntfId,
1176 "Flow": flow,
1177 "SerialNumber": onu.Sn(),
1178 "err": err,
1179 }).Error("invalid-flow-for-onu")
1180 return nil, err
1181 }
1182
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301183 if err := o.storeGemPortIdByFlow(flow); err != nil {
1184 return nil, err
1185 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001186 o.storeAllocId(flow)
1187
Matteo Scandolof9d43412021-01-12 11:11:34 -08001188 msg := types.Message{
1189 Type: types.FlowAdd,
1190 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001191 PonPortID: pon.ID,
1192 OnuID: onu.ID,
1193 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001194 },
1195 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001196 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001197 }
1198
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001199 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001200}
1201
Pragya Arya8bdb4532020-03-02 17:08:09 +05301202// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301203func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001204
Pragya Arya8bdb4532020-03-02 17:08:09 +05301205 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001206 "AllocId": flow.AllocId,
1207 "Cookie": flow.Cookie,
1208 "FlowId": flow.FlowId,
1209 "FlowType": flow.FlowType,
1210 "GemportId": flow.GemportId,
1211 "IntfId": flow.AccessIntfId,
1212 "OnuId": flow.OnuId,
1213 "PortNo": flow.PortNo,
1214 "UniID": flow.UniId,
1215 "ReplicateFlow": flow.ReplicateFlow,
1216 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001217 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301218
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001219 olt.freeGemPortId(flow)
1220 olt.freeAllocId(flow)
1221
Pragya Arya8bdb4532020-03-02 17:08:09 +05301222 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001223 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301224 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001225 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301226 if !ok {
1227 oltLogger.Errorf("Flow %v not found", flow)
1228 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1229 }
1230
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001231 storedFlow := storedFlowIntf.(openolt.Flow)
1232
Pragya Arya8bdb4532020-03-02 17:08:09 +05301233 // if its ONU flow remove it from ONU also
1234 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001235 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1236 if err != nil {
1237 oltLogger.WithFields(log.Fields{
1238 "OnuId": storedFlow.OnuId,
1239 "IntfId": storedFlow.AccessIntfId,
1240 "PONs": olt.Pons,
1241 "err": err,
1242 }).Error("PON-port-not-found")
1243 return new(openolt.Empty), nil
1244 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301245 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1246 if err != nil {
1247 oltLogger.WithFields(log.Fields{
1248 "OnuId": storedFlow.OnuId,
1249 "IntfId": storedFlow.AccessIntfId,
1250 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001251 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301252 return new(openolt.Empty), nil
1253 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001254 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001255 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301256 }
1257
1258 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001259 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301260 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001261
1262 if flow.AccessIntfId == -1 {
1263 oltLogger.WithFields(log.Fields{
1264 "FlowId": flow.FlowId,
1265 }).Debug("Removing OLT flow")
1266 } else if flow.FlowType == "multicast" {
1267 oltLogger.WithFields(log.Fields{
1268 "FlowId": flow.FlowId,
1269 }).Debug("Removing OLT multicast flow")
1270 } else {
1271
1272 onu, err := o.GetOnuByFlowId(flow.FlowId)
1273 if err != nil {
1274 oltLogger.WithFields(log.Fields{
1275 "OnuId": flow.OnuId,
1276 "IntfId": flow.AccessIntfId,
1277 "err": err,
1278 }).Error("Can't find Onu")
1279 return nil, err
1280 }
1281
Matteo Scandolof9d43412021-01-12 11:11:34 -08001282 msg := types.Message{
1283 Type: types.FlowRemoved,
1284 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301285 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001286 },
1287 }
1288 onu.Channel <- msg
1289 }
1290
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001291 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001292}
1293
Shrey Baid688b4242020-07-10 20:40:10 +05301294func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301295 res := openolt.Heartbeat{HeartbeatSignature: o.signature}
Matteo Scandolo18859852020-01-15 13:33:57 -08001296 oltLogger.WithFields(log.Fields{
1297 "signature": res.HeartbeatSignature,
1298 }).Trace("HeartbeatCheck")
1299 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001300}
1301
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001302func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001303 for _, pon := range o.Pons {
1304 for _, onu := range pon.Onus {
1305 for _, fId := range onu.FlowIds {
1306 if fId == flowId {
1307 return onu, nil
1308 }
1309 }
1310 }
1311 }
Shrey Baid688b4242020-07-10 20:40:10 +05301312 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001313}
1314
Shrey Baid688b4242020-07-10 20:40:10 +05301315func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolocedde462021-03-09 17:37:16 -08001316 devinfo := &openolt.DeviceInfo{
1317 Vendor: common.Config.Olt.Vendor,
1318 Model: common.Config.Olt.Model,
1319 HardwareVersion: common.Config.Olt.HardwareVersion,
1320 FirmwareVersion: common.Config.Olt.FirmwareVersion,
Matteo Scandolocedde462021-03-09 17:37:16 -08001321 PonPorts: uint32(o.NumPon),
Matteo Scandolocedde462021-03-09 17:37:16 -08001322 DeviceSerialNumber: o.SerialNumber,
1323 DeviceId: common.Config.Olt.DeviceId,
1324 PreviouslyConnected: o.PreviouslyConnected,
Elia Battistonb7bea222022-02-18 16:25:00 +01001325 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{},
1326 }
1327
1328 for _, resRange := range common.PonsConfig.Ranges {
1329 intfIDs := []uint32{}
1330 for i := resRange.PonRange.StartId; i <= resRange.PonRange.EndId; i++ {
1331 intfIDs = append(intfIDs, uint32(i))
1332 }
1333
1334 devinfo.Ranges = append(devinfo.Ranges, &openolt.DeviceInfo_DeviceResourceRanges{
1335 IntfIds: intfIDs,
1336 Technology: resRange.Technology,
1337 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1338 {
1339 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1340 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1341 Start: resRange.OnuRange.StartId,
1342 End: resRange.OnuRange.EndId,
1343 },
1344 {
1345 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1346 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1347 Start: resRange.AllocIdRange.StartId,
1348 End: resRange.AllocIdRange.EndId,
1349 },
1350 {
1351 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1352 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1353 Start: resRange.GemportRange.StartId,
1354 End: resRange.GemportRange.EndId,
Matteo Scandolocedde462021-03-09 17:37:16 -08001355 },
1356 },
Elia Battistonb7bea222022-02-18 16:25:00 +01001357 })
Matteo Scandolocedde462021-03-09 17:37:16 -08001358 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001359
1360 oltLogger.WithFields(log.Fields{
1361 "Vendor": devinfo.Vendor,
1362 "Model": devinfo.Model,
1363 "HardwareVersion": devinfo.HardwareVersion,
1364 "FirmwareVersion": devinfo.FirmwareVersion,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001365 "PonPorts": devinfo.PonPorts,
Matteo Scandolo96f89192021-03-12 13:17:26 -08001366 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1367 "DeviceId": devinfo.DeviceId,
1368 "PreviouslyConnected": devinfo.PreviouslyConnected,
1369 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1370
1371 // once we connect, set the flag
1372 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001373
1374 return devinfo, nil
1375}
1376
Shrey Baid688b4242020-07-10 20:40:10 +05301377func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001378 pon, err := o.GetPonById(omci_msg.IntfId)
1379 if err != nil {
1380 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001381 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001382 "onu_id": omci_msg.OnuId,
1383 "pon_id": omci_msg.IntfId,
1384 }).Error("pon ID not found")
1385 return nil, err
1386 }
1387
1388 onu, err := pon.GetOnuById(omci_msg.OnuId)
1389 if err != nil {
1390 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001391 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001392 "onu_id": omci_msg.OnuId,
1393 "pon_id": omci_msg.IntfId,
1394 }).Error("onu ID not found")
1395 return nil, err
1396 }
1397
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001398 oltLogger.WithFields(log.Fields{
1399 "IntfId": onu.PonPortID,
1400 "OnuId": onu.ID,
1401 "OnuSn": onu.Sn(),
1402 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001403 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1404 if err != nil {
1405 log.WithFields(log.Fields{
1406 "IntfId": onu.PonPortID,
1407 "SerialNumber": onu.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001408 "omciPacket": hex.EncodeToString(omci_msg.Pkt),
Matteo Scandolob5913142021-03-19 16:10:18 -07001409 "err": err.Error(),
1410 }).Error("cannot-parse-OMCI-packet")
1411 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001412 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001413 if onu.InternalState.Current() == OnuStateDisabled {
1414 // if the ONU is disabled just drop the message
1415 log.WithFields(log.Fields{
1416 "IntfId": onu.PonPortID,
1417 "SerialNumber": onu.Sn(),
1418 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1419 "omciPkt": omciPkt,
1420 "omciMsgType": omciMsg.MessageType,
1421 }).Warn("dropping-omci-message")
1422 } else {
1423 msg := types.Message{
1424 Type: types.OMCI,
1425 Data: types.OmciMessage{
1426 OnuSN: onu.SerialNumber,
1427 OnuID: onu.ID,
1428 OmciMsg: omciMsg,
1429 OmciPkt: omciPkt,
1430 },
1431 }
1432 onu.Channel <- msg
1433 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001434 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001435}
1436
Matteo Scandolo8a574812021-05-20 15:18:53 -07001437// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301438func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001439 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001440 if err != nil {
1441 oltLogger.WithFields(log.Fields{
1442 "OnuId": onuPkt.OnuId,
1443 "IntfId": onuPkt.IntfId,
1444 "err": err,
1445 }).Error("Can't find PonPort")
1446 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001447 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001448 if err != nil {
1449 oltLogger.WithFields(log.Fields{
1450 "OnuId": onuPkt.OnuId,
1451 "IntfId": onuPkt.IntfId,
1452 "err": err,
1453 }).Error("Can't find Onu")
1454 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001455
Matteo Scandolo075b1892019-10-07 12:11:07 -07001456 oltLogger.WithFields(log.Fields{
1457 "IntfId": onu.PonPortID,
1458 "OnuId": onu.ID,
1459 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001460 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001461 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001462
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001463 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001464
1465 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001466 if err != nil {
1467 onuLogger.WithFields(log.Fields{
1468 "IntfId": onu.PonPortID,
1469 "OnuId": onu.ID,
1470 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001471 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001472 }).Error("Can't find pktType in packet, droppint it")
1473 return new(openolt.Empty), nil
1474 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001475
Matteo Scandolo4a036262020-08-17 15:56:13 -07001476 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001477 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001478 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001479 "IntfId": onu.PonPortID,
1480 "OnuId": onu.ID,
1481 "OnuSn": onu.Sn(),
1482 "Pkt": rawpkt.Data(),
1483 }).Error("Can't find Dst MacAddress in packet, droppint it")
1484 return new(openolt.Empty), nil
1485 }
1486
Matteo Scandolof9d43412021-01-12 11:11:34 -08001487 msg := types.Message{
1488 Type: types.OnuPacketOut,
1489 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001490 IntfId: onuPkt.IntfId,
1491 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001492 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001493 Packet: rawpkt,
1494 Type: pktType,
1495 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001496 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001497 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001498
Matteo Scandolo075b1892019-10-07 12:11:07 -07001499 onu.Channel <- msg
1500
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001501 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001502}
1503
Shrey Baid688b4242020-07-10 20:40:10 +05301504func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001505
1506 // OLT Reboot is called in two cases:
1507 // - 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)
1508 // - when an OLT needs to be rebooted (voltcl device reboot)
1509
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001510 oltLogger.WithFields(log.Fields{
1511 "oltId": o.ID,
1512 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301513 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301514 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001515 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001516}
1517
Shrey Baid688b4242020-07-10 20:40:10 +05301518func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301519 oltLogger.WithFields(log.Fields{
1520 "oltId": o.ID,
1521 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301522 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301523
Pragya Arya2225f202020-01-29 18:05:01 +05301524 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001525 oltMsg := types.Message{
1526 Type: types.OltIndication,
1527 Data: types.OltIndicationMessage{
1528 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301529 },
Pragya Arya1881df02020-01-29 18:05:01 +05301530 }
Pragya Arya2225f202020-01-29 18:05:01 +05301531 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301532
Pragya Arya2225f202020-01-29 18:05:01 +05301533 for _, pon := range o.Pons {
1534 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001535 msg := types.Message{
1536 Type: types.PonIndication,
1537 Data: types.PonIndicationMessage{
1538 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301539 PonPortID: pon.ID,
1540 },
1541 }
1542 o.channel <- msg
1543 }
1544 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001545
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001546 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001547}
1548
Shrey Baid688b4242020-07-10 20:40:10 +05301549func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001550 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1551
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001552 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1553
1554 if err != nil {
1555 return nil, err
1556 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001557 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001558}
1559
Shrey Baid688b4242020-07-10 20:40:10 +05301560func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001561 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001562 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001563}
1564
Shrey Baid688b4242020-07-10 20:40:10 +05301565func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001566 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001567 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001568}
1569
Shrey Baid688b4242020-07-10 20:40:10 +05301570func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001571 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001572 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001573}
1574
Shrey Baid688b4242020-07-10 20:40:10 +05301575func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001576 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001577 return new(openolt.Empty), nil
1578}
1579
Matteo Scandolo8a574812021-05-20 15:18:53 -07001580func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1581 oltLogger.WithFields(log.Fields{
1582 "OnuId": tq.OnuId,
1583 "IntfId": tq.IntfId,
1584 "OnuPortNo": tq.PortNo,
1585 "UniId": tq.UniId,
1586 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001587 return new(openolt.Empty), nil
1588}
1589
Matteo Scandolo8a574812021-05-20 15:18:53 -07001590func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301591 oltLogger.WithFields(log.Fields{
1592 "OnuId": trafficSchedulers.OnuId,
1593 "IntfId": trafficSchedulers.IntfId,
1594 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001595 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301596 }).Info("received CreateTrafficSchedulers")
1597
1598 if !s.enablePerf {
1599 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1600 if err != nil {
1601 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1602 return new(openolt.Empty), err
1603 }
1604 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1605 if err != nil {
1606 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1607 return new(openolt.Empty), err
1608 }
1609 onu.TrafficSchedulers = trafficSchedulers
1610 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001611 return new(openolt.Empty), nil
1612}
1613
Shrey Baid688b4242020-07-10 20:40:10 +05301614func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301615 oltLogger.WithFields(log.Fields{
1616 "OnuId": trafficSchedulers.OnuId,
1617 "IntfId": trafficSchedulers.IntfId,
1618 "OnuPortNo": trafficSchedulers.PortNo,
1619 }).Info("received RemoveTrafficSchedulers")
1620 if !s.enablePerf {
1621 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1622 if err != nil {
1623 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1624 return new(openolt.Empty), err
1625 }
1626 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1627 if err != nil {
1628 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1629 return new(openolt.Empty), err
1630 }
1631
1632 onu.TrafficSchedulers = nil
1633 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001634 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001635}
Scott Baker41724b82020-01-21 19:54:53 -08001636
Matteo Scandolo618a6582020-09-09 12:21:29 -07001637func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1638 oltLogger.WithFields(log.Fields{
1639 "GroupId": group.GroupId,
1640 "Command": group.Command,
1641 "Members": group.Members,
1642 "Action": group.Action,
1643 }).Debug("received PerformGroupOperation")
1644 return &openolt.Empty{}, nil
1645}
1646
1647func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1648 oltLogger.WithFields(log.Fields{
1649 "GroupId": group.GroupId,
1650 "Command": group.Command,
1651 "Members": group.Members,
1652 "Action": group.Action,
1653 }).Debug("received PerformGroupOperation")
1654 return &openolt.Empty{}, nil
1655}
1656
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001657func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1658 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001659}
1660
1661func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1662 return &openolt.Empty{}, nil
1663}
1664
1665func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1666 return &openolt.OnuLogicalDistance{}, nil
1667}
1668
1669func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1670 return &openolt.OnuLogicalDistance{}, nil
1671}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001672
Girish Gowdra62f24292021-05-12 16:28:39 -07001673func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1674 return &openolt.PonRxPowerData{}, nil
1675}
1676
Matteo Scandolo96f89192021-03-12 13:17:26 -08001677func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1678 return &openolt.GemPortStatistics{}, nil
1679}
1680
1681func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1682 return &openolt.OnuStatistics{}, nil
1683}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001684
1685func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1686 o.AllocIDsLock.Lock()
1687 defer o.AllocIDsLock.Unlock()
1688
Matteo Scandolo21195d62021-04-07 14:31:23 -07001689 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1690 oltLogger.WithFields(log.Fields{
1691 "IntfId": flow.AccessIntfId,
1692 "OnuId": flow.OnuId,
1693 "PortNo": flow.PortNo,
1694 "GemportId": flow.GemportId,
1695 "FlowId": flow.FlowId,
1696 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1697 }
1698
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001699 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001700 "IntfId": flow.AccessIntfId,
1701 "OnuId": flow.OnuId,
1702 "PortNo": flow.PortNo,
1703 "GemportId": flow.GemportId,
1704 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001705 }).Trace("storing-alloc-id-via-flow")
1706
1707 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1708 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1709 }
1710 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1711 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1712 }
1713 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1714}
1715
1716func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1717 // if this is the last flow referencing the AllocId then remove it
1718 o.AllocIDsLock.Lock()
1719 defer o.AllocIDsLock.Unlock()
1720
1721 oltLogger.WithFields(log.Fields{
1722 "IntfId": flow.AccessIntfId,
1723 "OnuId": flow.OnuId,
1724 "PortNo": flow.PortNo,
1725 "GemportId": flow.GemportId,
1726 }).Trace("freeing-alloc-id-via-flow")
1727
1728 // NOTE look at the freeGemPortId implementation for comments and context
1729 for ponId, ponValues := range o.AllocIDs {
1730 for onuId, onuValues := range ponValues {
1731 for uniId, uniValues := range onuValues {
1732 for allocId, flows := range uniValues {
1733 for flowId := range flows {
1734 // if the flow matches, remove it from the map.
1735 if flow.FlowId == flowId {
1736 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1737 }
1738 // if that was the last flow for a particular allocId, remove the entire allocId
1739 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1740 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1741 }
1742 }
1743 }
1744 }
1745 }
1746 }
1747}
1748
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301749func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) error {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001750 o.GemPortIDsLock.Lock()
1751 defer o.GemPortIDsLock.Unlock()
1752
1753 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1754 oltLogger.WithFields(log.Fields{
1755 "IntfId": ponId,
1756 "OnuId": onuId,
1757 "PortNo": portNo,
1758 "GemportId": gemId,
1759 "FlowId": flowId,
1760 }).Error("trying-to-store-gemport-for-unknown-onu")
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301761 return fmt.Errorf("failed-trying-to-store-gemport-%d-for-unknown-onu-%d-and-IntfId-%d", gemId, onuId, ponId)
Matteo Scandolo21195d62021-04-07 14:31:23 -07001762 }
1763
1764 oltLogger.WithFields(log.Fields{
1765 "IntfId": ponId,
1766 "OnuId": onuId,
1767 "PortNo": portNo,
1768 "GemportId": gemId,
1769 "FlowId": flowId,
1770 }).Trace("storing-alloc-id-via-flow")
1771
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001772 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1773 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1774 }
1775 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1776 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1777 }
1778 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301779
1780 return nil
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001781}
1782
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301783func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001784 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001785 "IntfId": flow.AccessIntfId,
1786 "OnuId": flow.OnuId,
1787 "PortNo": flow.PortNo,
1788 "GemportId": flow.GemportId,
1789 "FlowId": flow.FlowId,
1790 "ReplicateFlow": flow.ReplicateFlow,
1791 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001792 }).Trace("storing-gem-port-id-via-flow")
1793
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001794 if flow.ReplicateFlow {
1795 for _, gem := range flow.PbitToGemport {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301796 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1797 if err != nil {
1798 return err
1799 }
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001800 }
1801 } else {
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301802 err := o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
1803 if err != nil {
1804 return err
1805 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001806 }
Abhay Kumar5f9b7f22023-08-03 13:09:08 +05301807
1808 return nil
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001809}
1810
1811func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1812 // if this is the last flow referencing the GemPort then remove it
1813 o.GemPortIDsLock.Lock()
1814 defer o.GemPortIDsLock.Unlock()
1815
1816 oltLogger.WithFields(log.Fields{
1817 "IntfId": flow.AccessIntfId,
1818 "OnuId": flow.OnuId,
1819 "PortNo": flow.PortNo,
1820 "GemportId": flow.GemportId,
1821 }).Trace("freeing-gem-port-id-via-flow")
1822
1823 // NOTE that this loop is not very performant, it would be better if the flow carries
1824 // the same information that it carries during a FlowAdd. If so we can directly remove
1825 // items from the map
1826
1827 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1828 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1829 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1830 //}
1831
1832 // NOTE this loop assumes that flow IDs are unique per device
1833 for ponId, ponValues := range o.GemPortIDs {
1834 for onuId, onuValues := range ponValues {
1835 for uniId, uniValues := range onuValues {
1836 for gemId, flows := range uniValues {
1837 for flowId := range flows {
1838 // if the flow matches, remove it from the map.
1839 if flow.FlowId == flowId {
1840 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1841 }
1842 // if that was the last flow for a particular gem, remove the entire gem
1843 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1844 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1845 }
1846 }
1847 }
1848 }
1849 }
1850 }
1851}
1852
1853// validateFlow checks that:
1854// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1855// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1856func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001857 // validate gemPort
1858 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001859 defer o.GemPortIDsLock.RUnlock()
1860 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001861 if onuId == uint32(flow.OnuId) {
1862 continue
1863 }
1864 for uniId, uni := range onu {
1865 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001866 if flow.ReplicateFlow {
1867 for _, flowGem := range flow.PbitToGemport {
1868 if gem == int32(flowGem) {
1869 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1870 }
1871 }
1872 } else {
1873 if gem == flow.GemportId {
1874 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1875 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001876 }
1877 }
1878 }
1879 }
1880
1881 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001882 defer o.AllocIDsLock.RUnlock()
1883 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001884 if onuId == uint32(flow.OnuId) {
1885 continue
1886 }
1887 for uniId, uni := range onu {
1888 for allocId := range uni {
1889 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001890 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 -08001891 }
1892 }
1893 }
1894 }
1895
1896 return nil
1897}
1898
1899// clearAllResources is invoked up OLT Reboot to remove all the allocated
1900// GemPorts, AllocId and ONU-IDs across the PONs
1901func (o *OltDevice) clearAllResources() {
1902
1903 // remove the resources received via flows
1904 o.GemPortIDsLock.Lock()
1905 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1906 o.GemPortIDsLock.Unlock()
1907 o.AllocIDsLock.Lock()
1908 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1909 o.AllocIDsLock.Unlock()
1910
1911 // remove the resources received via OMCI
1912 for _, pon := range o.Pons {
1913 pon.removeAllAllocIds()
1914 pon.removeAllGemPorts()
1915 pon.removeAllOnuIds()
1916 }
1917}