blob: 35b6da05af25a9ff24ac9aa1d4ae6a19cad7a7fc [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
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000028 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
29 "github.com/opencord/bbsim/internal/bbsim/types"
30 omcilib "github.com/opencord/bbsim/internal/common/omci"
31 "github.com/opencord/voltha-protos/v4/go/ext/config"
32
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070033 "github.com/google/gopacket"
34 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070035 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070036 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010037 "github.com/opencord/bbsim/internal/common"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070038 common_protos "github.com/opencord/voltha-protos/v4/go/common"
39 "github.com/opencord/voltha-protos/v4/go/openolt"
40 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070041 log "github.com/sirupsen/logrus"
42 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053043 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010044 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053045 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070046)
47
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070048var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070049 "module": "OLT",
50})
51
Matteo Scandolocedde462021-03-09 17:37:16 -080052const (
53 onuIdStart = 1
54 onuIdEnd = 127
55 allocIdStart = 1024
56 allocIdEnd = 16383
57 gemportIdStart = 1024
58 gemportIdEnd = 65535
59 flowIdStart = 1
60 flowIdEnd = 65535
61)
62
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070063type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000064 sync.Mutex
Hardik Windlassefdb4b62021-03-18 10:33:24 +000065 OltServer *grpc.Server
David Bainbridge103cf022019-12-16 20:11:35 +000066
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070067 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053068 ID int
69 SerialNumber string
70 NumNni int
71 NumPon int
72 NumOnuPerPon int
Mahir Gunyela1753ae2021-06-23 00:24:56 -070073 NumUni int
Pragya Arya2225f202020-01-29 18:05:01 +053074 InternalState *fsm.FSM
Matteo Scandolof9d43412021-01-12 11:11:34 -080075 channel chan types.Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070076 dhcpServer dhcp.DHCPServerIf
Andrea Campanellabe8e12f2020-12-14 18:43:41 +010077 Flows sync.Map
Pragya Arya2225f202020-01-29 18:05:01 +053078 Delay int
79 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053080 EventChannel chan common.Event
81 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053082 PortStatsInterval int
Matteo Scandolo96f89192021-03-12 13:17:26 -080083 PreviouslyConnected bool
Matteo Scandoloe33447a2019-10-31 12:38:23 -070084
Matteo Scandolo27428702019-10-11 16:21:16 -070085 Pons []*PonPort
86 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070087
88 // OLT Attributes
89 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000090
91 enableContext context.Context
92 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053093
Matteo Scandolo4a036262020-08-17 15:56:13 -070094 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053095 enablePerf bool
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080096
97 // Allocated Resources
98 // this data are to verify that the openolt adapter does not duplicate resources
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000099 AllocIDsLock sync.RWMutex
100 AllocIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[AllocIds]map[FlowId]bool
101 GemPortIDsLock sync.RWMutex
102 GemPortIDs map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool // map[ponPortId]map[OnuId]map[PortNo]map[GemPortIDs]map[FlowId]bool
103 OmciResponseRate uint8
Matteo Scandolo4747d292019-08-05 11:50:18 -0700104}
105
Matteo Scandolo27428702019-10-11 16:21:16 -0700106var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700107
Matteo Scandolo27428702019-10-11 16:21:16 -0700108func GetOLT() *OltDevice {
109 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700110}
111
Matteo Scandolo4a036262020-08-17 15:56:13 -0700112func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700113 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +0530114 "ID": options.Olt.ID,
115 "NumNni": options.Olt.NniPorts,
116 "NumPon": options.Olt.PonPorts,
117 "NumOnuPerPon": options.Olt.OnusPonPort,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700118 "NumUni": options.Olt.UniPorts,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700119 }).Debug("CreateOLT")
120
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700121 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +0530122 ID: options.Olt.ID,
123 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700124 OperState: getOperStateFSM(func(e *fsm.Event) {
125 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
126 }),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800127 NumNni: int(options.Olt.NniPorts),
128 NumPon: int(options.Olt.PonPorts),
129 NumOnuPerPon: int(options.Olt.OnusPonPort),
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700130 NumUni: int(options.Olt.UniPorts),
Matteo Scandolo96f89192021-03-12 13:17:26 -0800131 Pons: []*PonPort{},
132 Nnis: []*NniPort{},
133 Delay: options.BBSim.Delay,
134 enablePerf: options.BBSim.EnablePerf,
135 PublishEvents: options.BBSim.Events,
136 PortStatsInterval: options.Olt.PortStatsInterval,
137 dhcpServer: dhcp.NewDHCPServer(),
138 PreviouslyConnected: false,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800139 AllocIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
140 GemPortIDs: make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool),
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000141 OmciResponseRate: options.Olt.OmciResponseRate,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700142 }
143
Pragya Arya996a0892020-03-09 21:47:52 +0530144 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530145 olt.ControlledActivation = val
146 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700147 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530148 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
149 olt.ControlledActivation = Default
150 }
151
Matteo Scandolo4747d292019-08-05 11:50:18 -0700152 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700153 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700154 olt.InternalState = fsm.NewFSM(
155 "created",
156 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800157 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100158 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700160 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800161 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700162 },
163 fsm.Callbacks{
164 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700165 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100167 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800168 "enter_deleted": func(e *fsm.Event) {
169 // remove all the resource allocations
170 olt.clearAllResources()
171 },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700172 },
173 )
174
Shrey Baid688b4242020-07-10 20:40:10 +0530175 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700176 // create NNI Port
177 nniPort, err := CreateNNI(&olt)
178 if err != nil {
179 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
180 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700181
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700182 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700183 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700184
Matteo Scandolo4a036262020-08-17 15:56:13 -0700185 // Create device and Services
Matteo Scandolo4a036262020-08-17 15:56:13 -0700186 nextCtag := map[string]int{}
187 nextStag := map[string]int{}
188
Matteo Scandolo4747d292019-08-05 11:50:18 -0700189 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700190 for i := 0; i < olt.NumPon; i++ {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800191
192 // initialize the resource maps for every PON Ports
193 olt.AllocIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
194 olt.GemPortIDs[uint32(i)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
195
Matteo Scandolo4a036262020-08-17 15:56:13 -0700196 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700197
Matteo Scandolo4a036262020-08-17 15:56:13 -0700198 // create ONU devices
199 for j := 0; j < olt.NumOnuPerPon; j++ {
200 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandolo8a574812021-05-20 15:18:53 -0700201 o := CreateONU(&olt, p, uint32(j+1), delay, nextCtag, nextStag, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700202
Matteo Scandolo4a036262020-08-17 15:56:13 -0700203 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700204 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700205 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700206 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100207
Shrey Baid688b4242020-07-10 20:40:10 +0530208 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700209 if err := olt.InternalState.Event("initialize"); err != nil {
210 log.Errorf("Error initializing OLT: %v", err)
211 return nil
212 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100213 }
214
Pragya Arya324337e2020-02-20 14:35:08 +0530215 if olt.PublishEvents {
216 log.Debugf("BBSim event publishing is enabled")
217 // Create a channel to write event messages
218 olt.EventChannel = make(chan common.Event, 100)
219 }
220
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700221 return &olt
222}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700223
Shrey Baid688b4242020-07-10 20:40:10 +0530224func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000226 if o.OltServer == nil {
227 o.OltServer, _ = o.StartOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100228 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800229 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100230 }
231
232 // create new channel for processOltMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800233 o.channel = make(chan types.Message)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100234
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100235 // FIXME we are assuming we have only one NNI
236 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800237 // NOTE we want to make sure the state is down when we initialize the OLT,
238 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
239 // in-band management
240 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100241 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800242
243 for ponId := range o.Pons {
244 // initialize the resource maps for every PON Ports
245 olt.AllocIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
246 olt.GemPortIDs[uint32(ponId)] = make(map[uint32]map[uint32]map[int32]map[uint64]bool)
247 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700248}
249
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800250func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100251
Matteo Scandolo96f89192021-03-12 13:17:26 -0800252 o.PreviouslyConnected = false
253
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700254 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700255 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800256
257 oltLogger.WithFields(log.Fields{
258 "oltId": o.ID,
259 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
260
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700261 if o.InternalState.Is("enabled") {
262 oltLogger.WithFields(log.Fields{
263 "oltId": o.ID,
264 }).Info("This is an OLT soft reboot")
265 softReboot = true
266 }
267
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800268 // transition internal state to deleted
269 if err := o.InternalState.Event("delete"); err != nil {
270 oltLogger.WithFields(log.Fields{
271 "oltId": o.ID,
272 }).Errorf("Error deleting OLT: %v", err)
273 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274 }
275
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700276 if softReboot {
277 for _, pon := range o.Pons {
278 if pon.InternalState.Current() == "enabled" {
279 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800280 msg := types.Message{
281 Type: types.PonIndication,
282 Data: types.PonIndicationMessage{
283 OperState: types.DOWN,
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700284 PonPortID: pon.ID,
285 },
286 }
287 o.channel <- msg
288 }
289
290 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800291 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700292 }
293 }
294 } else {
295 // PONs are already handled in the Disable call
296 for _, pon := range olt.Pons {
297 // ONUs are not automatically disabled when a PON goes down
298 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
299 for _, onu := range pon.Onus {
Matteo Scandolocedde462021-03-09 17:37:16 -0800300 _ = onu.InternalState.Event(OnuTxDisable)
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700301 }
Pragya Arya2225f202020-01-29 18:05:01 +0530302 }
303 }
304
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700305 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
306 o.StopOltServer()
307
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100308 // terminate the OLT's processOltMessages go routine
309 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700310
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700311 o.enableContextCancel()
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100312 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100313
314 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800315 oltLogger.WithFields(log.Fields{
316 "oltId": o.ID,
317 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100318 return err
319 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800320 oltLogger.WithFields(log.Fields{
321 "oltId": o.ID,
322 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100323 return nil
324}
325
326// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800327func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700328 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700329 lis, err := net.Listen("tcp", address)
330 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700331 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332 }
333 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100334
Matteo Scandolo4747d292019-08-05 11:50:18 -0700335 openolt.RegisterOpenoltServer(grpcServer, o)
336
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100337 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700338
Shrey Baid688b4242020-07-10 20:40:10 +0530339 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100340 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700341
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100342 return grpcServer, nil
343}
344
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800345// StartOltServer will create the grpc server that VOLTHA uses
346// to communicate with the device
347func (o *OltDevice) StartOltServer() (*grpc.Server, error) {
348 oltServer, err := o.newOltServer()
349 if err != nil {
350 oltLogger.WithFields(log.Fields{
351 "err": err,
352 }).Error("Cannot OLT gRPC server")
353 return nil, err
354 }
355 return oltServer, nil
356}
357
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100358// StopOltServer stops the OpenOLT grpc server
Matteo Scandolo88c204a2020-11-03 10:34:24 -0800359func (o *OltDevice) StopOltServer() {
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000360 if o.OltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800361 oltLogger.WithFields(log.Fields{
362 "oltId": o.SerialNumber,
363 }).Warnf("Stopping OLT gRPC server")
Hardik Windlassefdb4b62021-03-18 10:33:24 +0000364 o.OltServer.Stop()
365 o.OltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700366 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700367}
368
369// Device Methods
370
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100371// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530372func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700373 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530374 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700375
David Bainbridge103cf022019-12-16 20:11:35 +0000376 // If enabled has already been called then an enabled context has
377 // been created. If this is the case then we want to cancel all the
378 // proessing loops associated with that enable before we recreate
379 // new ones
380 o.Lock()
381 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700382 oltLogger.Info("This is an OLT reboot or a reconcile")
David Bainbridge103cf022019-12-16 20:11:35 +0000383 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530384 rebootFlag = true
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700385 time.Sleep(1 * time.Second)
David Bainbridge103cf022019-12-16 20:11:35 +0000386 }
387 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
388 o.Unlock()
389
Matteo Scandolo4747d292019-08-05 11:50:18 -0700390 wg := sync.WaitGroup{}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700391
Matteo Scandolo4a036262020-08-17 15:56:13 -0700392 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530393
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100394 // create Go routine to process all OLT events
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700395 wg.Add(1)
David Bainbridge103cf022019-12-16 20:11:35 +0000396 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700397
398 // enable the OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800399 oltMsg := types.Message{
400 Type: types.OltIndication,
401 Data: types.OltIndicationMessage{
402 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700403 },
404 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100405 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700406
407 // send NNI Port Indications
408 for _, nni := range o.Nnis {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800409 msg := types.Message{
410 Type: types.NniIndication,
411 Data: types.NniIndicationMessage{
412 OperState: types.UP,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700413 NniPortID: nni.ID,
414 },
415 }
416 o.channel <- msg
417 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100418
Shrey Baid688b4242020-07-10 20:40:10 +0530419 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530420 for _, pon := range o.Pons {
421 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800422 msg := types.Message{
423 Type: types.PonIndication,
424 Data: types.PonIndicationMessage{
425 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530426 PonPortID: pon.ID,
427 },
428 }
429 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000430 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700431 // when the enableContext was canceled the ONUs stopped listening on the channel
432 for _, onu := range pon.Onus {
433 go onu.ProcessOnuMessages(o.enableContext, stream, nil)
434
435 // update the stream on all the services
Matteo Scandolo8a574812021-05-20 15:18:53 -0700436 for _, uni := range onu.UniPorts {
437 uni.UpdateStream(stream)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700438 }
439 }
Pragya Arya2225f202020-01-29 18:05:01 +0530440 }
441 } else {
442
443 // 1. controlledActivation == Default: Send both PON and ONUs indications
444 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
445
446 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
447 // send PON Port indications
448 for _, pon := range o.Pons {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800449 msg := types.Message{
450 Type: types.PonIndication,
451 Data: types.PonIndicationMessage{
452 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530453 PonPortID: pon.ID,
454 },
455 }
456 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700457 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700458 }
459 }
460
Pragya Arya996a0892020-03-09 21:47:52 +0530461 if !o.enablePerf {
462 // Start a go routine to send periodic port stats to openolt adapter
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700463 wg.Add(1)
464 go o.periodicPortStats(o.enableContext, &wg, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530465 }
466
Matteo Scandolo4747d292019-08-05 11:50:18 -0700467 wg.Wait()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700468 oltLogger.WithFields(log.Fields{
469 "stream": stream,
470 }).Debug("OpenOLT Stream closed")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700471}
472
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700473func (o *OltDevice) periodicPortStats(ctx context.Context, wg *sync.WaitGroup, stream openolt.Openolt_EnableIndicationServer) {
Pragya Arya996a0892020-03-09 21:47:52 +0530474 var portStats *openolt.PortStatistics
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700475
476loop:
Pragya Arya996a0892020-03-09 21:47:52 +0530477 for {
478 select {
479 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
480 // send NNI port stats
481 for _, port := range o.Nnis {
482 incrementStat := true
483 if port.OperState.Current() == "down" {
484 incrementStat = false
485 }
486 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700487 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530488 }
489
490 // send PON port stats
491 for _, port := range o.Pons {
492 incrementStat := true
493 // do not increment port stats if PON port is down or no ONU is activated on PON port
494 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
495 incrementStat = false
496 }
497 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700498 o.sendPortStatsIndication(portStats, port.ID, port.Type, stream)
Pragya Arya996a0892020-03-09 21:47:52 +0530499 }
500 case <-ctx.Done():
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700501 oltLogger.Debug("Stop sending port stats")
502 break loop
Pragya Arya996a0892020-03-09 21:47:52 +0530503 }
Pragya Arya996a0892020-03-09 21:47:52 +0530504 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700505 wg.Done()
Pragya Arya996a0892020-03-09 21:47:52 +0530506}
507
Matteo Scandolo4747d292019-08-05 11:50:18 -0700508// Helpers method
509
Matteo Scandolof9d43412021-01-12 11:11:34 -0800510func (o *OltDevice) SetAlarm(interfaceId uint32, interfaceType string, alarmStatus string) error {
511
512 switch interfaceType {
513 case "nni":
514 if !o.HasNni(interfaceId) {
515 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" NNI not present in olt")
516 }
517
518 case "pon":
519 if !o.HasPon(interfaceId) {
520 return status.Errorf(codes.NotFound, strconv.Itoa(int(interfaceId))+" PON not present in olt")
521 }
522 }
523
524 alarmIndication := &openolt.AlarmIndication{
525 Data: &openolt.AlarmIndication_LosInd{LosInd: &openolt.LosIndication{
526 Status: alarmStatus,
527 IntfId: InterfaceIDToPortNo(interfaceId, interfaceType),
528 }},
529 }
530
531 msg := types.Message{
532 Type: types.AlarmIndication,
533 Data: alarmIndication,
534 }
535
536 o.channel <- msg
537
538 return nil
539}
540
541func (o *OltDevice) HasNni(id uint32) bool {
542 for _, intf := range o.Nnis {
543 if intf.ID == id {
544 return true
545 }
546 }
547 return false
548}
549
550func (o *OltDevice) HasPon(id uint32) bool {
551 for _, intf := range o.Pons {
552 if intf.ID == id {
553 return true
554 }
555 }
556 return false
557}
558
Shrey Baid688b4242020-07-10 20:40:10 +0530559func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560 for _, pon := range o.Pons {
561 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700562 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700563 }
564 }
Shrey Baid688b4242020-07-10 20:40:10 +0530565 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700566}
567
Shrey Baid688b4242020-07-10 20:40:10 +0530568func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700569 for _, nni := range o.Nnis {
570 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700571 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572 }
573 }
Shrey Baid688b4242020-07-10 20:40:10 +0530574 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700575}
576
Scott Baker41724b82020-01-21 19:54:53 -0800577func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
578 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
579 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
580 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
581 return
582 }
583
584 oltLogger.WithFields(log.Fields{
585 "AlarmIndication": alarmInd,
586 }).Debug("Sent Indication_AlarmInd")
587}
588
Matteo Scandolof9d43412021-01-12 11:11:34 -0800589func (o *OltDevice) sendOltIndication(msg types.OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
591 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700592 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800593 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700594 }
595
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700596 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597 "OperState": msg.OperState,
598 }).Debug("Sent Indication_OltInd")
599}
600
Matteo Scandolof9d43412021-01-12 11:11:34 -0800601func (o *OltDevice) sendNniIndication(msg types.NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700602 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800603 if msg.OperState == types.UP {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800604 if err := nni.OperState.Event("enable"); err != nil {
605 log.WithFields(log.Fields{
606 "Type": nni.Type,
607 "IntfId": nni.ID,
608 "OperState": nni.OperState.Current(),
609 }).Errorf("Can't move NNI Port to enabled state: %v", err)
610 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800611 } else if msg.OperState == types.DOWN {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800612 if err := nni.OperState.Event("disable"); err != nil {
613 log.WithFields(log.Fields{
614 "Type": nni.Type,
615 "IntfId": nni.ID,
616 "OperState": nni.OperState.Current(),
617 }).Errorf("Can't move NNI Port to disable state: %v", err)
618 }
619 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700620 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700621 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700622 Type: nni.Type,
623 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700624 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700625 }}
626
627 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700628 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800629 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700630 }
631
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700632 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700633 "Type": nni.Type,
634 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700635 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636 }).Debug("Sent Indication_IntfOperInd for NNI")
637}
638
Pragya Arya2225f202020-01-29 18:05:01 +0530639func (o *OltDevice) sendPonIndication(ponPortID uint32) {
640
Matteo Scandolo4a036262020-08-17 15:56:13 -0700641 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530642 pon, _ := o.GetPonById(ponPortID)
643 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700644 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700645 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700646 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700647 }}
648
649 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700650 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800651 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700652 }
653
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700654 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700655 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700656 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700657 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700658
Pragya Arya2225f202020-01-29 18:05:01 +0530659 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700660 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700661 Type: pon.Type,
662 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: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700667 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %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 "Type": pon.Type,
673 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700674 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700675 }).Debug("Sent Indication_IntfOperInd for PON")
676}
677
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700678func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string, stream openolt.Openolt_EnableIndicationServer) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530679 if o.InternalState.Current() == "enabled" {
680 oltLogger.WithFields(log.Fields{
681 "Type": portType,
682 "IntfId": portID,
683 }).Trace("Sending port stats")
684 stats.IntfId = InterfaceIDToPortNo(portID, portType)
685 data := &openolt.Indication_PortStats{
686 PortStats: stats,
687 }
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700688
Shrey Baid55f328c2020-07-07 19:20:42 +0530689 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
690 oltLogger.Errorf("Failed to send PortStats: %v", err)
691 return
692 }
Pragya Arya996a0892020-03-09 21:47:52 +0530693 }
694}
695
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100696// processOltMessages handles messages received over the OpenOLT interface
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700697func (o *OltDevice) processOltMessages(ctx context.Context, stream types.Stream, wg *sync.WaitGroup) {
698 oltLogger.WithFields(log.Fields{
699 "stream": stream,
700 }).Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000701 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700702
David Bainbridge103cf022019-12-16 20:11:35 +0000703loop:
704 for {
705 select {
706 case <-ctx.Done():
707 oltLogger.Debug("OLT Indication processing canceled via context")
708 break loop
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700709 // do not terminate this loop if the stream is closed,
710 // when we restart the gRPC server it will automatically reconnect and we need this loop to send indications
711 //case <-stream.Context().Done():
712 // oltLogger.Debug("OLT Indication processing canceled via stream context")
713 // break loop
David Bainbridge103cf022019-12-16 20:11:35 +0000714 case message, ok := <-ch:
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700715 if !ok {
716 if ctx.Err() != nil {
717 oltLogger.WithField("err", ctx.Err()).Error("OLT EnableContext error")
718 }
719 oltLogger.Warn("OLT Indication processing canceled via closed channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000720 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700721 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700722
David Bainbridge103cf022019-12-16 20:11:35 +0000723 oltLogger.WithFields(log.Fields{
724 "oltId": o.ID,
725 "messageType": message.Type,
726 }).Trace("Received message")
727
728 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800729 case types.OltIndication:
730 msg, _ := message.Data.(types.OltIndicationMessage)
731 if msg.OperState == types.UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530732 _ = o.InternalState.Event("enable")
733 _ = o.OperState.Event("enable")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800734 } else if msg.OperState == types.DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530735 _ = o.InternalState.Event("disable")
736 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000737 }
738 o.sendOltIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800739 case types.AlarmIndication:
Scott Baker41724b82020-01-21 19:54:53 -0800740 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
741 o.sendAlarmIndication(alarmInd, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800742 case types.NniIndication:
743 msg, _ := message.Data.(types.NniIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000744 o.sendNniIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800745 case types.PonIndication:
746 msg, _ := message.Data.(types.PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530747 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800748 if msg.OperState == types.UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530749 if err := pon.OperState.Event("enable"); err != nil {
750 oltLogger.WithFields(log.Fields{
751 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800752 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530753 }).Error("Can't Enable Oper state for PON Port")
754 }
755 if err := pon.InternalState.Event("enable"); err != nil {
756 oltLogger.WithFields(log.Fields{
757 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800758 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530759 }).Error("Can't Enable Internal state for PON Port")
760 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800761 } else if msg.OperState == types.DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530762 if err := pon.OperState.Event("disable"); err != nil {
763 oltLogger.WithFields(log.Fields{
764 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800765 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530766 }).Error("Can't Disable Oper state for PON Port")
767 }
768 if err := pon.InternalState.Event("disable"); err != nil {
769 oltLogger.WithFields(log.Fields{
770 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800771 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530772 }).Error("Can't Disable Internal state for PON Port")
773 }
Pragya Arya2225f202020-01-29 18:05:01 +0530774 }
David Bainbridge103cf022019-12-16 20:11:35 +0000775 default:
776 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
777 }
778 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700779 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100780 wg.Done()
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700781 oltLogger.WithFields(log.Fields{
782 "stream": stream,
783 }).Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700784}
785
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700786// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530787func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700788 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700789 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700790 for _, pon := range o.Pons {
791 for _, onu := range pon.Onus {
792 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700793 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700794 }
795 }
796 }
797
Shrey Baid688b4242020-07-10 20:40:10 +0530798 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700799}
800
William Kurkian9dadc5b2019-10-22 13:51:57 -0400801// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530802func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700803 // NOTE this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400804 // memoizing it will remove the bottleneck
805 for _, pon := range o.Pons {
806 if pon.ID == intfId {
807 for _, onu := range pon.Onus {
808 if onu.ID == onuId {
809 return onu, nil
810 }
811 }
812 }
813 }
Shrey Baid688b4242020-07-10 20:40:10 +0530814 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400815}
816
Matteo Scandolo4a036262020-08-17 15:56:13 -0700817// returns a Service with a given Mac Address
818func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700819 // NOTE this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700820 // memoizing it will remove the bottleneck
821 for _, pon := range o.Pons {
822 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700823 s, err := onu.findServiceByMacAddress(mac)
824 if err == nil {
825 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700826 }
827 }
828 }
829
Matteo Scandolo4a036262020-08-17 15:56:13 -0700830 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700831}
832
Matteo Scandolo4747d292019-08-05 11:50:18 -0700833// GRPC Endpoints
834
Shrey Baid688b4242020-07-10 20:40:10 +0530835func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700836
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700837 pon, _ := o.GetPonById(onu.IntfId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800838
Matteo Scandolo8a574812021-05-20 15:18:53 -0700839 // Enable the resource maps for this ONU
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800840 olt.AllocIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
841 olt.GemPortIDs[onu.IntfId][onu.OnuId] = make(map[uint32]map[int32]map[uint64]bool)
842
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700843 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700844
845 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), _onu.Sn())
846 oltLogger.WithFields(log.Fields{
847 "OnuSn": _onu.Sn(),
848 }).Info("Received ActivateOnu call from VOLTHA")
849
William Kurkian0418bc82019-11-06 12:16:24 -0500850 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700851
Matteo Scandolocedde462021-03-09 17:37:16 -0800852 if err := _onu.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700853 oltLogger.WithFields(log.Fields{
854 "IntfId": _onu.PonPortID,
855 "OnuSn": _onu.Sn(),
856 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800857 }).Infof("Failed to transition ONU to %s state: %s", OnuStateEnabled, err.Error())
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700858 }
859
860 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
861
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700862 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700863}
864
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800865func (o *OltDevice) DeactivateOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700866 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700867 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700868}
869
Shrey Baid688b4242020-07-10 20:40:10 +0530870func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530871 oltLogger.WithFields(log.Fields{
872 "IntfId": onu.IntfId,
873 "OnuId": onu.OnuId,
874 }).Info("Received DeleteOnu call from VOLTHA")
875
876 pon, err := o.GetPonById(onu.IntfId)
877 if err != nil {
878 oltLogger.WithFields(log.Fields{
879 "OnuId": onu.OnuId,
880 "IntfId": onu.IntfId,
881 "err": err,
882 }).Error("Can't find PonPort")
883 }
884 _onu, err := pon.GetOnuById(onu.OnuId)
885 if err != nil {
886 oltLogger.WithFields(log.Fields{
887 "OnuId": onu.OnuId,
888 "IntfId": onu.IntfId,
889 "err": err,
890 }).Error("Can't find Onu")
891 }
892
Matteo Scandolocedde462021-03-09 17:37:16 -0800893 if err := _onu.InternalState.Event(OnuTxDisable); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530894 oltLogger.WithFields(log.Fields{
895 "IntfId": _onu.PonPortID,
896 "OnuSn": _onu.Sn(),
897 "OnuId": _onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800898 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDisabled, err.Error())
Hardik Windlassad790cb2020-06-17 21:26:22 +0530899 }
900
Hardik Windlassad790cb2020-06-17 21:26:22 +0530901 // ONU Re-Discovery
902 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530903 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530904 }
905
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700906 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700907}
908
Shrey Baid688b4242020-07-10 20:40:10 +0530909func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700910 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800911 oltLogger.WithFields(log.Fields{
912 "oltId": o.ID,
913 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530914 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800915
Matteo Scandolo401503a2019-12-11 14:48:14 -0800916 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530917 if pon.InternalState.Current() == "enabled" {
918 // disable PONs
Matteo Scandolof9d43412021-01-12 11:11:34 -0800919 msg := types.Message{
920 Type: types.PonIndication,
921 Data: types.PonIndicationMessage{
922 OperState: types.DOWN,
Pragya Arya2225f202020-01-29 18:05:01 +0530923 PonPortID: pon.ID,
924 },
925 }
926 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800927 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800928 }
929
Matteo Scandolo401503a2019-12-11 14:48:14 -0800930 // Note that we are not disabling the NNI as the real OLT does not.
931 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800932
933 // disable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -0800934 oltMsg := types.Message{
935 Type: types.OltIndication,
936 Data: types.OltIndicationMessage{
937 OperState: types.DOWN,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700938 },
939 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100940 o.channel <- oltMsg
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -0700941
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700942 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700943}
944
Shrey Baid688b4242020-07-10 20:40:10 +0530945func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530946 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200947 ponID := intf.GetIntfId()
948 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200949
Matteo Scandolof9d43412021-01-12 11:11:34 -0800950 msg := types.Message{
951 Type: types.PonIndication,
952 Data: types.PonIndicationMessage{
953 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200954 PonPortID: ponID,
955 },
956 }
957 o.channel <- msg
958
959 for _, onu := range pon.Onus {
960
Matteo Scandolof9d43412021-01-12 11:11:34 -0800961 onuIndication := types.OnuIndicationMessage{
962 OperState: types.DOWN,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200963 PonPortID: ponID,
964 OnuID: onu.ID,
965 OnuSN: onu.SerialNumber,
966 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700967 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200968
969 }
970
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700971 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700972}
973
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100974func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700975 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530976 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700977 o.Enable(stream)
978 return nil
979}
980
Shrey Baid688b4242020-07-10 20:40:10 +0530981func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530982 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530983 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200984 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200985
Matteo Scandolof9d43412021-01-12 11:11:34 -0800986 msg := types.Message{
987 Type: types.PonIndication,
988 Data: types.PonIndicationMessage{
989 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +0530990 PonPortID: ponID,
991 },
992 }
993 o.channel <- msg
994
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200995 for _, onu := range pon.Onus {
996
Matteo Scandolof9d43412021-01-12 11:11:34 -0800997 onuIndication := types.OnuIndicationMessage{
998 OperState: types.UP,
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200999 PonPortID: ponID,
1000 OnuID: onu.ID,
1001 OnuSN: onu.SerialNumber,
1002 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001003 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001004
1005 }
1006
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001007 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001008}
1009
Shrey Baid688b4242020-07-10 20:40:10 +05301010func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001011 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001012 "IntfId": flow.AccessIntfId,
1013 "OnuId": flow.OnuId,
1014 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001015 "InnerVlan": flow.Classifier.IVid,
1016 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001017 "FlowType": flow.FlowType,
1018 "FlowId": flow.FlowId,
1019 "UniID": flow.UniId,
1020 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301021 }).Tracef("OLT receives FlowAdd")
1022
1023 flowKey := FlowKey{}
1024 if !o.enablePerf {
1025 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001026 olt.Flows.Store(flowKey, *flow)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301027 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001028
1029 if flow.AccessIntfId == -1 {
1030 oltLogger.WithFields(log.Fields{
1031 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001032 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001033 } else if flow.FlowType == "multicast" {
1034 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -07001035 "Cookie": flow.Cookie,
1036 "DstPort": flow.Classifier.DstPort,
1037 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
1038 "FlowId": flow.FlowId,
1039 "FlowType": flow.FlowType,
1040 "GemportId": flow.GemportId,
1041 "InnerVlan": flow.Classifier.IVid,
1042 "IntfId": flow.AccessIntfId,
1043 "IpProto": flow.Classifier.IpProto,
1044 "OnuId": flow.OnuId,
1045 "OuterVlan": flow.Classifier.OVid,
1046 "PortNo": flow.PortNo,
1047 "SrcPort": flow.Classifier.SrcPort,
1048 "UniID": flow.UniId,
1049 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001050 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001051 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001052 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001053 if err != nil {
1054 oltLogger.WithFields(log.Fields{
1055 "OnuId": flow.OnuId,
1056 "IntfId": flow.AccessIntfId,
1057 "err": err,
1058 }).Error("Can't find PonPort")
1059 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001060 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001061 if err != nil {
1062 oltLogger.WithFields(log.Fields{
1063 "OnuId": flow.OnuId,
1064 "IntfId": flow.AccessIntfId,
1065 "err": err,
1066 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001067 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001068 }
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001069
1070 // if the ONU is disabled reject the flow
1071 // as per VOL-4061 there is a small window during which the ONU is disabled
1072 // but the port has not been reported as down to ONOS
1073 if onu.InternalState.Is(OnuStatePonDisabled) || onu.InternalState.Is(OnuStateDisabled) {
1074 oltLogger.WithFields(log.Fields{
1075 "OnuId": flow.OnuId,
1076 "IntfId": flow.AccessIntfId,
1077 "Flow": flow,
1078 "SerialNumber": onu.Sn(),
1079 "InternalState": onu.InternalState.Current(),
1080 }).Error("rejected-flow-because-of-onu-state")
1081 return nil, fmt.Errorf("onu-%s-is-currently-%s", onu.Sn(), onu.InternalState.Current())
1082 }
1083
Pragya Arya8bdb4532020-03-02 17:08:09 +05301084 if !o.enablePerf {
1085 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301086 // Generate event on first flow for ONU
1087 if len(onu.Flows) == 1 {
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001088 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301089 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301090 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001091
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001092 // validate that the flow reference correct IDs (Alloc, Gem)
1093 if err := o.validateFlow(flow); err != nil {
1094 oltLogger.WithFields(log.Fields{
1095 "OnuId": flow.OnuId,
1096 "IntfId": flow.AccessIntfId,
1097 "Flow": flow,
1098 "SerialNumber": onu.Sn(),
1099 "err": err,
1100 }).Error("invalid-flow-for-onu")
1101 return nil, err
1102 }
1103
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001104 o.storeGemPortIdByFlow(flow)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001105 o.storeAllocId(flow)
1106
Matteo Scandolof9d43412021-01-12 11:11:34 -08001107 msg := types.Message{
1108 Type: types.FlowAdd,
1109 Data: types.OnuFlowUpdateMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001110 PonPortID: pon.ID,
1111 OnuID: onu.ID,
1112 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001113 },
1114 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001115 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001116 }
1117
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001118 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001119}
1120
Pragya Arya8bdb4532020-03-02 17:08:09 +05301121// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301122func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001123
Pragya Arya8bdb4532020-03-02 17:08:09 +05301124 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001125 "AllocId": flow.AllocId,
1126 "Cookie": flow.Cookie,
1127 "FlowId": flow.FlowId,
1128 "FlowType": flow.FlowType,
1129 "GemportId": flow.GemportId,
1130 "IntfId": flow.AccessIntfId,
1131 "OnuId": flow.OnuId,
1132 "PortNo": flow.PortNo,
1133 "UniID": flow.UniId,
1134 "ReplicateFlow": flow.ReplicateFlow,
1135 "PbitToGemport": flow.PbitToGemport,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001136 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301137
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001138 olt.freeGemPortId(flow)
1139 olt.freeAllocId(flow)
1140
Pragya Arya8bdb4532020-03-02 17:08:09 +05301141 if !o.enablePerf { // remove only if flow were stored
1142 flowKey := FlowKey{
1143 ID: flow.FlowId,
1144 Direction: flow.FlowType,
1145 }
1146
1147 // Check if flow exists
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001148 storedFlowIntf, ok := o.Flows.Load(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301149 if !ok {
1150 oltLogger.Errorf("Flow %v not found", flow)
1151 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1152 }
1153
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001154 storedFlow := storedFlowIntf.(openolt.Flow)
1155
Pragya Arya8bdb4532020-03-02 17:08:09 +05301156 // if its ONU flow remove it from ONU also
1157 if storedFlow.AccessIntfId != -1 {
Matteo Scandolocedde462021-03-09 17:37:16 -08001158 pon, err := o.GetPonById(uint32(storedFlow.AccessIntfId))
1159 if err != nil {
1160 oltLogger.WithFields(log.Fields{
1161 "OnuId": storedFlow.OnuId,
1162 "IntfId": storedFlow.AccessIntfId,
1163 "PONs": olt.Pons,
1164 "err": err,
1165 }).Error("PON-port-not-found")
1166 return new(openolt.Empty), nil
1167 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301168 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1169 if err != nil {
1170 oltLogger.WithFields(log.Fields{
1171 "OnuId": storedFlow.OnuId,
1172 "IntfId": storedFlow.AccessIntfId,
1173 "err": err,
Matteo Scandolocedde462021-03-09 17:37:16 -08001174 }).Error("ONU-not-found")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301175 return new(openolt.Empty), nil
1176 }
1177 onu.DeleteFlow(flowKey)
Matteo Scandoloba3e9cd2021-05-14 16:19:54 -07001178 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onu.Sn())
Pragya Arya8bdb4532020-03-02 17:08:09 +05301179 }
1180
1181 // delete from olt flows
Andrea Campanellabe8e12f2020-12-14 18:43:41 +01001182 o.Flows.Delete(flowKey)
Pragya Arya8bdb4532020-03-02 17:08:09 +05301183 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001184
1185 if flow.AccessIntfId == -1 {
1186 oltLogger.WithFields(log.Fields{
1187 "FlowId": flow.FlowId,
1188 }).Debug("Removing OLT flow")
1189 } else if flow.FlowType == "multicast" {
1190 oltLogger.WithFields(log.Fields{
1191 "FlowId": flow.FlowId,
1192 }).Debug("Removing OLT multicast flow")
1193 } else {
1194
1195 onu, err := o.GetOnuByFlowId(flow.FlowId)
1196 if err != nil {
1197 oltLogger.WithFields(log.Fields{
1198 "OnuId": flow.OnuId,
1199 "IntfId": flow.AccessIntfId,
1200 "err": err,
1201 }).Error("Can't find Onu")
1202 return nil, err
1203 }
1204
Matteo Scandolof9d43412021-01-12 11:11:34 -08001205 msg := types.Message{
1206 Type: types.FlowRemoved,
1207 Data: types.OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301208 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001209 },
1210 }
1211 onu.Channel <- msg
1212 }
1213
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001214 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001215}
1216
Shrey Baid688b4242020-07-10 20:40:10 +05301217func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001218 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1219 oltLogger.WithFields(log.Fields{
1220 "signature": res.HeartbeatSignature,
1221 }).Trace("HeartbeatCheck")
1222 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001223}
1224
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001225func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001226 for _, pon := range o.Pons {
1227 for _, onu := range pon.Onus {
1228 for _, fId := range onu.FlowIds {
1229 if fId == flowId {
1230 return onu, nil
1231 }
1232 }
1233 }
1234 }
Shrey Baid688b4242020-07-10 20:40:10 +05301235 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001236}
1237
Shrey Baid688b4242020-07-10 20:40:10 +05301238func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001239
Matteo Scandolocedde462021-03-09 17:37:16 -08001240 intfIDs := []uint32{}
1241 for i := 0; i < o.NumPon; i++ {
1242 intfIDs = append(intfIDs, uint32(i))
1243 }
1244
1245 devinfo := &openolt.DeviceInfo{
1246 Vendor: common.Config.Olt.Vendor,
1247 Model: common.Config.Olt.Model,
1248 HardwareVersion: common.Config.Olt.HardwareVersion,
1249 FirmwareVersion: common.Config.Olt.FirmwareVersion,
1250 Technology: common.Config.Olt.Technology,
1251 PonPorts: uint32(o.NumPon),
1252 OnuIdStart: onuIdStart,
1253 OnuIdEnd: onuIdEnd,
1254 AllocIdStart: allocIdStart,
1255 AllocIdEnd: allocIdEnd,
1256 GemportIdStart: gemportIdStart,
1257 GemportIdEnd: gemportIdEnd,
1258 FlowIdStart: flowIdStart,
1259 FlowIdEnd: flowIdEnd,
1260 DeviceSerialNumber: o.SerialNumber,
1261 DeviceId: common.Config.Olt.DeviceId,
1262 PreviouslyConnected: o.PreviouslyConnected,
1263 Ranges: []*openolt.DeviceInfo_DeviceResourceRanges{
1264 {
1265 IntfIds: intfIDs,
1266 Technology: common.Config.Olt.Technology,
1267 Pools: []*openolt.DeviceInfo_DeviceResourceRanges_Pool{
1268 {
1269 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ONU_ID,
1270 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1271 Start: onuIdStart,
1272 End: onuIdEnd,
1273 },
1274 {
1275 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_ALLOC_ID,
1276 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1277 Start: allocIdStart,
1278 End: allocIdEnd,
1279 },
1280 {
1281 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_GEMPORT_ID,
1282 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_DEDICATED_PER_INTF,
1283 Start: gemportIdStart,
1284 End: gemportIdEnd,
1285 },
1286 {
1287 Type: openolt.DeviceInfo_DeviceResourceRanges_Pool_FLOW_ID,
1288 Sharing: openolt.DeviceInfo_DeviceResourceRanges_Pool_SHARED_BY_ALL_INTF_ALL_TECH,
1289 Start: flowIdStart,
1290 End: flowIdEnd,
1291 },
1292 },
1293 },
1294 },
1295 }
Matteo Scandolo96f89192021-03-12 13:17:26 -08001296
1297 oltLogger.WithFields(log.Fields{
1298 "Vendor": devinfo.Vendor,
1299 "Model": devinfo.Model,
1300 "HardwareVersion": devinfo.HardwareVersion,
1301 "FirmwareVersion": devinfo.FirmwareVersion,
1302 "Technology": devinfo.Technology,
1303 "PonPorts": devinfo.PonPorts,
1304 "OnuIdStart": devinfo.OnuIdStart,
1305 "OnuIdEnd": devinfo.OnuIdEnd,
1306 "AllocIdStart": devinfo.AllocIdStart,
1307 "AllocIdEnd": devinfo.AllocIdEnd,
1308 "GemportIdStart": devinfo.GemportIdStart,
1309 "GemportIdEnd": devinfo.GemportIdEnd,
1310 "FlowIdStart": devinfo.FlowIdStart,
1311 "FlowIdEnd": devinfo.FlowIdEnd,
1312 "DeviceSerialNumber": devinfo.DeviceSerialNumber,
1313 "DeviceId": devinfo.DeviceId,
1314 "PreviouslyConnected": devinfo.PreviouslyConnected,
1315 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
1316
1317 // once we connect, set the flag
1318 o.PreviouslyConnected = true
Matteo Scandolo4747d292019-08-05 11:50:18 -07001319
1320 return devinfo, nil
1321}
1322
Shrey Baid688b4242020-07-10 20:40:10 +05301323func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001324 pon, err := o.GetPonById(omci_msg.IntfId)
1325 if err != nil {
1326 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001327 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001328 "onu_id": omci_msg.OnuId,
1329 "pon_id": omci_msg.IntfId,
1330 }).Error("pon ID not found")
1331 return nil, err
1332 }
1333
1334 onu, err := pon.GetOnuById(omci_msg.OnuId)
1335 if err != nil {
1336 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001337 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001338 "onu_id": omci_msg.OnuId,
1339 "pon_id": omci_msg.IntfId,
1340 }).Error("onu ID not found")
1341 return nil, err
1342 }
1343
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001344 oltLogger.WithFields(log.Fields{
1345 "IntfId": onu.PonPortID,
1346 "OnuId": onu.ID,
1347 "OnuSn": onu.Sn(),
1348 }).Tracef("Received OmciMsgOut")
Matteo Scandolob5913142021-03-19 16:10:18 -07001349 omciPkt, omciMsg, err := omcilib.ParseOpenOltOmciPacket(omci_msg.Pkt)
1350 if err != nil {
1351 log.WithFields(log.Fields{
1352 "IntfId": onu.PonPortID,
1353 "SerialNumber": onu.Sn(),
1354 "omciPacket": omcilib.HexDecode(omci_msg.Pkt),
1355 "err": err.Error(),
1356 }).Error("cannot-parse-OMCI-packet")
1357 return nil, fmt.Errorf("olt-received-malformed-omci-packet")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001358 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001359 if onu.InternalState.Current() == OnuStateDisabled {
1360 // if the ONU is disabled just drop the message
1361 log.WithFields(log.Fields{
1362 "IntfId": onu.PonPortID,
1363 "SerialNumber": onu.Sn(),
1364 "omciBytes": hex.EncodeToString(omciPkt.Data()),
1365 "omciPkt": omciPkt,
1366 "omciMsgType": omciMsg.MessageType,
1367 }).Warn("dropping-omci-message")
1368 } else {
1369 msg := types.Message{
1370 Type: types.OMCI,
1371 Data: types.OmciMessage{
1372 OnuSN: onu.SerialNumber,
1373 OnuID: onu.ID,
1374 OmciMsg: omciMsg,
1375 OmciPkt: omciPkt,
1376 },
1377 }
1378 onu.Channel <- msg
1379 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001380 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001381}
1382
Matteo Scandolo8a574812021-05-20 15:18:53 -07001383// this gRPC methods receives packets from VOLTHA and sends them to the subscriber on the ONU
Shrey Baid688b4242020-07-10 20:40:10 +05301384func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001385 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001386 if err != nil {
1387 oltLogger.WithFields(log.Fields{
1388 "OnuId": onuPkt.OnuId,
1389 "IntfId": onuPkt.IntfId,
1390 "err": err,
1391 }).Error("Can't find PonPort")
1392 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001393 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001394 if err != nil {
1395 oltLogger.WithFields(log.Fields{
1396 "OnuId": onuPkt.OnuId,
1397 "IntfId": onuPkt.IntfId,
1398 "err": err,
1399 }).Error("Can't find Onu")
1400 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001401
Matteo Scandolo075b1892019-10-07 12:11:07 -07001402 oltLogger.WithFields(log.Fields{
1403 "IntfId": onu.PonPortID,
1404 "OnuId": onu.ID,
1405 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001406 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001407 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001408
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001409 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001410
1411 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001412 if err != nil {
1413 onuLogger.WithFields(log.Fields{
1414 "IntfId": onu.PonPortID,
1415 "OnuId": onu.ID,
1416 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001417 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001418 }).Error("Can't find pktType in packet, droppint it")
1419 return new(openolt.Empty), nil
1420 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001421
Matteo Scandolo4a036262020-08-17 15:56:13 -07001422 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001423 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001424 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001425 "IntfId": onu.PonPortID,
1426 "OnuId": onu.ID,
1427 "OnuSn": onu.Sn(),
1428 "Pkt": rawpkt.Data(),
1429 }).Error("Can't find Dst MacAddress in packet, droppint it")
1430 return new(openolt.Empty), nil
1431 }
1432
Matteo Scandolof9d43412021-01-12 11:11:34 -08001433 msg := types.Message{
1434 Type: types.OnuPacketOut,
1435 Data: types.OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001436 IntfId: onuPkt.IntfId,
1437 OnuId: onuPkt.OnuId,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001438 PortNo: onuPkt.PortNo,
Matteo Scandolo4a036262020-08-17 15:56:13 -07001439 Packet: rawpkt,
1440 Type: pktType,
1441 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001442 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001443 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001444
Matteo Scandolo075b1892019-10-07 12:11:07 -07001445 onu.Channel <- msg
1446
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001447 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001448}
1449
Shrey Baid688b4242020-07-10 20:40:10 +05301450func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001451
1452 // OLT Reboot is called in two cases:
1453 // - 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)
1454 // - when an OLT needs to be rebooted (voltcl device reboot)
1455
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001456 oltLogger.WithFields(log.Fields{
1457 "oltId": o.ID,
1458 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301459 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301460 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001461 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001462}
1463
Shrey Baid688b4242020-07-10 20:40:10 +05301464func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301465 oltLogger.WithFields(log.Fields{
1466 "oltId": o.ID,
1467 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301468 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301469
Pragya Arya2225f202020-01-29 18:05:01 +05301470 // enable OLT
Matteo Scandolof9d43412021-01-12 11:11:34 -08001471 oltMsg := types.Message{
1472 Type: types.OltIndication,
1473 Data: types.OltIndicationMessage{
1474 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301475 },
Pragya Arya1881df02020-01-29 18:05:01 +05301476 }
Pragya Arya2225f202020-01-29 18:05:01 +05301477 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301478
Pragya Arya2225f202020-01-29 18:05:01 +05301479 for _, pon := range o.Pons {
1480 if pon.InternalState.Current() == "disabled" {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001481 msg := types.Message{
1482 Type: types.PonIndication,
1483 Data: types.PonIndicationMessage{
1484 OperState: types.UP,
Pragya Arya2225f202020-01-29 18:05:01 +05301485 PonPortID: pon.ID,
1486 },
1487 }
1488 o.channel <- msg
1489 }
1490 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001491
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001492 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001493}
1494
Shrey Baid688b4242020-07-10 20:40:10 +05301495func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001496 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1497
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001498 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1499
1500 if err != nil {
1501 return nil, err
1502 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001503 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001504}
1505
Shrey Baid688b4242020-07-10 20:40:10 +05301506func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001507 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001508 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001509}
1510
Shrey Baid688b4242020-07-10 20:40:10 +05301511func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001512 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001513 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001514}
1515
Shrey Baid688b4242020-07-10 20:40:10 +05301516func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001517 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001518 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001519}
1520
Shrey Baid688b4242020-07-10 20:40:10 +05301521func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001522 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001523 return new(openolt.Empty), nil
1524}
1525
Matteo Scandolo8a574812021-05-20 15:18:53 -07001526func (s *OltDevice) RemoveTrafficQueues(_ context.Context, tq *tech_profile.TrafficQueues) (*openolt.Empty, error) {
1527 oltLogger.WithFields(log.Fields{
1528 "OnuId": tq.OnuId,
1529 "IntfId": tq.IntfId,
1530 "OnuPortNo": tq.PortNo,
1531 "UniId": tq.UniId,
1532 }).Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001533 return new(openolt.Empty), nil
1534}
1535
Matteo Scandolo8a574812021-05-20 15:18:53 -07001536func (s *OltDevice) CreateTrafficSchedulers(_ context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301537 oltLogger.WithFields(log.Fields{
1538 "OnuId": trafficSchedulers.OnuId,
1539 "IntfId": trafficSchedulers.IntfId,
1540 "OnuPortNo": trafficSchedulers.PortNo,
Matteo Scandolo8a574812021-05-20 15:18:53 -07001541 "UniId": trafficSchedulers.UniId,
Anand S Katti09541352020-01-29 15:54:01 +05301542 }).Info("received CreateTrafficSchedulers")
1543
1544 if !s.enablePerf {
1545 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1546 if err != nil {
1547 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1548 return new(openolt.Empty), err
1549 }
1550 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1551 if err != nil {
1552 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1553 return new(openolt.Empty), err
1554 }
1555 onu.TrafficSchedulers = trafficSchedulers
1556 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001557 return new(openolt.Empty), nil
1558}
1559
Shrey Baid688b4242020-07-10 20:40:10 +05301560func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301561 oltLogger.WithFields(log.Fields{
1562 "OnuId": trafficSchedulers.OnuId,
1563 "IntfId": trafficSchedulers.IntfId,
1564 "OnuPortNo": trafficSchedulers.PortNo,
1565 }).Info("received RemoveTrafficSchedulers")
1566 if !s.enablePerf {
1567 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1568 if err != nil {
1569 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1570 return new(openolt.Empty), err
1571 }
1572 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1573 if err != nil {
1574 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1575 return new(openolt.Empty), err
1576 }
1577
1578 onu.TrafficSchedulers = nil
1579 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001580 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001581}
Scott Baker41724b82020-01-21 19:54:53 -08001582
Matteo Scandolo618a6582020-09-09 12:21:29 -07001583func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1584 oltLogger.WithFields(log.Fields{
1585 "GroupId": group.GroupId,
1586 "Command": group.Command,
1587 "Members": group.Members,
1588 "Action": group.Action,
1589 }).Debug("received PerformGroupOperation")
1590 return &openolt.Empty{}, nil
1591}
1592
1593func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1594 oltLogger.WithFields(log.Fields{
1595 "GroupId": group.GroupId,
1596 "Command": group.Command,
1597 "Members": group.Members,
1598 "Action": group.Action,
1599 }).Debug("received PerformGroupOperation")
1600 return &openolt.Empty{}, nil
1601}
1602
1603func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1604 return &common_protos.ReturnValues{}, nil
1605}
1606
1607func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1608 return &openolt.Empty{}, nil
1609}
1610
1611func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1612 return &openolt.OnuLogicalDistance{}, nil
1613}
1614
1615func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1616 return &openolt.OnuLogicalDistance{}, nil
1617}
Matteo Scandolo96f89192021-03-12 13:17:26 -08001618
1619func (o *OltDevice) GetGemPortStatistics(ctx context.Context, in *openolt.OnuPacket) (*openolt.GemPortStatistics, error) {
1620 return &openolt.GemPortStatistics{}, nil
1621}
1622
1623func (o *OltDevice) GetOnuStatistics(ctx context.Context, in *openolt.Onu) (*openolt.OnuStatistics, error) {
1624 return &openolt.OnuStatistics{}, nil
1625}
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001626
1627func (o *OltDevice) storeAllocId(flow *openolt.Flow) {
1628 o.AllocIDsLock.Lock()
1629 defer o.AllocIDsLock.Unlock()
1630
Matteo Scandolo21195d62021-04-07 14:31:23 -07001631 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)]; !ok {
1632 oltLogger.WithFields(log.Fields{
1633 "IntfId": flow.AccessIntfId,
1634 "OnuId": flow.OnuId,
1635 "PortNo": flow.PortNo,
1636 "GemportId": flow.GemportId,
1637 "FlowId": flow.FlowId,
1638 }).Error("trying-to-store-alloc-id-for-unknown-onu")
1639 }
1640
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001641 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001642 "IntfId": flow.AccessIntfId,
1643 "OnuId": flow.OnuId,
1644 "PortNo": flow.PortNo,
1645 "GemportId": flow.GemportId,
1646 "FlowId": flow.FlowId,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001647 }).Trace("storing-alloc-id-via-flow")
1648
1649 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo]; !ok {
1650 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo] = make(map[int32]map[uint64]bool)
1651 }
1652 if _, ok := o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId]; !ok {
1653 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId] = make(map[uint64]bool)
1654 }
1655 o.AllocIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.AllocId][flow.FlowId] = true
1656}
1657
1658func (o *OltDevice) freeAllocId(flow *openolt.Flow) {
1659 // if this is the last flow referencing the AllocId then remove it
1660 o.AllocIDsLock.Lock()
1661 defer o.AllocIDsLock.Unlock()
1662
1663 oltLogger.WithFields(log.Fields{
1664 "IntfId": flow.AccessIntfId,
1665 "OnuId": flow.OnuId,
1666 "PortNo": flow.PortNo,
1667 "GemportId": flow.GemportId,
1668 }).Trace("freeing-alloc-id-via-flow")
1669
1670 // NOTE look at the freeGemPortId implementation for comments and context
1671 for ponId, ponValues := range o.AllocIDs {
1672 for onuId, onuValues := range ponValues {
1673 for uniId, uniValues := range onuValues {
1674 for allocId, flows := range uniValues {
1675 for flowId := range flows {
1676 // if the flow matches, remove it from the map.
1677 if flow.FlowId == flowId {
1678 delete(o.AllocIDs[ponId][onuId][uniId][allocId], flow.FlowId)
1679 }
1680 // if that was the last flow for a particular allocId, remove the entire allocId
1681 if len(o.AllocIDs[ponId][onuId][uniId][allocId]) == 0 {
1682 delete(o.AllocIDs[ponId][onuId][uniId], allocId)
1683 }
1684 }
1685 }
1686 }
1687 }
1688 }
1689}
1690
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001691func (o *OltDevice) storeGemPortId(ponId uint32, onuId uint32, portNo uint32, gemId int32, flowId uint64) {
Matteo Scandolo21195d62021-04-07 14:31:23 -07001692 o.GemPortIDsLock.Lock()
1693 defer o.GemPortIDsLock.Unlock()
1694
1695 if _, ok := o.GemPortIDs[ponId][onuId]; !ok {
1696 oltLogger.WithFields(log.Fields{
1697 "IntfId": ponId,
1698 "OnuId": onuId,
1699 "PortNo": portNo,
1700 "GemportId": gemId,
1701 "FlowId": flowId,
1702 }).Error("trying-to-store-gemport-for-unknown-onu")
1703 }
1704
1705 oltLogger.WithFields(log.Fields{
1706 "IntfId": ponId,
1707 "OnuId": onuId,
1708 "PortNo": portNo,
1709 "GemportId": gemId,
1710 "FlowId": flowId,
1711 }).Trace("storing-alloc-id-via-flow")
1712
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001713 if _, ok := o.GemPortIDs[ponId][onuId][portNo]; !ok {
1714 o.GemPortIDs[ponId][onuId][portNo] = make(map[int32]map[uint64]bool)
1715 }
1716 if _, ok := o.GemPortIDs[ponId][onuId][portNo][gemId]; !ok {
1717 o.GemPortIDs[ponId][onuId][portNo][gemId] = make(map[uint64]bool)
1718 }
1719 o.GemPortIDs[ponId][onuId][portNo][gemId][flowId] = true
1720}
1721
1722func (o *OltDevice) storeGemPortIdByFlow(flow *openolt.Flow) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001723 oltLogger.WithFields(log.Fields{
Matteo Scandolo21195d62021-04-07 14:31:23 -07001724 "IntfId": flow.AccessIntfId,
1725 "OnuId": flow.OnuId,
1726 "PortNo": flow.PortNo,
1727 "GemportId": flow.GemportId,
1728 "FlowId": flow.FlowId,
1729 "ReplicateFlow": flow.ReplicateFlow,
1730 "PbitToGemport": flow.PbitToGemport,
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001731 }).Trace("storing-gem-port-id-via-flow")
1732
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001733 if flow.ReplicateFlow {
1734 for _, gem := range flow.PbitToGemport {
1735 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, int32(gem), flow.FlowId)
1736 }
1737 } else {
1738 o.storeGemPortId(uint32(flow.AccessIntfId), uint32(flow.OnuId), flow.PortNo, flow.GemportId, flow.FlowId)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001739 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001740}
1741
1742func (o *OltDevice) freeGemPortId(flow *openolt.Flow) {
1743 // if this is the last flow referencing the GemPort then remove it
1744 o.GemPortIDsLock.Lock()
1745 defer o.GemPortIDsLock.Unlock()
1746
1747 oltLogger.WithFields(log.Fields{
1748 "IntfId": flow.AccessIntfId,
1749 "OnuId": flow.OnuId,
1750 "PortNo": flow.PortNo,
1751 "GemportId": flow.GemportId,
1752 }).Trace("freeing-gem-port-id-via-flow")
1753
1754 // NOTE that this loop is not very performant, it would be better if the flow carries
1755 // the same information that it carries during a FlowAdd. If so we can directly remove
1756 // items from the map
1757
1758 //delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId], flow.FlowId)
1759 //if len(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo][flow.GemportId]) == 0 {
1760 // delete(o.GemPortIDs[uint32(flow.AccessIntfId)][uint32(flow.OnuId)][flow.PortNo], flow.GemportId)
1761 //}
1762
1763 // NOTE this loop assumes that flow IDs are unique per device
1764 for ponId, ponValues := range o.GemPortIDs {
1765 for onuId, onuValues := range ponValues {
1766 for uniId, uniValues := range onuValues {
1767 for gemId, flows := range uniValues {
1768 for flowId := range flows {
1769 // if the flow matches, remove it from the map.
1770 if flow.FlowId == flowId {
1771 delete(o.GemPortIDs[ponId][onuId][uniId][gemId], flow.FlowId)
1772 }
1773 // if that was the last flow for a particular gem, remove the entire gem
1774 if len(o.GemPortIDs[ponId][onuId][uniId][gemId]) == 0 {
1775 delete(o.GemPortIDs[ponId][onuId][uniId], gemId)
1776 }
1777 }
1778 }
1779 }
1780 }
1781 }
1782}
1783
1784// validateFlow checks that:
1785// - the AllocId is not used in any flow referencing other ONUs/UNIs on the same PON
1786// - the GemPortId is not used in any flow referencing other ONUs/UNIs on the same PON
1787func (o *OltDevice) validateFlow(flow *openolt.Flow) error {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001788 // validate gemPort
1789 o.GemPortIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001790 defer o.GemPortIDsLock.RUnlock()
1791 for onuId, onu := range o.GemPortIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001792 if onuId == uint32(flow.OnuId) {
1793 continue
1794 }
1795 for uniId, uni := range onu {
1796 for gem := range uni {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001797 if flow.ReplicateFlow {
1798 for _, flowGem := range flow.PbitToGemport {
1799 if gem == int32(flowGem) {
1800 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-replicated-flow-%d", gem, uniId, onuId, flow.FlowId)
1801 }
1802 }
1803 } else {
1804 if gem == flow.GemportId {
1805 return fmt.Errorf("gem-%d-already-in-use-on-uni-%d-onu-%d-flow-%d", gem, uniId, onuId, flow.FlowId)
1806 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001807 }
1808 }
1809 }
1810 }
1811
1812 o.AllocIDsLock.RLock()
Matteo Scandolo21195d62021-04-07 14:31:23 -07001813 defer o.AllocIDsLock.RUnlock()
1814 for onuId, onu := range o.AllocIDs[uint32(flow.AccessIntfId)] {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001815 if onuId == uint32(flow.OnuId) {
1816 continue
1817 }
1818 for uniId, uni := range onu {
1819 for allocId := range uni {
1820 if allocId == flow.AllocId {
Matteo Scandoloa8eca492021-03-23 09:45:16 -07001821 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 -08001822 }
1823 }
1824 }
1825 }
1826
1827 return nil
1828}
1829
1830// clearAllResources is invoked up OLT Reboot to remove all the allocated
1831// GemPorts, AllocId and ONU-IDs across the PONs
1832func (o *OltDevice) clearAllResources() {
1833
1834 // remove the resources received via flows
1835 o.GemPortIDsLock.Lock()
1836 o.GemPortIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1837 o.GemPortIDsLock.Unlock()
1838 o.AllocIDsLock.Lock()
1839 o.AllocIDs = make(map[uint32]map[uint32]map[uint32]map[int32]map[uint64]bool)
1840 o.AllocIDsLock.Unlock()
1841
1842 // remove the resources received via OMCI
1843 for _, pon := range o.Pons {
1844 pon.removeAllAllocIds()
1845 pon.removeAllGemPorts()
1846 pon.removeAllOnuIds()
1847 }
1848}