blob: 1c4e0999203a7de29bc89cf5f62377d043668110 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
20 "context"
Matteo Scandolo4a036262020-08-17 15:56:13 -070021 "encoding/hex"
Matteo Scandolo4747d292019-08-05 11:50:18 -070022 "fmt"
Matteo Scandolo90d08f62020-10-29 12:06:55 -070023 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
Matteo Scandolof9d43412021-01-12 11:11:34 -080024 "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolob5913142021-03-19 16:10:18 -070025 omcilib "github.com/opencord/bbsim/internal/common/omci"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070026 "github.com/opencord/voltha-protos/v4/go/ext/config"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020027 "net"
Matteo Scandolof9d43412021-01-12 11:11:34 -080028 "strconv"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020029 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010030 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020031
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070032 "github.com/google/gopacket"
33 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070034 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070035 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010036 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070037 common_protos "github.com/opencord/voltha-protos/v4/go/common"
38 "github.com/opencord/voltha-protos/v4/go/openolt"
39 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070040 log "github.com/sirupsen/logrus"
41 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053042 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010043 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053044 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070045)
46
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070047var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070048 "module": "OLT",
49})
50
Matteo Scandolocedde462021-03-09 17:37:16 -080051const (
52 onuIdStart = 1
53 onuIdEnd = 127
54 allocIdStart = 1024
55 allocIdEnd = 16383
56 gemportIdStart = 1024
57 gemportIdEnd = 65535
58 flowIdStart = 1
59 flowIdEnd = 65535
60)
61
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070062type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000063 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000064 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000065
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070066 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053067 ID int
68 SerialNumber string
69 NumNni int
70 NumPon int
71 NumOnuPerPon int
72 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080073 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070074 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010075 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053076 Delay int
77 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053078 EventChannel chan common.Event
79 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053080 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080081 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070082
Matteo Scandolo27428702019-10-11 16:21:16 -070083 Pons []*PonPort
84 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070085
86 // OLT Attributes
87 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000088
89 enableContext context.Context
90 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053091
Matteo Scandolo4a036262020-08-17 15:56:13 -070092 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053093 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080094
95 // Allocated Resources
96 // this data are to verify that the openolt adapter does not duplicate resources
97 AllocIDsLock sync.RWMutex
98 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
99 GemPortIDsLock sync.RWMutex
100 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
Matteo Scandolo4747d292019-08-05 11:50:18 -0700101}
102
Matteo Scandolo27428702019-10-11 16:21:16 -0700103var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700104
Matteo Scandolo27428702019-10-11 16:21:16 -0700105func GetOLT() *OltDevice {
106 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700107}
108
Matteo Scandolo4a036262020-08-17 15:56:13 -0700109func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700110 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530111 "ID": options.Olt.ID,
112 "NumNni": options.Olt.NniPorts,
113 "NumPon": options.Olt.PonPorts,
114 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700115 }).Debug("CreateOLT")
116
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700117 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530118 ID: options.Olt.ID,
119 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700120 OperState: getOperStateFSM(func(e *fsm.Event) {
121 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
122 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800123 NumNni: int(options.Olt.NniPorts),
124 NumPon: int(options.Olt.PonPorts),
125 NumOnuPerPon: int(options.Olt.OnusPonPort),
126 Pons: []*PonPort{},
127 Nnis: []*NniPort{},
128 Delay: options.BBSim.Delay,
129 enablePerf: options.BBSim.EnablePerf,
130 PublishEvents: options.BBSim.Events,
131 PortStatsInterval: options.Olt.PortStatsInterval,
132 dhcpServer: dhcp.NewDHCPServer(),
133 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800134 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
135 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 }
137
Pragya Arya996a0892020-03-09 21:47:52 +0530138 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530139 olt.ControlledActivation = val
140 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700141 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530142 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
143 olt.ControlledActivation = Default
144 }
145
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700147 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 olt.InternalState = fsm.NewFSM(
149 "created",
150 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800151 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100152 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700153 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700154 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800155 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700156 },
157 fsm.Callbacks{
158 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700159 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700160 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100161 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800162 "enter_deleted": func(e *fsm.Event) {
163 // remove all the resource allocations
164 olt.clearAllResources()
165 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166 },
167 )
168
Shrey Baid688b4242020-07-10 20:40:10 +0530169 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700170 // create NNI Port
171 nniPort, err := CreateNNI(&olt)
172 if err != nil {
173 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
174 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700175
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700176 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700177 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700178
Matteo Scandolo4a036262020-08-17 15:56:13 -0700179 // Create device and Services
180
181 nextCtag := map[string]int{}
182 nextStag := map[string]int{}
183
Matteo Scandolo4747d292019-08-05 11:50:18 -0700184 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700185 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800186
187 // initialize the resource maps for every PON Ports
188 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
189 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
190
Matteo Scandolo4a036262020-08-17 15:56:13 -0700191 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700192
Matteo Scandolo4a036262020-08-17 15:56:13 -0700193 // create ONU devices
194 for j := 0; j < olt.NumOnuPerPon; j++ {
195 delay := time.Duration(olt.Delay*j) * time.Millisecond
196 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700197
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198 for k, s := range common.Services {
199
200 // find the correct cTag for this service
201 if _, ok := nextCtag[s.Name]; !ok {
202 // it's the first time we iterate over this service,
203 // so we start from the config value
204 nextCtag[s.Name] = s.CTag
205 } else {
206 // we have a previous value, so we check it
207 // if Allocation is unique, we increment,
208 // otherwise (shared) we do nothing
209 if s.CTagAllocation == common.TagAllocationUnique.String() {
210 nextCtag[s.Name] = nextCtag[s.Name] + 1
211 }
212 }
213
214 // find the correct sTag for this service
215 if _, ok := nextStag[s.Name]; !ok {
216 nextStag[s.Name] = s.STag
217 } else {
218 if s.STagAllocation == common.TagAllocationUnique.String() {
219 nextStag[s.Name] = nextStag[s.Name] + 1
220 }
221 }
222
223 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
224 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
225 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
226 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
227
228 if err != nil {
229 oltLogger.WithFields(log.Fields{
230 "Err": err.Error(),
231 }).Fatal("Can't create Service")
232 }
233
234 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700235 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700236 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700237 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700238 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700239 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100240
Shrey Baid688b4242020-07-10 20:40:10 +0530241 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700242 if err := olt.InternalState.Event("initialize"); err != nil {
243 log.Errorf("Error initializing OLT: %v", err)
244 return nil
245 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246 }
247
Pragya Arya324337e2020-02-20 14:35:08 +0530248 if olt.PublishEvents {
249 log.Debugf("BBSim event publishing is enabled")
250 // Create a channel to write event messages
251 olt.EventChannel = make(chan common.Event, 100)
252 }
253
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700254 return &olt
255}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700256
Shrey Baid688b4242020-07-10 20:40:10 +0530257func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100258
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000259 if o.OltServer == nil {
260 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100261 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800262 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100263 }
264
265 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800266 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100267
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100268 // FIXME we are assuming we have only one NNI
269 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800270 // NOTE we want to make sure the state is down when we initialize the OLT,
271 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
272 // in-band management
273 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800275
276 for ponId := range o.Pons {
277 // initialize the resource maps for every PON Ports
278 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
279 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
280 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700281}
282
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800283func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100284
Matteo Scandolo96f89192021-03-12 13:17:26 -0800285 o.PreviouslyConnected = false
286
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700287 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700288 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800289
290 oltLogger.WithFields(log.Fields{
291 "oltId": o.ID,
292 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
293
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700294 if o.InternalState.Is("enabled") {
295 oltLogger.WithFields(log.Fields{
296 "oltId": o.ID,
297 }).Info("This is an OLT soft reboot")
298 softReboot = true
299 }
300
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800301 // transition internal state to deleted
302 if err := o.InternalState.Event("delete"); err != nil {
303 oltLogger.WithFields(log.Fields{
304 "oltId": o.ID,
305 }).Errorf("Error deleting OLT: %v", err)
306 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100307 }
308
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800309 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
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800310 o.StopOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100311
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700312 if softReboot {
313 for _, pon := range o.Pons {
314 if pon.InternalState.Current() == "enabled" {
315 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800316 msg := types.Message{
317 Type: types.PonIndication,
318 Data: types.PonIndicationMessage{
319 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700320 PonPortID: pon.ID,
321 },
322 }
323 o.channel <- msg
324 }
325
326 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800327 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700328 }
329 }
330 } else {
331 // PONs are already handled in the Disable call
332 for _, pon := range olt.Pons {
333 // ONUs are not automatically disabled when a PON goes down
334 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
335 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800336 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700337 }
Pragya Arya2225f202020-01-29 18:05:01 +0530338 }
339 }
340
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100341 // terminate the OLT's processOltMessages go routine
342 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700343
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700344 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100345
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100346 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100347
348 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800349 oltLogger.WithFields(log.Fields{
350 "oltId": o.ID,
351 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100352 return err
353 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800354 oltLogger.WithFields(log.Fields{
355 "oltId": o.ID,
356 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100357 return nil
358}
359
360// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800361func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700362 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700363 lis, err := net.Listen("tcp", address)
364 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700365 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700366 }
367 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100368
Matteo Scandolo4747d292019-08-05 11:50:18 -0700369 openolt.RegisterOpenoltServer(grpcServer, o)
370
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100371 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700372
Shrey Baid688b4242020-07-10 20:40:10 +0530373 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100374 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700375
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100376 return grpcServer, nil
377}
378
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800379// StartOltServer will create the grpc server that VOLTHA uses
380// to communicate with the device
381func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
382 oltServer, err := o.newOltServer()
383 if err != nil {
384 oltLogger.WithFields(log.Fields{
385 "err": err,
386 }).Error("Cannot OLT gRPC server")
387 return nil, err
388 }
389 return oltServer, nil
390}
391
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100392// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800393func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000394 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800395 oltLogger.WithFields(log.Fields{
396 "oltId": o.SerialNumber,
397 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000398 o.OltServer.Stop()
399 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700400 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700401}
402
403// Device Methods
404
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100405// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530406func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700407 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530408 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700409
David Bainbridge103cf022019-12-16 20:11:35 +0000410 // If enabled has already been called then an enabled context has
411 // been created. If this is the case then we want to cancel all the
412 // proessing loops associated with that enable before we recreate
413 // new ones
414 o.Lock()
415 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700416 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000417 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530418 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700419 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000420 }
421 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
422 o.Unlock()
423
Matteo Scandolo4747d292019-08-05 11:50:18 -0700424 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700425
Matteo Scandolo4a036262020-08-17 15:56:13 -0700426 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530427
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100428 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700429 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000430 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431
432 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800433 oltMsg := types.Message{
434 Type: types.OltIndication,
435 Data: types.OltIndicationMessage{
436 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700437 },
438 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100439 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700440
441 // send NNI Port Indications
442 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800443 msg := types.Message{
444 Type: types.NniIndication,
445 Data: types.NniIndicationMessage{
446 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700447 NniPortID: nni.ID,
448 },
449 }
450 o.channel <- msg
451 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100452
Shrey Baid688b4242020-07-10 20:40:10 +0530453 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530454 for _, pon := range o.Pons {
455 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800456 msg := types.Message{
457 Type: types.PonIndication,
458 Data: types.PonIndicationMessage{
459 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530460 PonPortID: pon.ID,
461 },
462 }
463 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000464 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700465 // when the enableContext was canceled the ONUs stopped listening on the channel
466 for _, onu := range pon.Onus {
467 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
468
469 // update the stream on all the services
470 for _, service := range onu.Services {
471 service.UpdateStream(stream)
472 }
473 }
Pragya Arya2225f202020-01-29 18:05:01 +0530474 }
475 } else {
476
477 // 1. controlledActivation == Default: Send both PON and ONUs indications
478 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
479
480 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
481 // send PON Port indications
482 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800483 msg := types.Message{
484 Type: types.PonIndication,
485 Data: types.PonIndicationMessage{
486 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530487 PonPortID: pon.ID,
488 },
489 }
490 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700491 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700492 }
493 }
494
Pragya Arya996a0892020-03-09 21:47:52 +0530495 if !o.enablePerf {
496 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700497 wg.Add(1)
498 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530499 }
500
Matteo Scandolo4747d292019-08-05 11:50:18 -0700501 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700502 oltLogger.WithFields(log.Fields{
503 "stream": stream,
504 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700505}
506
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700507func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530508 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700509
510loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530511 for {
512 select {
513 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
514 // send NNI port stats
515 for _, port := range o.Nnis {
516 incrementStat := true
517 if port.OperState.Current() == "down" {
518 incrementStat = false
519 }
520 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700521 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530522 }
523
524 // send PON port stats
525 for _, port := range o.Pons {
526 incrementStat := true
527 // do not increment port stats if PON port is down or no ONU is activated on PON port
528 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
529 incrementStat = false
530 }
531 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700532 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530533 }
534 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700535 oltLogger.Debug("Stop sending port stats")
536 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530537 }
Pragya Arya996a0892020-03-09 21:47:52 +0530538 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700539 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530540}
541
Matteo Scandolo4747d292019-08-05 11:50:18 -0700542// Helpers method
543
Matteo Scandolof9d43412021-01-12 11:11:34 -0800544func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
545
546 switch interfaceType {
547 case "nni":
548 if !o.HasNni(interfaceId) {
549 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
550 }
551
552 case "pon":
553 if !o.HasPon(interfaceId) {
554 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
555 }
556 }
557
558 alarmIndication := &openolt.AlarmIndication{
559 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
560 Status: alarmStatus,
561 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
562 }},
563 }
564
565 msg := types.Message{
566 Type: types.AlarmIndication,
567 Data: alarmIndication,
568 }
569
570 o.channel <- msg
571
572 return nil
573}
574
575func (o *OltDevice) HasNni(id uint32) bool {
576 for _, intf := range o.Nnis {
577 if intf.ID == id {
578 return true
579 }
580 }
581 return false
582}
583
584func (o *OltDevice) HasPon(id uint32) bool {
585 for _, intf := range o.Pons {
586 if intf.ID == id {
587 return true
588 }
589 }
590 return false
591}
592
Shrey Baid688b4242020-07-10 20:40:10 +0530593func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594 for _, pon := range o.Pons {
595 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700596 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597 }
598 }
Shrey Baid688b4242020-07-10 20:40:10 +0530599 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700600}
601
Shrey Baid688b4242020-07-10 20:40:10 +0530602func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603 for _, nni := range o.Nnis {
604 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700605 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700606 }
607 }
Shrey Baid688b4242020-07-10 20:40:10 +0530608 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609}
610
Scott Baker41724b82020-01-21 19:54:53 -0800611func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
612 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
613 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
614 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
615 return
616 }
617
618 oltLogger.WithFields(log.Fields{
619 "AlarmIndication": alarmInd,
620 }).Debug("Sent Indication_AlarmInd")
621}
622
Matteo Scandolof9d43412021-01-12 11:11:34 -0800623func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700624 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
625 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700626 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800627 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700628 }
629
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700630 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700631 "OperState": msg.OperState,
632 }).Debug("Sent Indication_OltInd")
633}
634
Matteo Scandolof9d43412021-01-12 11:11:34 -0800635func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800637 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800638 if err := nni.OperState.Event("enable"); err != nil {
639 log.WithFields(log.Fields{
640 "Type": nni.Type,
641 "IntfId": nni.ID,
642 "OperState": nni.OperState.Current(),
643 }).Errorf("Can't move NNI Port to enabled state: %v", err)
644 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800645 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800646 if err := nni.OperState.Event("disable"); err != nil {
647 log.WithFields(log.Fields{
648 "Type": nni.Type,
649 "IntfId": nni.ID,
650 "OperState": nni.OperState.Current(),
651 }).Errorf("Can't move NNI Port to disable state: %v", err)
652 }
653 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700655 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700656 Type: nni.Type,
657 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700658 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700659 }}
660
661 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700662 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800663 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664 }
665
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700666 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700667 "Type": nni.Type,
668 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700669 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700670 }).Debug("Sent Indication_IntfOperInd for NNI")
671}
672
Pragya Arya2225f202020-01-29 18:05:01 +0530673func (o *OltDevice) sendPonIndication(ponPortID uint32) {
674
Matteo Scandolo4a036262020-08-17 15:56:13 -0700675 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530676 pon, _ := o.GetPonById(ponPortID)
677 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700678 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700679 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: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700684 oltLogger.Errorf("Failed to send Indication_IntfInd: %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 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700690 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700691 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700692
Pragya Arya2225f202020-01-29 18:05:01 +0530693 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700694 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700695 Type: pon.Type,
696 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700697 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700698 }}
699
700 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700701 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800702 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700703 }
704
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700705 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700706 "Type": pon.Type,
707 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700708 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700709 }).Debug("Sent Indication_IntfOperInd for PON")
710}
711
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700712func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530713 if o.InternalState.Current() == "enabled" {
714 oltLogger.WithFields(log.Fields{
715 "Type": portType,
716 "IntfId": portID,
717 }).Trace("Sending port stats")
718 stats.IntfId = InterfaceIDToPortNo(portID, portType)
719 data := &openolt.Indication_PortStats{
720 PortStats: stats,
721 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700722
Shrey Baid55f328c2020-07-07 19:20:42 +0530723 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
724 oltLogger.Errorf("Failed to send PortStats: %v", err)
725 return
726 }
Pragya Arya996a0892020-03-09 21:47:52 +0530727 }
728}
729
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100730// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700731func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
732 oltLogger.WithFields(log.Fields{
733 "stream": stream,
734 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000735 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700736
David Bainbridge103cf022019-12-16 20:11:35 +0000737loop:
738 for {
739 select {
740 case <-ctx.Done():
741 oltLogger.Debug("OLT Indication processing canceled via context")
742 break loop
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700743 case <-stream.Context().Done():
744 oltLogger.Debug("OLT Indication processing canceled via stream context")
745 break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000746 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700747 if !ok {
748 if ctx.Err() != nil {
749 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
750 }
751 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000752 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700753 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700754
David Bainbridge103cf022019-12-16 20:11:35 +0000755 oltLogger.WithFields(log.Fields{
756 "oltId": o.ID,
757 "messageType": message.Type,
758 }).Trace("Received message")
759
760 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800761 case types.OltIndication:
762 msg, _ := message.Data.(types.OltIndicationMessage)
763 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530764 _ = o.InternalState.Event("enable")
765 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800766 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530767 _ = o.InternalState.Event("disable")
768 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000769 }
770 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800771 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800772 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
773 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800774 case types.NniIndication:
775 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000776 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800777 case types.PonIndication:
778 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530779 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800780 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530781 if err := pon.OperState.Event("enable"); err != nil {
782 oltLogger.WithFields(log.Fields{
783 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800784 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530785 }).Error("Can't Enable Oper state for PON Port")
786 }
787 if err := pon.InternalState.Event("enable"); err != nil {
788 oltLogger.WithFields(log.Fields{
789 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800790 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530791 }).Error("Can't Enable Internal state for PON Port")
792 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800793 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530794 if err := pon.OperState.Event("disable"); err != nil {
795 oltLogger.WithFields(log.Fields{
796 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800797 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530798 }).Error("Can't Disable Oper state for PON Port")
799 }
800 if err := pon.InternalState.Event("disable"); err != nil {
801 oltLogger.WithFields(log.Fields{
802 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800803 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530804 }).Error("Can't Disable Internal state for PON Port")
805 }
Pragya Arya2225f202020-01-29 18:05:01 +0530806 }
David Bainbridge103cf022019-12-16 20:11:35 +0000807 default:
808 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
809 }
810 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700811 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100812 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700813 oltLogger.WithFields(log.Fields{
814 "stream": stream,
815 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700816}
817
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700818// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530819func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200820 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700821 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700822 for _, pon := range o.Pons {
823 for _, onu := range pon.Onus {
824 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700825 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700826 }
827 }
828 }
829
Shrey Baid688b4242020-07-10 20:40:10 +0530830 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700831}
832
William Kurkian9dadc5b2019-10-22 13:51:57 -0400833// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530834func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200835 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400836 // memoizing it will remove the bottleneck
837 for _, pon := range o.Pons {
838 if pon.ID == intfId {
839 for _, onu := range pon.Onus {
840 if onu.ID == onuId {
841 return onu, nil
842 }
843 }
844 }
845 }
Shrey Baid688b4242020-07-10 20:40:10 +0530846 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400847}
848
Matteo Scandolo4a036262020-08-17 15:56:13 -0700849// returns a Service with a given Mac Address
850func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200851 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700852 // memoizing it will remove the bottleneck
853 for _, pon := range o.Pons {
854 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700855 s, err := onu.findServiceByMacAddress(mac)
856 if err == nil {
857 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700858 }
859 }
860 }
861
Matteo Scandolo4a036262020-08-17 15:56:13 -0700862 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700863}
864
Matteo Scandolo4747d292019-08-05 11:50:18 -0700865// GRPC Endpoints
866
Shrey Baid688b4242020-07-10 20:40:10 +0530867func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700868 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700869 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700870 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530871 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700872
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700873 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800874
875 // Initialize the resource maps for this ONU
876 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
877 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
878
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700879 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500880 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700881
Matteo Scandolocedde462021-03-09 17:37:16 -0800882 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700883 oltLogger.WithFields(log.Fields{
884 "IntfId": _onu.PonPortID,
885 "OnuSn": _onu.Sn(),
886 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800887 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700888 }
889
890 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
891
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700892 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700893}
894
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800895func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700896 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700897 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700898}
899
Shrey Baid688b4242020-07-10 20:40:10 +0530900func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530901 oltLogger.WithFields(log.Fields{
902 "IntfId": onu.IntfId,
903 "OnuId": onu.OnuId,
904 }).Info("Received DeleteOnu call from VOLTHA")
905
906 pon, err := o.GetPonById(onu.IntfId)
907 if err != nil {
908 oltLogger.WithFields(log.Fields{
909 "OnuId": onu.OnuId,
910 "IntfId": onu.IntfId,
911 "err": err,
912 }).Error("Can't find PonPort")
913 }
914 _onu, err := pon.GetOnuById(onu.OnuId)
915 if err != nil {
916 oltLogger.WithFields(log.Fields{
917 "OnuId": onu.OnuId,
918 "IntfId": onu.IntfId,
919 "err": err,
920 }).Error("Can't find Onu")
921 }
922
Matteo Scandolocedde462021-03-09 17:37:16 -0800923 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530924 oltLogger.WithFields(log.Fields{
925 "IntfId": _onu.PonPortID,
926 "OnuSn": _onu.Sn(),
927 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800928 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530929 }
930
Hardik Windlassad790cb2020-06-17 21:26:22 +0530931 // ONU Re-Discovery
932 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530933 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530934 }
935
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700936 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700937}
938
Shrey Baid688b4242020-07-10 20:40:10 +0530939func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700940 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800941 oltLogger.WithFields(log.Fields{
942 "oltId": o.ID,
943 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530944 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800945
Matteo Scandolo401503a2019-12-11 14:48:14 -0800946 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530947 if pon.InternalState.Current() == "enabled" {
948 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800949 msg := types.Message{
950 Type: types.PonIndication,
951 Data: types.PonIndicationMessage{
952 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530953 PonPortID: pon.ID,
954 },
955 }
956 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800957 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800958 }
959
Matteo Scandolo401503a2019-12-11 14:48:14 -0800960 // Note that we are not disabling the NNI as the real OLT does not.
961 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800962
963 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800964 oltMsg := types.Message{
965 Type: types.OltIndication,
966 Data: types.OltIndicationMessage{
967 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700968 },
969 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100970 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700971 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700972}
973
Shrey Baid688b4242020-07-10 20:40:10 +0530974func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530975 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200976 ponID := intf.GetIntfId()
977 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200978
Matteo Scandolof9d43412021-01-12 11:11:34 -0800979 msg := types.Message{
980 Type: types.PonIndication,
981 Data: types.PonIndicationMessage{
982 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200983 PonPortID: ponID,
984 },
985 }
986 o.channel <- msg
987
988 for _, onu := range pon.Onus {
989
Matteo Scandolof9d43412021-01-12 11:11:34 -0800990 onuIndication := types.OnuIndicationMessage{
991 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200992 PonPortID: ponID,
993 OnuID: onu.ID,
994 OnuSN: onu.SerialNumber,
995 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700996 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200997
998 }
999
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001000 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001001}
1002
Zdravko Bozakov681364d2019-11-10 14:28:46 +01001003func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001004 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301005 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001006 o.Enable(stream)
1007 return nil
1008}
1009
Shrey Baid688b4242020-07-10 20:40:10 +05301010func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301011 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301012 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001013 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001014
Matteo Scandolof9d43412021-01-12 11:11:34 -08001015 msg := types.Message{
1016 Type: types.PonIndication,
1017 Data: types.PonIndicationMessage{
1018 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301019 PonPortID: ponID,
1020 },
1021 }
1022 o.channel <- msg
1023
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001024 for _, onu := range pon.Onus {
1025
Matteo Scandolof9d43412021-01-12 11:11:34 -08001026 onuIndication := types.OnuIndicationMessage{
1027 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001028 PonPortID: ponID,
1029 OnuID: onu.ID,
1030 OnuSN: onu.SerialNumber,
1031 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001032 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001033
1034 }
1035
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001036 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001037}
1038
Shrey Baid688b4242020-07-10 20:40:10 +05301039func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001040 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001041 "IntfId": flow.AccessIntfId,
1042 "OnuId": flow.OnuId,
1043 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001044 "InnerVlan": flow.Classifier.IVid,
1045 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001046 "FlowType": flow.FlowType,
1047 "FlowId": flow.FlowId,
1048 "UniID": flow.UniId,
1049 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301050 }).Tracef("OLT receives FlowAdd")
1051
1052 flowKey := FlowKey{}
1053 if !o.enablePerf {
1054 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001055 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301056 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001057
1058 if flow.AccessIntfId == -1 {
1059 oltLogger.WithFields(log.Fields{
1060 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001061 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001062 } else if flow.FlowType == "multicast" {
1063 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001064 "Cookie": flow.Cookie,
1065 "DstPort": flow.Classifier.DstPort,
1066 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1067 "FlowId": flow.FlowId,
1068 "FlowType": flow.FlowType,
1069 "GemportId": flow.GemportId,
1070 "InnerVlan": flow.Classifier.IVid,
1071 "IntfId": flow.AccessIntfId,
1072 "IpProto": flow.Classifier.IpProto,
1073 "OnuId": flow.OnuId,
1074 "OuterVlan": flow.Classifier.OVid,
1075 "PortNo": flow.PortNo,
1076 "SrcPort": flow.Classifier.SrcPort,
1077 "UniID": flow.UniId,
1078 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001079 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001080 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001081 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001082 if err != nil {
1083 oltLogger.WithFields(log.Fields{
1084 "OnuId": flow.OnuId,
1085 "IntfId": flow.AccessIntfId,
1086 "err": err,
1087 }).Error("Can't find PonPort")
1088 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001089 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001090 if err != nil {
1091 oltLogger.WithFields(log.Fields{
1092 "OnuId": flow.OnuId,
1093 "IntfId": flow.AccessIntfId,
1094 "err": err,
1095 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001096 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001097 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301098 if !o.enablePerf {
1099 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301100 // Generate event on first flow for ONU
1101 if len(onu.Flows) == 1 {
1102 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1103 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301104 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001105
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001106 // validate that the flow reference correct IDs (Alloc, Gem)
1107 if err := o.validateFlow(flow); err != nil {
1108 oltLogger.WithFields(log.Fields{
1109 "OnuId": flow.OnuId,
1110 "IntfId": flow.AccessIntfId,
1111 "Flow": flow,
1112 "SerialNumber": onu.Sn(),
1113 "err": err,
1114 }).Error("invalid-flow-for-onu")
1115 return nil, err
1116 }
1117
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001118 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001119 o.storeAllocId(flow)
1120
Matteo Scandolof9d43412021-01-12 11:11:34 -08001121 msg := types.Message{
1122 Type: types.FlowAdd,
1123 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001124 PonPortID: pon.ID,
1125 OnuID: onu.ID,
1126 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001127 },
1128 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001129 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001130 }
1131
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001132 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001133}
1134
Pragya Arya8bdb4532020-03-02 17:08:09 +05301135// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301136func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001137
Pragya Arya8bdb4532020-03-02 17:08:09 +05301138 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001139 "AllocId": flow.AllocId,
1140 "Cookie": flow.Cookie,
1141 "FlowId": flow.FlowId,
1142 "FlowType": flow.FlowType,
1143 "GemportId": flow.GemportId,
1144 "IntfId": flow.AccessIntfId,
1145 "OnuId": flow.OnuId,
1146 "PortNo": flow.PortNo,
1147 "UniID": flow.UniId,
1148 "ReplicateFlow": flow.ReplicateFlow,
1149 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001150 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301151
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001152 olt.freeGemPortId(flow)
1153 olt.freeAllocId(flow)
1154
Pragya Arya8bdb4532020-03-02 17:08:09 +05301155 if !o.enablePerf { // remove only if flow were stored
1156 flowKey := FlowKey{
1157 ID: flow.FlowId,
1158 Direction: flow.FlowType,
1159 }
1160
1161 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001162 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301163 if !ok {
1164 oltLogger.Errorf("Flow %v not found", flow)
1165 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1166 }
1167
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001168 storedFlow := storedFlowIntf.(openolt.Flow)
1169
Pragya Arya8bdb4532020-03-02 17:08:09 +05301170 // if its ONU flow remove it from ONU also
1171 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001172 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1173 if err != nil {
1174 oltLogger.WithFields(log.Fields{
1175 "OnuId": storedFlow.OnuId,
1176 "IntfId": storedFlow.AccessIntfId,
1177 "PONs": olt.Pons,
1178 "err": err,
1179 }).Error("PON-port-not-found")
1180 return new(openolt.Empty), nil
1181 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301182 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1183 if err != nil {
1184 oltLogger.WithFields(log.Fields{
1185 "OnuId": storedFlow.OnuId,
1186 "IntfId": storedFlow.AccessIntfId,
1187 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001188 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301189 return new(openolt.Empty), nil
1190 }
1191 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301192 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301193 }
1194
1195 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001196 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301197 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001198
1199 if flow.AccessIntfId == -1 {
1200 oltLogger.WithFields(log.Fields{
1201 "FlowId": flow.FlowId,
1202 }).Debug("Removing OLT flow")
1203 } else if flow.FlowType == "multicast" {
1204 oltLogger.WithFields(log.Fields{
1205 "FlowId": flow.FlowId,
1206 }).Debug("Removing OLT multicast flow")
1207 } else {
1208
1209 onu, err := o.GetOnuByFlowId(flow.FlowId)
1210 if err != nil {
1211 oltLogger.WithFields(log.Fields{
1212 "OnuId": flow.OnuId,
1213 "IntfId": flow.AccessIntfId,
1214 "err": err,
1215 }).Error("Can't find Onu")
1216 return nil, err
1217 }
1218
Matteo Scandolof9d43412021-01-12 11:11:34 -08001219 msg := types.Message{
1220 Type: types.FlowRemoved,
1221 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301222 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001223 },
1224 }
1225 onu.Channel <- msg
1226 }
1227
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001228 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001229}
1230
Shrey Baid688b4242020-07-10 20:40:10 +05301231func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001232 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1233 oltLogger.WithFields(log.Fields{
1234 "signature": res.HeartbeatSignature,
1235 }).Trace("HeartbeatCheck")
1236 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001237}
1238
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001239func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001240 for _, pon := range o.Pons {
1241 for _, onu := range pon.Onus {
1242 for _, fId := range onu.FlowIds {
1243 if fId == flowId {
1244 return onu, nil
1245 }
1246 }
1247 }
1248 }
Shrey Baid688b4242020-07-10 20:40:10 +05301249 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001250}
1251
Shrey Baid688b4242020-07-10 20:40:10 +05301252func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001253
Matteo Scandolocedde462021-03-09 17:37:16 -08001254 intfIDs := []uint32{}
1255 for i := 0; i < o.NumPon; i++ {
1256 intfIDs = append(intfIDs, uint32(i))
1257 }
1258
1259 devinfo := &openolt.DeviceInfo{
1260 Vendor: common.Config.Olt.Vendor,
1261 Model: common.Config.Olt.Model,
1262 HardwareVersion: common.Config.Olt.HardwareVersion,
1263 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1264 Technology: common.Config.Olt.Technology,
1265 PonPorts: uint32(o.NumPon),
1266 OnuIdStart: onuIdStart,
1267 OnuIdEnd: onuIdEnd,
1268 AllocIdStart: allocIdStart,
1269 AllocIdEnd: allocIdEnd,
1270 GemportIdStart: gemportIdStart,
1271 GemportIdEnd: gemportIdEnd,
1272 FlowIdStart: flowIdStart,
1273 FlowIdEnd: flowIdEnd,
1274 DeviceSerialNumber: o.SerialNumber,
1275 DeviceId: common.Config.Olt.DeviceId,
1276 PreviouslyConnected: o.PreviouslyConnected,
1277 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1278 {
1279 IntfIds: intfIDs,
1280 Technology: common.Config.Olt.Technology,
1281 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1282 {
1283 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1284 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1285 Start: onuIdStart,
1286 End: onuIdEnd,
1287 },
1288 {
1289 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1290 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1291 Start: allocIdStart,
1292 End: allocIdEnd,
1293 },
1294 {
1295 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1296 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1297 Start: gemportIdStart,
1298 End: gemportIdEnd,
1299 },
1300 {
1301 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1302 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1303 Start: flowIdStart,
1304 End: flowIdEnd,
1305 },
1306 },
1307 },
1308 },
1309 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001310
1311 oltLogger.WithFields(log.Fields{
1312 "Vendor": devinfo.Vendor,
1313 "Model": devinfo.Model,
1314 "HardwareVersion": devinfo.HardwareVersion,
1315 "FirmwareVersion": devinfo.FirmwareVersion,
1316 "Technology": devinfo.Technology,
1317 "PonPorts": devinfo.PonPorts,
1318 "OnuIdStart": devinfo.OnuIdStart,
1319 "OnuIdEnd": devinfo.OnuIdEnd,
1320 "AllocIdStart": devinfo.AllocIdStart,
1321 "AllocIdEnd": devinfo.AllocIdEnd,
1322 "GemportIdStart": devinfo.GemportIdStart,
1323 "GemportIdEnd": devinfo.GemportIdEnd,
1324 "FlowIdStart": devinfo.FlowIdStart,
1325 "FlowIdEnd": devinfo.FlowIdEnd,
1326 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1327 "DeviceId": devinfo.DeviceId,
1328 "PreviouslyConnected": devinfo.PreviouslyConnected,
1329 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1330
1331 // once we connect, set the flag
1332 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001333
1334 return devinfo, nil
1335}
1336
Shrey Baid688b4242020-07-10 20:40:10 +05301337func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001338 pon, err := o.GetPonById(omci_msg.IntfId)
1339 if err != nil {
1340 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001341 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001342 "onu_id": omci_msg.OnuId,
1343 "pon_id": omci_msg.IntfId,
1344 }).Error("pon ID not found")
1345 return nil, err
1346 }
1347
1348 onu, err := pon.GetOnuById(omci_msg.OnuId)
1349 if err != nil {
1350 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001351 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001352 "onu_id": omci_msg.OnuId,
1353 "pon_id": omci_msg.IntfId,
1354 }).Error("onu ID not found")
1355 return nil, err
1356 }
1357
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001358 oltLogger.WithFields(log.Fields{
1359 "IntfId": onu.PonPortID,
1360 "OnuId": onu.ID,
1361 "OnuSn": onu.Sn(),
1362 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001363 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1364 if err != nil {
1365 log.WithFields(log.Fields{
1366 "IntfId": onu.PonPortID,
1367 "SerialNumber": onu.Sn(),
1368 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1369 "err": err.Error(),
1370 }).Error("cannot-parse-OMCI-packet")
1371 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001372 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001373 if onu.InternalState.Current() == OnuStateDisabled {
1374 // if the ONU is disabled just drop the message
1375 log.WithFields(log.Fields{
1376 "IntfId": onu.PonPortID,
1377 "SerialNumber": onu.Sn(),
1378 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1379 "omciPkt": omciPkt,
1380 "omciMsgType": omciMsg.MessageType,
1381 }).Warn("dropping-omci-message")
1382 } else {
1383 msg := types.Message{
1384 Type: types.OMCI,
1385 Data: types.OmciMessage{
1386 OnuSN: onu.SerialNumber,
1387 OnuID: onu.ID,
1388 OmciMsg: omciMsg,
1389 OmciPkt: omciPkt,
1390 },
1391 }
1392 onu.Channel <- msg
1393 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001394 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001395}
1396
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,
1451 Packet: rawpkt,
1452 Type: pktType,
1453 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001454 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001455 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001456
Matteo Scandolo075b1892019-10-07 12:11:07 -07001457 onu.Channel <- msg
1458
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001459 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001460}
1461
Shrey Baid688b4242020-07-10 20:40:10 +05301462func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001463
1464 // OLT Reboot is called in two cases:
1465 // - 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)
1466 // - when an OLT needs to be rebooted (voltcl device reboot)
1467
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001468 oltLogger.WithFields(log.Fields{
1469 "oltId": o.ID,
1470 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301471 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301472 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001473 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001474}
1475
Shrey Baid688b4242020-07-10 20:40:10 +05301476func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301477 oltLogger.WithFields(log.Fields{
1478 "oltId": o.ID,
1479 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301480 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301481
Pragya Arya2225f202020-01-29 18:05:01 +05301482 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001483 oltMsg := types.Message{
1484 Type: types.OltIndication,
1485 Data: types.OltIndicationMessage{
1486 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301487 },
Pragya Arya1881df02020-01-29 18:05:01 +05301488 }
Pragya Arya2225f202020-01-29 18:05:01 +05301489 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301490
Pragya Arya2225f202020-01-29 18:05:01 +05301491 for _, pon := range o.Pons {
1492 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001493 msg := types.Message{
1494 Type: types.PonIndication,
1495 Data: types.PonIndicationMessage{
1496 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301497 PonPortID: pon.ID,
1498 },
1499 }
1500 o.channel <- msg
1501 }
1502 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001503
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001504 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001505}
1506
Shrey Baid688b4242020-07-10 20:40:10 +05301507func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001508 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1509
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001510 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1511
1512 if err != nil {
1513 return nil, err
1514 }
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) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001519 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001520 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001521}
1522
Shrey Baid688b4242020-07-10 20:40:10 +05301523func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001524 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001525 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001526}
1527
Shrey Baid688b4242020-07-10 20:40:10 +05301528func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001529 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001530 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001531}
1532
Shrey Baid688b4242020-07-10 20:40:10 +05301533func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001534 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001535 return new(openolt.Empty), nil
1536}
1537
Shrey Baid688b4242020-07-10 20:40:10 +05301538func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001539 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001540 return new(openolt.Empty), nil
1541}
1542
Shrey Baid688b4242020-07-10 20:40:10 +05301543func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301544 oltLogger.WithFields(log.Fields{
1545 "OnuId": trafficSchedulers.OnuId,
1546 "IntfId": trafficSchedulers.IntfId,
1547 "OnuPortNo": trafficSchedulers.PortNo,
1548 }).Info("received CreateTrafficSchedulers")
1549
1550 if !s.enablePerf {
1551 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1552 if err != nil {
1553 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1554 return new(openolt.Empty), err
1555 }
1556 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1557 if err != nil {
1558 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1559 return new(openolt.Empty), err
1560 }
1561 onu.TrafficSchedulers = trafficSchedulers
1562 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001563 return new(openolt.Empty), nil
1564}
1565
Shrey Baid688b4242020-07-10 20:40:10 +05301566func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301567 oltLogger.WithFields(log.Fields{
1568 "OnuId": trafficSchedulers.OnuId,
1569 "IntfId": trafficSchedulers.IntfId,
1570 "OnuPortNo": trafficSchedulers.PortNo,
1571 }).Info("received RemoveTrafficSchedulers")
1572 if !s.enablePerf {
1573 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1574 if err != nil {
1575 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1576 return new(openolt.Empty), err
1577 }
1578 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1579 if err != nil {
1580 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1581 return new(openolt.Empty), err
1582 }
1583
1584 onu.TrafficSchedulers = nil
1585 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001586 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001587}
Scott Baker41724b82020-01-21 19:54:53 -08001588
Matteo Scandolo618a6582020-09-09 12:21:29 -07001589func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1590 oltLogger.WithFields(log.Fields{
1591 "GroupId": group.GroupId,
1592 "Command": group.Command,
1593 "Members": group.Members,
1594 "Action": group.Action,
1595 }).Debug("received PerformGroupOperation")
1596 return &openolt.Empty{}, nil
1597}
1598
1599func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1600 oltLogger.WithFields(log.Fields{
1601 "GroupId": group.GroupId,
1602 "Command": group.Command,
1603 "Members": group.Members,
1604 "Action": group.Action,
1605 }).Debug("received PerformGroupOperation")
1606 return &openolt.Empty{}, nil
1607}
1608
1609func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1610 return &common_protos.ReturnValues{}, nil
1611}
1612
1613func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1614 return &openolt.Empty{}, nil
1615}
1616
1617func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1618 return &openolt.OnuLogicalDistance{}, nil
1619}
1620
1621func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1622 return &openolt.OnuLogicalDistance{}, nil
1623}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001624
1625func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1626 return &openolt.GemPortStatistics{}, nil
1627}
1628
1629func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1630 return &openolt.OnuStatistics{}, nil
1631}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001632
1633func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1634 o.AllocIDsLock.Lock()
1635 defer o.AllocIDsLock.Unlock()
1636
Matteo Scandolo21195d62021-04-07 14:31:23 -07001637 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1638 oltLogger.WithFields(log.Fields{
1639 "IntfId": flow.AccessIntfId,
1640 "OnuId": flow.OnuId,
1641 "PortNo": flow.PortNo,
1642 "GemportId": flow.GemportId,
1643 "FlowId": flow.FlowId,
1644 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1645 }
1646
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001647 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001648 "IntfId": flow.AccessIntfId,
1649 "OnuId": flow.OnuId,
1650 "PortNo": flow.PortNo,
1651 "GemportId": flow.GemportId,
1652 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001653 }).Trace("storing-alloc-id-via-flow")
1654
1655 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1656 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1657 }
1658 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1659 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1660 }
1661 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1662}
1663
1664func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1665 // if this is the last flow referencing the AllocId then remove it
1666 o.AllocIDsLock.Lock()
1667 defer o.AllocIDsLock.Unlock()
1668
1669 oltLogger.WithFields(log.Fields{
1670 "IntfId": flow.AccessIntfId,
1671 "OnuId": flow.OnuId,
1672 "PortNo": flow.PortNo,
1673 "GemportId": flow.GemportId,
1674 }).Trace("freeing-alloc-id-via-flow")
1675
1676 // NOTE look at the freeGemPortId implementation for comments and context
1677 for ponId, ponValues := range o.AllocIDs {
1678 for onuId, onuValues := range ponValues {
1679 for uniId, uniValues := range onuValues {
1680 for allocId, flows := range uniValues {
1681 for flowId := range flows {
1682 // if the flow matches, remove it from the map.
1683 if flow.FlowId == flowId {
1684 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1685 }
1686 // if that was the last flow for a particular allocId, remove the entire allocId
1687 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1688 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1689 }
1690 }
1691 }
1692 }
1693 }
1694 }
1695}
1696
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001697func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001698 o.GemPortIDsLock.Lock()
1699 defer o.GemPortIDsLock.Unlock()
1700
1701 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1702 oltLogger.WithFields(log.Fields{
1703 "IntfId": ponId,
1704 "OnuId": onuId,
1705 "PortNo": portNo,
1706 "GemportId": gemId,
1707 "FlowId": flowId,
1708 }).Error("trying-to-store-gemport-for-unknown-onu")
1709 }
1710
1711 oltLogger.WithFields(log.Fields{
1712 "IntfId": ponId,
1713 "OnuId": onuId,
1714 "PortNo": portNo,
1715 "GemportId": gemId,
1716 "FlowId": flowId,
1717 }).Trace("storing-alloc-id-via-flow")
1718
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001719 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1720 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1721 }
1722 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1723 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1724 }
1725 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1726}
1727
1728func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001729 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001730 "IntfId": flow.AccessIntfId,
1731 "OnuId": flow.OnuId,
1732 "PortNo": flow.PortNo,
1733 "GemportId": flow.GemportId,
1734 "FlowId": flow.FlowId,
1735 "ReplicateFlow": flow.ReplicateFlow,
1736 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001737 }).Trace("storing-gem-port-id-via-flow")
1738
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001739 if flow.ReplicateFlow {
1740 for _, gem := range flow.PbitToGemport {
1741 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1742 }
1743 } else {
1744 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001745 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001746}
1747
1748func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1749 // if this is the last flow referencing the GemPort then remove it
1750 o.GemPortIDsLock.Lock()
1751 defer o.GemPortIDsLock.Unlock()
1752
1753 oltLogger.WithFields(log.Fields{
1754 "IntfId": flow.AccessIntfId,
1755 "OnuId": flow.OnuId,
1756 "PortNo": flow.PortNo,
1757 "GemportId": flow.GemportId,
1758 }).Trace("freeing-gem-port-id-via-flow")
1759
1760 // NOTE that this loop is not very performant, it would be better if the flow carries
1761 // the same information that it carries during a FlowAdd. If so we can directly remove
1762 // items from the map
1763
1764 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1765 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1766 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1767 //}
1768
1769 // NOTE this loop assumes that flow IDs are unique per device
1770 for ponId, ponValues := range o.GemPortIDs {
1771 for onuId, onuValues := range ponValues {
1772 for uniId, uniValues := range onuValues {
1773 for gemId, flows := range uniValues {
1774 for flowId := range flows {
1775 // if the flow matches, remove it from the map.
1776 if flow.FlowId == flowId {
1777 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1778 }
1779 // if that was the last flow for a particular gem, remove the entire gem
1780 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1781 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1782 }
1783 }
1784 }
1785 }
1786 }
1787 }
1788}
1789
1790// validateFlow checks that:
1791// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1792// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1793func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001794 // validate gemPort
1795 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001796 defer o.GemPortIDsLock.RUnlock()
1797 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001798 if onuId == uint32(flow.OnuId) {
1799 continue
1800 }
1801 for uniId, uni := range onu {
1802 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001803 if flow.ReplicateFlow {
1804 for _, flowGem := range flow.PbitToGemport {
1805 if gem == int32(flowGem) {
1806 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1807 }
1808 }
1809 } else {
1810 if gem == flow.GemportId {
1811 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1812 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001813 }
1814 }
1815 }
1816 }
1817
1818 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001819 defer o.AllocIDsLock.RUnlock()
1820 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001821 if onuId == uint32(flow.OnuId) {
1822 continue
1823 }
1824 for uniId, uni := range onu {
1825 for allocId := range uni {
1826 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001827 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 -08001828 }
1829 }
1830 }
1831 }
1832
1833 return nil
1834}
1835
1836// clearAllResources is invoked up OLT Reboot to remove all the allocated
1837// GemPorts, AllocId and ONU-IDs across the PONs
1838func (o *OltDevice) clearAllResources() {
1839
1840 // remove the resources received via flows
1841 o.GemPortIDsLock.Lock()
1842 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1843 o.GemPortIDsLock.Unlock()
1844 o.AllocIDsLock.Lock()
1845 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1846 o.AllocIDsLock.Unlock()
1847
1848 // remove the resources received via OMCI
1849 for _, pon := range o.Pons {
1850 pon.removeAllAllocIds()
1851 pon.removeAllGemPorts()
1852 pon.removeAllOnuIds()
1853 }
1854}