blob: 3410e60548cf621bee629593cdcc2dcbc1877b78 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
20 "context"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "encoding/hex"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "fmt"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010026 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020027
Elia Battistonac63b112022-01-12 18:40:49 +010028 "github.com/opencord/voltha-protos/v5/go/extension"
29
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000030 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
31 "github.com/opencord/bbsim/internal/bbsim/types"
32 omcilib "github.com/opencord/bbsim/internal/common/omci"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000033 "github.com/opencord/voltha-protos/v5/go/ext/config"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000034
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070035 "github.com/google/gopacket"
36 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070038 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010039 "github.com/opencord/bbsim/internal/common"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000040 "github.com/opencord/voltha-protos/v5/go/openolt"
41 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042 log "github.com/sirupsen/logrus"
43 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053044 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010045 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053046 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070047)
48
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070049var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070050 "module": "OLT",
51})
52
Matteo Scandolocedde462021-03-09 17:37:16 -080053const (
Girish Gowdra3015ff72021-06-28 11:48:56 -070054 onuIdStart = 1
55 // Least pon port on the real OLTs we test with today have 16 ports (not including the pluggable OLTs).
56 // Given that we have to support 512 ONUs per OLT, we have to have up to 32 ONU per PON (could be less
57 // on a higher density port OLT).
58 // We pass just enough limits here to ensure the resource pool is as
59 // compact as possible on the etcd to reduce storage.
60 onuIdEnd = onuIdStart + 31
61 allocIdStart = 1024
62 allocIdPerOnu = 4
63 allocIdEnd = allocIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu // up to 4 alloc-id per ONU
64 gemPortIdPerAllocId = 8
65 gemportIdStart = 1024
66 gemportIdEnd = gemportIdStart + (onuIdEnd-onuIdStart+1)*allocIdPerOnu*gemPortIdPerAllocId // up to 8 gemport-id per tcont/alloc-id
67 // The flow ids are no more necessary by the adapter, but still need to pass something dummy. Pass a very small valid range.
68 flowIdStart = 1
69 flowIdEnd = flowIdStart + 1
Matteo Scandolocedde462021-03-09 17:37:16 -080070)
71
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070072type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000073 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000074 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000075
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070076 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053077 ID int
78 SerialNumber string
79 NumNni int
Elia Battiston420c9092022-02-02 12:17:54 +010080 NniSpeed uint32
Pragya Arya2225f202020-01-29 18:05:01 +053081 NumPon int
82 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070083 NumUni int
Elia Battistonac63b112022-01-12 18:40:49 +010084 NumPots int
Pragya Arya2225f202020-01-29 18:05:01 +053085 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080086 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070087 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010088 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053089 Delay int
90 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053091 EventChannel chan common.Event
92 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053093 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080094 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070095
Matteo Scandolo27428702019-10-11 16:21:16 -070096 Pons []*PonPort
97 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070098
99 // OLT Attributes
100 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +0000101
102 enableContext context.Context
103 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +0530104
Matteo Scandolo4a036262020-08-17 15:56:13 -0700105 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +0530106 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800107
108 // Allocated Resources
109 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000110 AllocIDsLock sync.RWMutex
111 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
112 GemPortIDsLock sync.RWMutex
113 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
114 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700115}
116
Matteo Scandolo27428702019-10-11 16:21:16 -0700117var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700118
Matteo Scandolo27428702019-10-11 16:21:16 -0700119func GetOLT() *OltDevice {
120 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700121}
122
Matteo Scandolo4a036262020-08-17 15:56:13 -0700123func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700124 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530125 "ID": options.Olt.ID,
126 "NumNni": options.Olt.NniPorts,
Elia Battiston420c9092022-02-02 12:17:54 +0100127 "NniSpeed": options.Olt.NniSpeed,
Pragya Arya996a0892020-03-09 21:47:52 +0530128 "NumPon": options.Olt.PonPorts,
129 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700130 "NumUni": options.Olt.UniPorts,
Elia Battistonac63b112022-01-12 18:40:49 +0100131 "NumPots": options.Olt.PotsPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700132 }).Debug("CreateOLT")
133
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700134 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530135 ID: options.Olt.ID,
136 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700137 OperState: getOperStateFSM(func(e *fsm.Event) {
138 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
139 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800140 NumNni: int(options.Olt.NniPorts),
Elia Battiston420c9092022-02-02 12:17:54 +0100141 NniSpeed: options.Olt.NniSpeed,
Matteo Scandolo96f89192021-03-12 13:17:26 -0800142 NumPon: int(options.Olt.PonPorts),
143 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700144 NumUni: int(options.Olt.UniPorts),
Elia Battistonac63b112022-01-12 18:40:49 +0100145 NumPots: int(options.Olt.PotsPorts),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800146 Pons: []*PonPort{},
147 Nnis: []*NniPort{},
148 Delay: options.BBSim.Delay,
149 enablePerf: options.BBSim.EnablePerf,
150 PublishEvents: options.BBSim.Events,
151 PortStatsInterval: options.Olt.PortStatsInterval,
152 dhcpServer: dhcp.NewDHCPServer(),
153 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800154 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
155 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000156 OmciResponseRate: options.Olt.OmciResponseRate,
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(
170 "created",
171 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800172 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100173 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700174 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700175 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800176 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
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 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100182 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800183 "enter_deleted": func(e *fsm.Event) {
184 // 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++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800206
207 // initialize the resource maps for every PON Ports
208 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
209 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
210
Matteo Scandolo4a036262020-08-17 15:56:13 -0700211 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700212
Matteo Scandolo4a036262020-08-17 15:56:13 -0700213 // create ONU devices
214 for j := 0; j < olt.NumOnuPerPon; j++ {
215 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700216 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700217
Matteo Scandolo4a036262020-08-17 15:56:13 -0700218 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700219 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700220 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700221 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100222
Shrey Baid688b4242020-07-10 20:40:10 +0530223 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700224 if err := olt.InternalState.Event("initialize"); err != nil {
225 log.Errorf("Error initializing OLT: %v", err)
226 return nil
227 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100228 }
229
Pragya Arya324337e2020-02-20 14:35:08 +0530230 if olt.PublishEvents {
231 log.Debugf("BBSim event publishing is enabled")
232 // Create a channel to write event messages
233 olt.EventChannel = make(chan common.Event, 100)
234 }
235
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700236 return &olt
237}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700238
Shrey Baid688b4242020-07-10 20:40:10 +0530239func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100240
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000241 if o.OltServer == nil {
242 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800244 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100245 }
246
247 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800248 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100250 // FIXME we are assuming we have only one NNI
251 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800252 // NOTE we want to make sure the state is down when we initialize the OLT,
253 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
254 // in-band management
255 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100256 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800257
258 for ponId := range o.Pons {
259 // initialize the resource maps for every PON Ports
260 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
261 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
262 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700263}
264
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800265func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100266
Matteo Scandolo96f89192021-03-12 13:17:26 -0800267 o.PreviouslyConnected = false
268
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700269 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700270 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800271
272 oltLogger.WithFields(log.Fields{
273 "oltId": o.ID,
274 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
275
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700276 if o.InternalState.Is("enabled") {
277 oltLogger.WithFields(log.Fields{
278 "oltId": o.ID,
279 }).Info("This is an OLT soft reboot")
280 softReboot = true
281 }
282
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800283 // transition internal state to deleted
284 if err := o.InternalState.Event("delete"); err != nil {
285 oltLogger.WithFields(log.Fields{
286 "oltId": o.ID,
287 }).Errorf("Error deleting OLT: %v", err)
288 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289 }
290
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700291 if softReboot {
292 for _, pon := range o.Pons {
293 if pon.InternalState.Current() == "enabled" {
294 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800295 msg := types.Message{
296 Type: types.PonIndication,
297 Data: types.PonIndicationMessage{
298 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700299 PonPortID: pon.ID,
300 },
301 }
302 o.channel <- msg
303 }
304
305 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800306 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700307 }
308 }
309 } else {
310 // PONs are already handled in the Disable call
311 for _, pon := range olt.Pons {
312 // ONUs are not automatically disabled when a PON goes down
313 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
314 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800315 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700316 }
Pragya Arya2225f202020-01-29 18:05:01 +0530317 }
318 }
319
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700320 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
321 o.StopOltServer()
322
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100323 // terminate the OLT's processOltMessages go routine
324 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700325
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700326 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100327 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100328
329 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800330 oltLogger.WithFields(log.Fields{
331 "oltId": o.ID,
332 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100333 return err
334 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800335 oltLogger.WithFields(log.Fields{
336 "oltId": o.ID,
337 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100338 return nil
339}
340
341// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800342func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700343 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700344 lis, err := net.Listen("tcp", address)
345 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700346 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347 }
348 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100349
Matteo Scandolo4747d292019-08-05 11:50:18 -0700350 openolt.RegisterOpenoltServer(grpcServer, o)
351
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100352 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700353
Shrey Baid688b4242020-07-10 20:40:10 +0530354 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100355 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700356
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100357 return grpcServer, nil
358}
359
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800360// StartOltServer will create the grpc server that VOLTHA uses
361// to communicate with the device
362func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
363 oltServer, err := o.newOltServer()
364 if err != nil {
365 oltLogger.WithFields(log.Fields{
366 "err": err,
367 }).Error("Cannot OLT gRPC server")
368 return nil, err
369 }
370 return oltServer, nil
371}
372
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100373// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800374func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000375 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800376 oltLogger.WithFields(log.Fields{
377 "oltId": o.SerialNumber,
378 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000379 o.OltServer.Stop()
380 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700381 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700382}
383
384// Device Methods
385
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100386// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530387func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700388 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530389 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700390
David Bainbridge103cf022019-12-16 20:11:35 +0000391 // If enabled has already been called then an enabled context has
392 // been created. If this is the case then we want to cancel all the
393 // proessing loops associated with that enable before we recreate
394 // new ones
395 o.Lock()
396 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700397 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000398 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530399 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700400 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000401 }
402 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
403 o.Unlock()
404
Matteo Scandolo4747d292019-08-05 11:50:18 -0700405 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700406
Matteo Scandolo4a036262020-08-17 15:56:13 -0700407 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530408
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100409 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700410 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000411 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700412
413 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800414 oltMsg := types.Message{
415 Type: types.OltIndication,
416 Data: types.OltIndicationMessage{
417 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700418 },
419 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100420 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700421
422 // send NNI Port Indications
423 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800424 msg := types.Message{
425 Type: types.NniIndication,
426 Data: types.NniIndicationMessage{
427 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700428 NniPortID: nni.ID,
429 },
430 }
431 o.channel <- msg
432 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100433
Shrey Baid688b4242020-07-10 20:40:10 +0530434 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530435 for _, pon := range o.Pons {
436 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800437 msg := types.Message{
438 Type: types.PonIndication,
439 Data: types.PonIndicationMessage{
440 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530441 PonPortID: pon.ID,
442 },
443 }
444 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000445 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700446 // when the enableContext was canceled the ONUs stopped listening on the channel
447 for _, onu := range pon.Onus {
448 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
449
450 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700451 for _, uni := range onu.UniPorts {
452 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700453 }
454 }
Pragya Arya2225f202020-01-29 18:05:01 +0530455 }
456 } else {
457
458 // 1. controlledActivation == Default: Send both PON and ONUs indications
459 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
460
461 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
462 // send PON Port indications
463 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800464 msg := types.Message{
465 Type: types.PonIndication,
466 Data: types.PonIndicationMessage{
467 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530468 PonPortID: pon.ID,
469 },
470 }
471 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700472 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700473 }
474 }
475
Pragya Arya996a0892020-03-09 21:47:52 +0530476 if !o.enablePerf {
477 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700478 wg.Add(1)
479 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530480 }
481
Matteo Scandolo4747d292019-08-05 11:50:18 -0700482 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700483 oltLogger.WithFields(log.Fields{
484 "stream": stream,
485 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700486}
487
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700488func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530489 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700490
491loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530492 for {
493 select {
494 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
495 // send NNI port stats
496 for _, port := range o.Nnis {
497 incrementStat := true
498 if port.OperState.Current() == "down" {
499 incrementStat = false
500 }
501 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700502 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530503 }
504
505 // send PON port stats
506 for _, port := range o.Pons {
507 incrementStat := true
508 // do not increment port stats if PON port is down or no ONU is activated on PON port
509 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
510 incrementStat = false
511 }
512 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700513 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530514 }
515 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700516 oltLogger.Debug("Stop sending port stats")
517 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530518 }
Pragya Arya996a0892020-03-09 21:47:52 +0530519 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700520 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530521}
522
Matteo Scandolo4747d292019-08-05 11:50:18 -0700523// Helpers method
524
Matteo Scandolof9d43412021-01-12 11:11:34 -0800525func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
526
527 switch interfaceType {
528 case "nni":
529 if !o.HasNni(interfaceId) {
530 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
531 }
532
533 case "pon":
534 if !o.HasPon(interfaceId) {
535 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
536 }
537 }
538
539 alarmIndication := &openolt.AlarmIndication{
540 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
541 Status: alarmStatus,
542 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
543 }},
544 }
545
546 msg := types.Message{
547 Type: types.AlarmIndication,
548 Data: alarmIndication,
549 }
550
551 o.channel <- msg
552
553 return nil
554}
555
556func (o *OltDevice) HasNni(id uint32) bool {
557 for _, intf := range o.Nnis {
558 if intf.ID == id {
559 return true
560 }
561 }
562 return false
563}
564
565func (o *OltDevice) HasPon(id uint32) bool {
566 for _, intf := range o.Pons {
567 if intf.ID == id {
568 return true
569 }
570 }
571 return false
572}
573
Shrey Baid688b4242020-07-10 20:40:10 +0530574func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700575 for _, pon := range o.Pons {
576 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700577 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578 }
579 }
Shrey Baid688b4242020-07-10 20:40:10 +0530580 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581}
582
Shrey Baid688b4242020-07-10 20:40:10 +0530583func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700584 for _, nni := range o.Nnis {
585 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700586 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587 }
588 }
Shrey Baid688b4242020-07-10 20:40:10 +0530589 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590}
591
Scott Baker41724b82020-01-21 19:54:53 -0800592func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
593 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
594 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
595 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
596 return
597 }
598
599 oltLogger.WithFields(log.Fields{
600 "AlarmIndication": alarmInd,
601 }).Debug("Sent Indication_AlarmInd")
602}
603
Matteo Scandolof9d43412021-01-12 11:11:34 -0800604func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
606 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700607 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800608 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 }
610
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700611 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612 "OperState": msg.OperState,
613 }).Debug("Sent Indication_OltInd")
614}
615
Matteo Scandolof9d43412021-01-12 11:11:34 -0800616func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800618 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800619 if err := nni.OperState.Event("enable"); err != nil {
620 log.WithFields(log.Fields{
621 "Type": nni.Type,
622 "IntfId": nni.ID,
623 "OperState": nni.OperState.Current(),
624 }).Errorf("Can't move NNI Port to enabled state: %v", err)
625 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800626 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800627 if err := nni.OperState.Event("disable"); err != nil {
628 log.WithFields(log.Fields{
629 "Type": nni.Type,
630 "IntfId": nni.ID,
631 "OperState": nni.OperState.Current(),
632 }).Errorf("Can't move NNI Port to disable state: %v", err)
633 }
634 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700635 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700637 Type: nni.Type,
638 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700639 OperState: nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100640 Speed: o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700641 }}
642
643 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700644 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800645 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700646 }
647
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700648 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700649 "Type": nni.Type,
650 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700651 "OperState": nni.OperState.Current(),
Elia Battiston420c9092022-02-02 12:17:54 +0100652 "Speed": o.NniSpeed,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700653 }).Debug("Sent Indication_IntfOperInd for NNI")
654}
655
Pragya Arya2225f202020-01-29 18:05:01 +0530656func (o *OltDevice) sendPonIndication(ponPortID uint32) {
657
Matteo Scandolo4a036262020-08-17 15:56:13 -0700658 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530659 pon, _ := o.GetPonById(ponPortID)
660 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700661 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700662 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700663 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 }}
665
666 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700667 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800668 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669 }
670
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700671 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700672 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700673 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700674 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700675
Pragya Arya2225f202020-01-29 18:05:01 +0530676 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700677 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700678 Type: pon.Type,
679 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700680 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700681 }}
682
683 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700684 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800685 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700686 }
687
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700688 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700689 "Type": pon.Type,
690 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700691 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700692 }).Debug("Sent Indication_IntfOperInd for PON")
693}
694
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700695func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530696 if o.InternalState.Current() == "enabled" {
697 oltLogger.WithFields(log.Fields{
698 "Type": portType,
699 "IntfId": portID,
700 }).Trace("Sending port stats")
701 stats.IntfId = InterfaceIDToPortNo(portID, portType)
702 data := &openolt.Indication_PortStats{
703 PortStats: stats,
704 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700705
Shrey Baid55f328c2020-07-07 19:20:42 +0530706 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
707 oltLogger.Errorf("Failed to send PortStats: %v", err)
708 return
709 }
Pragya Arya996a0892020-03-09 21:47:52 +0530710 }
711}
712
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100713// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700714func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
715 oltLogger.WithFields(log.Fields{
716 "stream": stream,
717 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000718 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700719
David Bainbridge103cf022019-12-16 20:11:35 +0000720loop:
721 for {
722 select {
723 case <-ctx.Done():
724 oltLogger.Debug("OLT Indication processing canceled via context")
725 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700726 // do not terminate this loop if the stream is closed,
727 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
728 //case <-stream.Context().Done():
729 // oltLogger.Debug("OLT Indication processing canceled via stream context")
730 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000731 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700732 if !ok {
733 if ctx.Err() != nil {
734 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
735 }
736 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000737 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700738 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700739
David Bainbridge103cf022019-12-16 20:11:35 +0000740 oltLogger.WithFields(log.Fields{
741 "oltId": o.ID,
742 "messageType": message.Type,
743 }).Trace("Received message")
744
745 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800746 case types.OltIndication:
747 msg, _ := message.Data.(types.OltIndicationMessage)
748 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530749 _ = o.InternalState.Event("enable")
750 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800751 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530752 _ = o.InternalState.Event("disable")
753 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000754 }
755 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800756 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800757 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
758 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800759 case types.NniIndication:
760 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000761 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800762 case types.PonIndication:
763 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530764 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800765 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530766 if err := pon.OperState.Event("enable"); err != nil {
767 oltLogger.WithFields(log.Fields{
768 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800769 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530770 }).Error("Can't Enable Oper state for PON Port")
771 }
772 if err := pon.InternalState.Event("enable"); err != nil {
773 oltLogger.WithFields(log.Fields{
774 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800775 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530776 }).Error("Can't Enable Internal state for PON Port")
777 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800778 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530779 if err := pon.OperState.Event("disable"); err != nil {
780 oltLogger.WithFields(log.Fields{
781 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800782 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530783 }).Error("Can't Disable Oper state for PON Port")
784 }
785 if err := pon.InternalState.Event("disable"); err != nil {
786 oltLogger.WithFields(log.Fields{
787 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800788 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530789 }).Error("Can't Disable Internal state for PON Port")
790 }
Pragya Arya2225f202020-01-29 18:05:01 +0530791 }
David Bainbridge103cf022019-12-16 20:11:35 +0000792 default:
793 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
794 }
795 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700796 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100797 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700798 oltLogger.WithFields(log.Fields{
799 "stream": stream,
800 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700801}
802
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700803// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530804func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700805 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700806 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700807 for _, pon := range o.Pons {
808 for _, onu := range pon.Onus {
809 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700810 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700811 }
812 }
813 }
814
Shrey Baid688b4242020-07-10 20:40:10 +0530815 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700816}
817
William Kurkian9dadc5b2019-10-22 13:51:57 -0400818// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530819func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700820 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400821 // memoizing it will remove the bottleneck
822 for _, pon := range o.Pons {
823 if pon.ID == intfId {
824 for _, onu := range pon.Onus {
825 if onu.ID == onuId {
826 return onu, nil
827 }
828 }
829 }
830 }
Shrey Baid688b4242020-07-10 20:40:10 +0530831 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400832}
833
Matteo Scandolo4a036262020-08-17 15:56:13 -0700834// returns a Service with a given Mac Address
835func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700836 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700837 // memoizing it will remove the bottleneck
838 for _, pon := range o.Pons {
839 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700840 s, err := onu.findServiceByMacAddress(mac)
841 if err == nil {
842 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700843 }
844 }
845 }
846
Matteo Scandolo4a036262020-08-17 15:56:13 -0700847 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700848}
849
Matteo Scandolo4747d292019-08-05 11:50:18 -0700850// GRPC Endpoints
851
Shrey Baid688b4242020-07-10 20:40:10 +0530852func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700853
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700854 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800855
Matteo Scandolo8a574812021-05-20 15:18:53 -0700856 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800857 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
858 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
859
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700860 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700861
862 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
863 oltLogger.WithFields(log.Fields{
864 "OnuSn": _onu.Sn(),
865 }).Info("Received ActivateOnu call from VOLTHA")
866
William Kurkian0418bc82019-11-06 12:16:24 -0500867 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700868
Matteo Scandolocedde462021-03-09 17:37:16 -0800869 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700870 oltLogger.WithFields(log.Fields{
871 "IntfId": _onu.PonPortID,
872 "OnuSn": _onu.Sn(),
873 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800874 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700875 }
876
877 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
878
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700879 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700880}
881
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800882func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700883 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700884 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700885}
886
Shrey Baid688b4242020-07-10 20:40:10 +0530887func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530888 oltLogger.WithFields(log.Fields{
889 "IntfId": onu.IntfId,
890 "OnuId": onu.OnuId,
891 }).Info("Received DeleteOnu call from VOLTHA")
892
893 pon, err := o.GetPonById(onu.IntfId)
894 if err != nil {
895 oltLogger.WithFields(log.Fields{
896 "OnuId": onu.OnuId,
897 "IntfId": onu.IntfId,
898 "err": err,
899 }).Error("Can't find PonPort")
900 }
901 _onu, err := pon.GetOnuById(onu.OnuId)
902 if err != nil {
903 oltLogger.WithFields(log.Fields{
904 "OnuId": onu.OnuId,
905 "IntfId": onu.IntfId,
906 "err": err,
907 }).Error("Can't find Onu")
908 }
909
Matteo Scandolocedde462021-03-09 17:37:16 -0800910 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530911 oltLogger.WithFields(log.Fields{
912 "IntfId": _onu.PonPortID,
913 "OnuSn": _onu.Sn(),
914 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800915 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530916 }
917
Hardik Windlassad790cb2020-06-17 21:26:22 +0530918 // ONU Re-Discovery
919 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530920 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530921 }
922
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700923 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700924}
925
Shrey Baid688b4242020-07-10 20:40:10 +0530926func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700927 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800928 oltLogger.WithFields(log.Fields{
929 "oltId": o.ID,
930 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530931 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800932
Matteo Scandolo401503a2019-12-11 14:48:14 -0800933 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530934 if pon.InternalState.Current() == "enabled" {
935 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800936 msg := types.Message{
937 Type: types.PonIndication,
938 Data: types.PonIndicationMessage{
939 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530940 PonPortID: pon.ID,
941 },
942 }
943 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800944 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800945 }
946
Matteo Scandolo401503a2019-12-11 14:48:14 -0800947 // Note that we are not disabling the NNI as the real OLT does not.
948 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800949
950 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800951 oltMsg := types.Message{
952 Type: types.OltIndication,
953 Data: types.OltIndicationMessage{
954 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700955 },
956 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100957 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700958
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700959 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700960}
961
Shrey Baid688b4242020-07-10 20:40:10 +0530962func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530963 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200964 ponID := intf.GetIntfId()
965 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200966
Matteo Scandolof9d43412021-01-12 11:11:34 -0800967 msg := types.Message{
968 Type: types.PonIndication,
969 Data: types.PonIndicationMessage{
970 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200971 PonPortID: ponID,
972 },
973 }
974 o.channel <- msg
975
976 for _, onu := range pon.Onus {
977
Matteo Scandolof9d43412021-01-12 11:11:34 -0800978 onuIndication := types.OnuIndicationMessage{
979 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200980 PonPortID: ponID,
981 OnuID: onu.ID,
982 OnuSN: onu.SerialNumber,
983 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700984 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200985
986 }
987
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700988 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700989}
990
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100991func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700992 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530993 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700994 o.Enable(stream)
995 return nil
996}
997
Shrey Baid688b4242020-07-10 20:40:10 +0530998func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530999 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301000 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001001 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001002
Matteo Scandolof9d43412021-01-12 11:11:34 -08001003 msg := types.Message{
1004 Type: types.PonIndication,
1005 Data: types.PonIndicationMessage{
1006 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301007 PonPortID: ponID,
1008 },
1009 }
1010 o.channel <- msg
1011
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001012 for _, onu := range pon.Onus {
1013
Matteo Scandolof9d43412021-01-12 11:11:34 -08001014 onuIndication := types.OnuIndicationMessage{
1015 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001016 PonPortID: ponID,
1017 OnuID: onu.ID,
1018 OnuSN: onu.SerialNumber,
1019 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001020 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001021
1022 }
1023
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001024 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001025}
1026
Shrey Baid688b4242020-07-10 20:40:10 +05301027func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001028 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001029 "IntfId": flow.AccessIntfId,
1030 "OnuId": flow.OnuId,
1031 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001032 "InnerVlan": flow.Classifier.IVid,
1033 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001034 "FlowType": flow.FlowType,
1035 "FlowId": flow.FlowId,
1036 "UniID": flow.UniId,
1037 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301038 }).Tracef("OLT receives FlowAdd")
1039
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001040 flowKey := FlowKey{}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301041 if !o.enablePerf {
yasin saplic07b9522022-01-27 11:23:54 +00001042 flowKey = FlowKey{ID: flow.FlowId}
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001043 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301044 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001045
1046 if flow.AccessIntfId == -1 {
1047 oltLogger.WithFields(log.Fields{
1048 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001049 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001050 } else if flow.FlowType == "multicast" {
1051 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001052 "Cookie": flow.Cookie,
1053 "DstPort": flow.Classifier.DstPort,
1054 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1055 "FlowId": flow.FlowId,
1056 "FlowType": flow.FlowType,
1057 "GemportId": flow.GemportId,
1058 "InnerVlan": flow.Classifier.IVid,
1059 "IntfId": flow.AccessIntfId,
1060 "IpProto": flow.Classifier.IpProto,
1061 "OnuId": flow.OnuId,
1062 "OuterVlan": flow.Classifier.OVid,
1063 "PortNo": flow.PortNo,
1064 "SrcPort": flow.Classifier.SrcPort,
1065 "UniID": flow.UniId,
1066 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001067 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001068 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001069 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001070 if err != nil {
1071 oltLogger.WithFields(log.Fields{
1072 "OnuId": flow.OnuId,
1073 "IntfId": flow.AccessIntfId,
1074 "err": err,
1075 }).Error("Can't find PonPort")
1076 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001077 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001078 if err != nil {
1079 oltLogger.WithFields(log.Fields{
1080 "OnuId": flow.OnuId,
1081 "IntfId": flow.AccessIntfId,
1082 "err": err,
1083 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001084 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001085 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001086
1087 // if the ONU is disabled reject the flow
1088 // as per VOL-4061 there is a small window during which the ONU is disabled
1089 // but the port has not been reported as down to ONOS
1090 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1091 oltLogger.WithFields(log.Fields{
1092 "OnuId": flow.OnuId,
1093 "IntfId": flow.AccessIntfId,
1094 "Flow": flow,
1095 "SerialNumber": onu.Sn(),
1096 "InternalState": onu.InternalState.Current(),
1097 }).Error("rejected-flow-because-of-onu-state")
1098 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1099 }
1100
Pragya Arya8bdb4532020-03-02 17:08:09 +05301101 if !o.enablePerf {
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001102 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301103 // Generate event on first flow for ONU
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001104 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001105 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301106 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301107 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001108
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001109 // validate that the flow reference correct IDs (Alloc, Gem)
1110 if err := o.validateFlow(flow); err != nil {
1111 oltLogger.WithFields(log.Fields{
1112 "OnuId": flow.OnuId,
1113 "IntfId": flow.AccessIntfId,
1114 "Flow": flow,
1115 "SerialNumber": onu.Sn(),
1116 "err": err,
1117 }).Error("invalid-flow-for-onu")
1118 return nil, err
1119 }
1120
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001121 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001122 o.storeAllocId(flow)
1123
Matteo Scandolof9d43412021-01-12 11:11:34 -08001124 msg := types.Message{
1125 Type: types.FlowAdd,
1126 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001127 PonPortID: pon.ID,
1128 OnuID: onu.ID,
1129 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001130 },
1131 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001132 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001133 }
1134
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001135 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001136}
1137
Pragya Arya8bdb4532020-03-02 17:08:09 +05301138// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301139func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001140
Pragya Arya8bdb4532020-03-02 17:08:09 +05301141 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001142 "AllocId": flow.AllocId,
1143 "Cookie": flow.Cookie,
1144 "FlowId": flow.FlowId,
1145 "FlowType": flow.FlowType,
1146 "GemportId": flow.GemportId,
1147 "IntfId": flow.AccessIntfId,
1148 "OnuId": flow.OnuId,
1149 "PortNo": flow.PortNo,
1150 "UniID": flow.UniId,
1151 "ReplicateFlow": flow.ReplicateFlow,
1152 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001153 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301154
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001155 olt.freeGemPortId(flow)
1156 olt.freeAllocId(flow)
1157
Pragya Arya8bdb4532020-03-02 17:08:09 +05301158 if !o.enablePerf { // remove only if flow were stored
yasin saplic07b9522022-01-27 11:23:54 +00001159 flowKey := FlowKey{ID: flow.FlowId}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301160 // Check if flow exists
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001161 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301162 if !ok {
1163 oltLogger.Errorf("Flow %v not found", flow)
1164 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1165 }
1166
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001167 storedFlow := storedFlowIntf.(openolt.Flow)
1168
Pragya Arya8bdb4532020-03-02 17:08:09 +05301169 // if its ONU flow remove it from ONU also
1170 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001171 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1172 if err != nil {
1173 oltLogger.WithFields(log.Fields{
1174 "OnuId": storedFlow.OnuId,
1175 "IntfId": storedFlow.AccessIntfId,
1176 "PONs": olt.Pons,
1177 "err": err,
1178 }).Error("PON-port-not-found")
1179 return new(openolt.Empty), nil
1180 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301181 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1182 if err != nil {
1183 oltLogger.WithFields(log.Fields{
1184 "OnuId": storedFlow.OnuId,
1185 "IntfId": storedFlow.AccessIntfId,
1186 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001187 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301188 return new(openolt.Empty), nil
1189 }
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001190 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001191 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301192 }
1193
1194 // delete from olt flows
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001195 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301196 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001197
1198 if flow.AccessIntfId == -1 {
1199 oltLogger.WithFields(log.Fields{
1200 "FlowId": flow.FlowId,
1201 }).Debug("Removing OLT flow")
1202 } else if flow.FlowType == "multicast" {
1203 oltLogger.WithFields(log.Fields{
1204 "FlowId": flow.FlowId,
1205 }).Debug("Removing OLT multicast flow")
1206 } else {
1207
1208 onu, err := o.GetOnuByFlowId(flow.FlowId)
1209 if err != nil {
1210 oltLogger.WithFields(log.Fields{
1211 "OnuId": flow.OnuId,
1212 "IntfId": flow.AccessIntfId,
1213 "err": err,
1214 }).Error("Can't find Onu")
1215 return nil, err
1216 }
1217
Matteo Scandolof9d43412021-01-12 11:11:34 -08001218 msg := types.Message{
1219 Type: types.FlowRemoved,
1220 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301221 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001222 },
1223 }
1224 onu.Channel <- msg
1225 }
1226
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001227 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001228}
1229
Shrey Baid688b4242020-07-10 20:40:10 +05301230func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001231 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1232 oltLogger.WithFields(log.Fields{
1233 "signature": res.HeartbeatSignature,
1234 }).Trace("HeartbeatCheck")
1235 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001236}
1237
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001238func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001239 for _, pon := range o.Pons {
1240 for _, onu := range pon.Onus {
1241 for _, fId := range onu.FlowIds {
1242 if fId == flowId {
1243 return onu, nil
1244 }
1245 }
1246 }
1247 }
Shrey Baid688b4242020-07-10 20:40:10 +05301248 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001249}
1250
Shrey Baid688b4242020-07-10 20:40:10 +05301251func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001252
Matteo Scandolocedde462021-03-09 17:37:16 -08001253 intfIDs := []uint32{}
1254 for i := 0; i < o.NumPon; i++ {
1255 intfIDs = append(intfIDs, uint32(i))
1256 }
1257
1258 devinfo := &openolt.DeviceInfo{
1259 Vendor: common.Config.Olt.Vendor,
1260 Model: common.Config.Olt.Model,
1261 HardwareVersion: common.Config.Olt.HardwareVersion,
1262 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1263 Technology: common.Config.Olt.Technology,
1264 PonPorts: uint32(o.NumPon),
1265 OnuIdStart: onuIdStart,
1266 OnuIdEnd: onuIdEnd,
1267 AllocIdStart: allocIdStart,
1268 AllocIdEnd: allocIdEnd,
1269 GemportIdStart: gemportIdStart,
1270 GemportIdEnd: gemportIdEnd,
1271 FlowIdStart: flowIdStart,
1272 FlowIdEnd: flowIdEnd,
1273 DeviceSerialNumber: o.SerialNumber,
1274 DeviceId: common.Config.Olt.DeviceId,
1275 PreviouslyConnected: o.PreviouslyConnected,
1276 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1277 {
1278 IntfIds: intfIDs,
1279 Technology: common.Config.Olt.Technology,
1280 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1281 {
1282 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1283 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1284 Start: onuIdStart,
1285 End: onuIdEnd,
1286 },
1287 {
1288 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1289 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1290 Start: allocIdStart,
1291 End: allocIdEnd,
1292 },
1293 {
1294 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1295 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1296 Start: gemportIdStart,
1297 End: gemportIdEnd,
1298 },
1299 {
1300 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1301 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1302 Start: flowIdStart,
1303 End: flowIdEnd,
1304 },
1305 },
1306 },
1307 },
1308 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001309
1310 oltLogger.WithFields(log.Fields{
1311 "Vendor": devinfo.Vendor,
1312 "Model": devinfo.Model,
1313 "HardwareVersion": devinfo.HardwareVersion,
1314 "FirmwareVersion": devinfo.FirmwareVersion,
1315 "Technology": devinfo.Technology,
1316 "PonPorts": devinfo.PonPorts,
1317 "OnuIdStart": devinfo.OnuIdStart,
1318 "OnuIdEnd": devinfo.OnuIdEnd,
1319 "AllocIdStart": devinfo.AllocIdStart,
1320 "AllocIdEnd": devinfo.AllocIdEnd,
1321 "GemportIdStart": devinfo.GemportIdStart,
1322 "GemportIdEnd": devinfo.GemportIdEnd,
1323 "FlowIdStart": devinfo.FlowIdStart,
1324 "FlowIdEnd": devinfo.FlowIdEnd,
1325 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1326 "DeviceId": devinfo.DeviceId,
1327 "PreviouslyConnected": devinfo.PreviouslyConnected,
1328 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1329
1330 // once we connect, set the flag
1331 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001332
1333 return devinfo, nil
1334}
1335
Shrey Baid688b4242020-07-10 20:40:10 +05301336func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001337 pon, err := o.GetPonById(omci_msg.IntfId)
1338 if err != nil {
1339 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001340 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001341 "onu_id": omci_msg.OnuId,
1342 "pon_id": omci_msg.IntfId,
1343 }).Error("pon ID not found")
1344 return nil, err
1345 }
1346
1347 onu, err := pon.GetOnuById(omci_msg.OnuId)
1348 if err != nil {
1349 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001350 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001351 "onu_id": omci_msg.OnuId,
1352 "pon_id": omci_msg.IntfId,
1353 }).Error("onu ID not found")
1354 return nil, err
1355 }
1356
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001357 oltLogger.WithFields(log.Fields{
1358 "IntfId": onu.PonPortID,
1359 "OnuId": onu.ID,
1360 "OnuSn": onu.Sn(),
1361 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001362 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1363 if err != nil {
1364 log.WithFields(log.Fields{
1365 "IntfId": onu.PonPortID,
1366 "SerialNumber": onu.Sn(),
1367 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1368 "err": err.Error(),
1369 }).Error("cannot-parse-OMCI-packet")
1370 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001371 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001372 if onu.InternalState.Current() == OnuStateDisabled {
1373 // if the ONU is disabled just drop the message
1374 log.WithFields(log.Fields{
1375 "IntfId": onu.PonPortID,
1376 "SerialNumber": onu.Sn(),
1377 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1378 "omciPkt": omciPkt,
1379 "omciMsgType": omciMsg.MessageType,
1380 }).Warn("dropping-omci-message")
1381 } else {
1382 msg := types.Message{
1383 Type: types.OMCI,
1384 Data: types.OmciMessage{
1385 OnuSN: onu.SerialNumber,
1386 OnuID: onu.ID,
1387 OmciMsg: omciMsg,
1388 OmciPkt: omciPkt,
1389 },
1390 }
1391 onu.Channel <- msg
1392 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001393 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001394}
1395
Matteo Scandolo8a574812021-05-20 15:18:53 -07001396// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301397func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001398 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001399 if err != nil {
1400 oltLogger.WithFields(log.Fields{
1401 "OnuId": onuPkt.OnuId,
1402 "IntfId": onuPkt.IntfId,
1403 "err": err,
1404 }).Error("Can't find PonPort")
1405 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001406 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001407 if err != nil {
1408 oltLogger.WithFields(log.Fields{
1409 "OnuId": onuPkt.OnuId,
1410 "IntfId": onuPkt.IntfId,
1411 "err": err,
1412 }).Error("Can't find Onu")
1413 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001414
Matteo Scandolo075b1892019-10-07 12:11:07 -07001415 oltLogger.WithFields(log.Fields{
1416 "IntfId": onu.PonPortID,
1417 "OnuId": onu.ID,
1418 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001419 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001420 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001421
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001422 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001423
1424 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001425 if err != nil {
1426 onuLogger.WithFields(log.Fields{
1427 "IntfId": onu.PonPortID,
1428 "OnuId": onu.ID,
1429 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001430 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001431 }).Error("Can't find pktType in packet, droppint it")
1432 return new(openolt.Empty), nil
1433 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001434
Matteo Scandolo4a036262020-08-17 15:56:13 -07001435 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001436 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001437 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001438 "IntfId": onu.PonPortID,
1439 "OnuId": onu.ID,
1440 "OnuSn": onu.Sn(),
1441 "Pkt": rawpkt.Data(),
1442 }).Error("Can't find Dst MacAddress in packet, droppint it")
1443 return new(openolt.Empty), nil
1444 }
1445
Matteo Scandolof9d43412021-01-12 11:11:34 -08001446 msg := types.Message{
1447 Type: types.OnuPacketOut,
1448 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001449 IntfId: onuPkt.IntfId,
1450 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001451 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001452 Packet: rawpkt,
1453 Type: pktType,
1454 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001455 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001456 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001457
Matteo Scandolo075b1892019-10-07 12:11:07 -07001458 onu.Channel <- msg
1459
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001460 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001461}
1462
Shrey Baid688b4242020-07-10 20:40:10 +05301463func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001464
1465 // OLT Reboot is called in two cases:
1466 // - 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)
1467 // - when an OLT needs to be rebooted (voltcl device reboot)
1468
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001469 oltLogger.WithFields(log.Fields{
1470 "oltId": o.ID,
1471 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301472 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301473 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001474 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001475}
1476
Shrey Baid688b4242020-07-10 20:40:10 +05301477func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301478 oltLogger.WithFields(log.Fields{
1479 "oltId": o.ID,
1480 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301481 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301482
Pragya Arya2225f202020-01-29 18:05:01 +05301483 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001484 oltMsg := types.Message{
1485 Type: types.OltIndication,
1486 Data: types.OltIndicationMessage{
1487 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301488 },
Pragya Arya1881df02020-01-29 18:05:01 +05301489 }
Pragya Arya2225f202020-01-29 18:05:01 +05301490 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301491
Pragya Arya2225f202020-01-29 18:05:01 +05301492 for _, pon := range o.Pons {
1493 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001494 msg := types.Message{
1495 Type: types.PonIndication,
1496 Data: types.PonIndicationMessage{
1497 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301498 PonPortID: pon.ID,
1499 },
1500 }
1501 o.channel <- msg
1502 }
1503 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001504
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001505 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001506}
1507
Shrey Baid688b4242020-07-10 20:40:10 +05301508func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001509 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1510
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001511 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1512
1513 if err != nil {
1514 return nil, err
1515 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001516 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001517}
1518
Shrey Baid688b4242020-07-10 20:40:10 +05301519func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001520 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001521 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001522}
1523
Shrey Baid688b4242020-07-10 20:40:10 +05301524func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001525 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001526 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001527}
1528
Shrey Baid688b4242020-07-10 20:40:10 +05301529func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001530 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001531 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001532}
1533
Shrey Baid688b4242020-07-10 20:40:10 +05301534func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001535 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001536 return new(openolt.Empty), nil
1537}
1538
Matteo Scandolo8a574812021-05-20 15:18:53 -07001539func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1540 oltLogger.WithFields(log.Fields{
1541 "OnuId": tq.OnuId,
1542 "IntfId": tq.IntfId,
1543 "OnuPortNo": tq.PortNo,
1544 "UniId": tq.UniId,
1545 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001546 return new(openolt.Empty), nil
1547}
1548
Matteo Scandolo8a574812021-05-20 15:18:53 -07001549func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301550 oltLogger.WithFields(log.Fields{
1551 "OnuId": trafficSchedulers.OnuId,
1552 "IntfId": trafficSchedulers.IntfId,
1553 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001554 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301555 }).Info("received CreateTrafficSchedulers")
1556
1557 if !s.enablePerf {
1558 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1559 if err != nil {
1560 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1561 return new(openolt.Empty), err
1562 }
1563 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1564 if err != nil {
1565 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1566 return new(openolt.Empty), err
1567 }
1568 onu.TrafficSchedulers = trafficSchedulers
1569 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001570 return new(openolt.Empty), nil
1571}
1572
Shrey Baid688b4242020-07-10 20:40:10 +05301573func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301574 oltLogger.WithFields(log.Fields{
1575 "OnuId": trafficSchedulers.OnuId,
1576 "IntfId": trafficSchedulers.IntfId,
1577 "OnuPortNo": trafficSchedulers.PortNo,
1578 }).Info("received RemoveTrafficSchedulers")
1579 if !s.enablePerf {
1580 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1581 if err != nil {
1582 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1583 return new(openolt.Empty), err
1584 }
1585 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1586 if err != nil {
1587 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1588 return new(openolt.Empty), err
1589 }
1590
1591 onu.TrafficSchedulers = nil
1592 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001593 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001594}
Scott Baker41724b82020-01-21 19:54:53 -08001595
Matteo Scandolo618a6582020-09-09 12:21:29 -07001596func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1597 oltLogger.WithFields(log.Fields{
1598 "GroupId": group.GroupId,
1599 "Command": group.Command,
1600 "Members": group.Members,
1601 "Action": group.Action,
1602 }).Debug("received PerformGroupOperation")
1603 return &openolt.Empty{}, nil
1604}
1605
1606func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1607 oltLogger.WithFields(log.Fields{
1608 "GroupId": group.GroupId,
1609 "Command": group.Command,
1610 "Members": group.Members,
1611 "Action": group.Action,
1612 }).Debug("received PerformGroupOperation")
1613 return &openolt.Empty{}, nil
1614}
1615
Matteo Scandolo1f9f4b22021-12-14 11:51:55 -08001616func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*extension.ReturnValues, error) {
1617 return &extension.ReturnValues{}, nil
Matteo Scandolo618a6582020-09-09 12:21:29 -07001618}
1619
1620func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1621 return &openolt.Empty{}, nil
1622}
1623
1624func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1625 return &openolt.OnuLogicalDistance{}, nil
1626}
1627
1628func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1629 return &openolt.OnuLogicalDistance{}, nil
1630}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001631
Girish Gowdra62f24292021-05-12 16:28:39 -07001632func (o *OltDevice) GetPonRxPower(ctx context.Context, in *openolt.Onu) (*openolt.PonRxPowerData, error) {
1633 return &openolt.PonRxPowerData{}, nil
1634}
1635
Matteo Scandolo96f89192021-03-12 13:17:26 -08001636func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1637 return &openolt.GemPortStatistics{}, nil
1638}
1639
1640func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1641 return &openolt.OnuStatistics{}, nil
1642}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001643
1644func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1645 o.AllocIDsLock.Lock()
1646 defer o.AllocIDsLock.Unlock()
1647
Matteo Scandolo21195d62021-04-07 14:31:23 -07001648 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1649 oltLogger.WithFields(log.Fields{
1650 "IntfId": flow.AccessIntfId,
1651 "OnuId": flow.OnuId,
1652 "PortNo": flow.PortNo,
1653 "GemportId": flow.GemportId,
1654 "FlowId": flow.FlowId,
1655 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1656 }
1657
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001658 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001659 "IntfId": flow.AccessIntfId,
1660 "OnuId": flow.OnuId,
1661 "PortNo": flow.PortNo,
1662 "GemportId": flow.GemportId,
1663 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001664 }).Trace("storing-alloc-id-via-flow")
1665
1666 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1667 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1668 }
1669 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1670 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1671 }
1672 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1673}
1674
1675func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1676 // if this is the last flow referencing the AllocId then remove it
1677 o.AllocIDsLock.Lock()
1678 defer o.AllocIDsLock.Unlock()
1679
1680 oltLogger.WithFields(log.Fields{
1681 "IntfId": flow.AccessIntfId,
1682 "OnuId": flow.OnuId,
1683 "PortNo": flow.PortNo,
1684 "GemportId": flow.GemportId,
1685 }).Trace("freeing-alloc-id-via-flow")
1686
1687 // NOTE look at the freeGemPortId implementation for comments and context
1688 for ponId, ponValues := range o.AllocIDs {
1689 for onuId, onuValues := range ponValues {
1690 for uniId, uniValues := range onuValues {
1691 for allocId, flows := range uniValues {
1692 for flowId := range flows {
1693 // if the flow matches, remove it from the map.
1694 if flow.FlowId == flowId {
1695 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1696 }
1697 // if that was the last flow for a particular allocId, remove the entire allocId
1698 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1699 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1700 }
1701 }
1702 }
1703 }
1704 }
1705 }
1706}
1707
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001708func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001709 o.GemPortIDsLock.Lock()
1710 defer o.GemPortIDsLock.Unlock()
1711
1712 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1713 oltLogger.WithFields(log.Fields{
1714 "IntfId": ponId,
1715 "OnuId": onuId,
1716 "PortNo": portNo,
1717 "GemportId": gemId,
1718 "FlowId": flowId,
1719 }).Error("trying-to-store-gemport-for-unknown-onu")
1720 }
1721
1722 oltLogger.WithFields(log.Fields{
1723 "IntfId": ponId,
1724 "OnuId": onuId,
1725 "PortNo": portNo,
1726 "GemportId": gemId,
1727 "FlowId": flowId,
1728 }).Trace("storing-alloc-id-via-flow")
1729
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001730 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1731 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1732 }
1733 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1734 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1735 }
1736 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1737}
1738
1739func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001740 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001741 "IntfId": flow.AccessIntfId,
1742 "OnuId": flow.OnuId,
1743 "PortNo": flow.PortNo,
1744 "GemportId": flow.GemportId,
1745 "FlowId": flow.FlowId,
1746 "ReplicateFlow": flow.ReplicateFlow,
1747 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001748 }).Trace("storing-gem-port-id-via-flow")
1749
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001750 if flow.ReplicateFlow {
1751 for _, gem := range flow.PbitToGemport {
1752 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1753 }
1754 } else {
1755 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001756 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001757}
1758
1759func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1760 // if this is the last flow referencing the GemPort then remove it
1761 o.GemPortIDsLock.Lock()
1762 defer o.GemPortIDsLock.Unlock()
1763
1764 oltLogger.WithFields(log.Fields{
1765 "IntfId": flow.AccessIntfId,
1766 "OnuId": flow.OnuId,
1767 "PortNo": flow.PortNo,
1768 "GemportId": flow.GemportId,
1769 }).Trace("freeing-gem-port-id-via-flow")
1770
1771 // NOTE that this loop is not very performant, it would be better if the flow carries
1772 // the same information that it carries during a FlowAdd. If so we can directly remove
1773 // items from the map
1774
1775 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1776 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1777 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1778 //}
1779
1780 // NOTE this loop assumes that flow IDs are unique per device
1781 for ponId, ponValues := range o.GemPortIDs {
1782 for onuId, onuValues := range ponValues {
1783 for uniId, uniValues := range onuValues {
1784 for gemId, flows := range uniValues {
1785 for flowId := range flows {
1786 // if the flow matches, remove it from the map.
1787 if flow.FlowId == flowId {
1788 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1789 }
1790 // if that was the last flow for a particular gem, remove the entire gem
1791 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1792 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1793 }
1794 }
1795 }
1796 }
1797 }
1798 }
1799}
1800
1801// validateFlow checks that:
1802// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1803// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1804func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001805 // validate gemPort
1806 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001807 defer o.GemPortIDsLock.RUnlock()
1808 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001809 if onuId == uint32(flow.OnuId) {
1810 continue
1811 }
1812 for uniId, uni := range onu {
1813 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001814 if flow.ReplicateFlow {
1815 for _, flowGem := range flow.PbitToGemport {
1816 if gem == int32(flowGem) {
1817 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1818 }
1819 }
1820 } else {
1821 if gem == flow.GemportId {
1822 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1823 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001824 }
1825 }
1826 }
1827 }
1828
1829 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001830 defer o.AllocIDsLock.RUnlock()
1831 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001832 if onuId == uint32(flow.OnuId) {
1833 continue
1834 }
1835 for uniId, uni := range onu {
1836 for allocId := range uni {
1837 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001838 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 -08001839 }
1840 }
1841 }
1842 }
1843
1844 return nil
1845}
1846
1847// clearAllResources is invoked up OLT Reboot to remove all the allocated
1848// GemPorts, AllocId and ONU-IDs across the PONs
1849func (o *OltDevice) clearAllResources() {
1850
1851 // remove the resources received via flows
1852 o.GemPortIDsLock.Lock()
1853 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1854 o.GemPortIDsLock.Unlock()
1855 o.AllocIDsLock.Lock()
1856 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1857 o.AllocIDsLock.Unlock()
1858
1859 // remove the resources received via OMCI
1860 for _, pon := range o.Pons {
1861 pon.removeAllAllocIds()
1862 pon.removeAllGemPorts()
1863 pon.removeAllOnuIds()
1864 }
1865}