blob: beeffce66242f5f047dd6fa0d47ce3afd2b67032 [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 Scandolo4f4ac792020-10-01 16:33:21 -070024 "github.com/opencord/voltha-protos/v4/go/ext/config"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025 "net"
26 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010027 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020028
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070029 "github.com/google/gopacket"
30 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070031 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070032 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010033 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040034 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070035 common_protos "github.com/opencord/voltha-protos/v4/go/common"
36 "github.com/opencord/voltha-protos/v4/go/openolt"
37 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070038 log "github.com/sirupsen/logrus"
39 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053040 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010041 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053042 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070043)
44
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070045var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070046 "module": "OLT",
47})
48
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070049type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000050 sync.Mutex
51
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070052 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053053 ID int
54 SerialNumber string
55 NumNni int
56 NumPon int
57 NumOnuPerPon int
58 InternalState *fsm.FSM
59 channel chan Message
Matteo Scandolo90d08f62020-10-29 12:06:55 -070060 dhcpServer dhcp.DHCPServerIf
Pragya Arya8bdb4532020-03-02 17:08:09 +053061 Flows map[FlowKey]openolt.Flow
Pragya Arya2225f202020-01-29 18:05:01 +053062 Delay int
63 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053064 EventChannel chan common.Event
65 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053066 PortStatsInterval int
Matteo Scandoloe33447a2019-10-31 12:38:23 -070067
Matteo Scandolo27428702019-10-11 16:21:16 -070068 Pons []*PonPort
69 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070070
71 // OLT Attributes
72 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000073
74 enableContext context.Context
75 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053076
Matteo Scandolo4a036262020-08-17 15:56:13 -070077 OpenoltStream openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053078 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070079}
80
Matteo Scandolo27428702019-10-11 16:21:16 -070081var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010082var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070083
Matteo Scandolo27428702019-10-11 16:21:16 -070084func GetOLT() *OltDevice {
85 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070086}
87
Matteo Scandolo4a036262020-08-17 15:56:13 -070088func CreateOLT(options common.GlobalConfig, services []common.ServiceYaml, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070089 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053090 "ID": options.Olt.ID,
91 "NumNni": options.Olt.NniPorts,
92 "NumPon": options.Olt.PonPorts,
93 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070094 }).Debug("CreateOLT")
95
Matteo Scandolo84f7d482019-08-08 19:00:47 -070096 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053097 ID: options.Olt.ID,
98 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070099 OperState: getOperStateFSM(func(e *fsm.Event) {
100 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
101 }),
Pragya Arya996a0892020-03-09 21:47:52 +0530102 NumNni: int(options.Olt.NniPorts),
103 NumPon: int(options.Olt.PonPorts),
104 NumOnuPerPon: int(options.Olt.OnusPonPort),
105 Pons: []*PonPort{},
106 Nnis: []*NniPort{},
107 Delay: options.BBSim.Delay,
108 Flows: make(map[FlowKey]openolt.Flow),
109 enablePerf: options.BBSim.EnablePerf,
110 PublishEvents: options.BBSim.Events,
111 PortStatsInterval: options.Olt.PortStatsInterval,
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700112 dhcpServer: dhcp.NewDHCPServer(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700113 }
114
Pragya Arya996a0892020-03-09 21:47:52 +0530115 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530116 olt.ControlledActivation = val
117 } else {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700118 // FIXME throw an error if the ControlledActivation is not valid
Pragya Arya2225f202020-01-29 18:05:01 +0530119 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
120 olt.ControlledActivation = Default
121 }
122
Matteo Scandolo4747d292019-08-05 11:50:18 -0700123 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700124 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700125 olt.InternalState = fsm.NewFSM(
126 "created",
127 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800128 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100129 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700131 // delete event in enabled state below is for reboot OLT case.
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800132 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133 },
134 fsm.Callbacks{
135 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700136 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100138 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139 },
140 )
141
Shrey Baid688b4242020-07-10 20:40:10 +0530142 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700143 // create NNI Port
144 nniPort, err := CreateNNI(&olt)
145 if err != nil {
146 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
147 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700148
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700149 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700151
Matteo Scandolo4a036262020-08-17 15:56:13 -0700152 // Create device and Services
153
154 nextCtag := map[string]int{}
155 nextStag := map[string]int{}
156
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700158 for i := 0; i < olt.NumPon; i++ {
159 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700160
Matteo Scandolo4a036262020-08-17 15:56:13 -0700161 // create ONU devices
162 for j := 0; j < olt.NumOnuPerPon; j++ {
163 delay := time.Duration(olt.Delay*j) * time.Millisecond
164 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700165
Matteo Scandolo4a036262020-08-17 15:56:13 -0700166 for k, s := range common.Services {
167
168 // find the correct cTag for this service
169 if _, ok := nextCtag[s.Name]; !ok {
170 // it's the first time we iterate over this service,
171 // so we start from the config value
172 nextCtag[s.Name] = s.CTag
173 } else {
174 // we have a previous value, so we check it
175 // if Allocation is unique, we increment,
176 // otherwise (shared) we do nothing
177 if s.CTagAllocation == common.TagAllocationUnique.String() {
178 nextCtag[s.Name] = nextCtag[s.Name] + 1
179 }
180 }
181
182 // find the correct sTag for this service
183 if _, ok := nextStag[s.Name]; !ok {
184 nextStag[s.Name] = s.STag
185 } else {
186 if s.STagAllocation == common.TagAllocationUnique.String() {
187 nextStag[s.Name] = nextStag[s.Name] + 1
188 }
189 }
190
191 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
192 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
193 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
194 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
195
196 if err != nil {
197 oltLogger.WithFields(log.Fields{
198 "Err": err.Error(),
199 }).Fatal("Can't create Service")
200 }
201
202 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700203 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700206 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700207 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100208
Shrey Baid688b4242020-07-10 20:40:10 +0530209 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700210 if err := olt.InternalState.Event("initialize"); err != nil {
211 log.Errorf("Error initializing OLT: %v", err)
212 return nil
213 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100214 }
215
Pragya Arya324337e2020-02-20 14:35:08 +0530216 if olt.PublishEvents {
217 log.Debugf("BBSim event publishing is enabled")
218 // Create a channel to write event messages
219 olt.EventChannel = make(chan common.Event, 100)
220 }
221
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700222 return &olt
223}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700224
Shrey Baid688b4242020-07-10 20:40:10 +0530225func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100226
227 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800228 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100229 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800230 // FIXME there should never be a server running if we are initializing the OLT
231 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100232 }
233
234 // create new channel for processOltMessages Go routine
235 o.channel = make(chan Message)
236
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100237 // FIXME we are assuming we have only one NNI
238 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800239 // NOTE we want to make sure the state is down when we initialize the OLT,
240 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
241 // in-band management
242 o.Nnis[0].OperState.SetState("down")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700244}
245
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800246func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100247
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700248 softReboot := false
Matteo Scandolo4a036262020-08-17 15:56:13 -0700249 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800250
251 oltLogger.WithFields(log.Fields{
252 "oltId": o.ID,
253 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
254
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700255 if o.InternalState.Is("enabled") {
256 oltLogger.WithFields(log.Fields{
257 "oltId": o.ID,
258 }).Info("This is an OLT soft reboot")
259 softReboot = true
260 }
261
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800262 // transition internal state to deleted
263 if err := o.InternalState.Event("delete"); err != nil {
264 oltLogger.WithFields(log.Fields{
265 "oltId": o.ID,
266 }).Errorf("Error deleting OLT: %v", err)
267 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100268 }
269
270 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800271 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
272 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530273 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100274 return err
275 }
276
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700277 if softReboot {
278 for _, pon := range o.Pons {
279 if pon.InternalState.Current() == "enabled" {
280 // disable PONs
281 msg := Message{
282 Type: PonIndication,
283 Data: PonIndicationMessage{
284 OperState: DOWN,
285 PonPortID: pon.ID,
286 },
287 }
288 o.channel <- msg
289 }
290
291 for _, onu := range pon.Onus {
292 _ = onu.InternalState.Event("disable")
293 }
294 }
295 } else {
296 // PONs are already handled in the Disable call
297 for _, pon := range olt.Pons {
298 // ONUs are not automatically disabled when a PON goes down
299 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
300 for _, onu := range pon.Onus {
301 _ = onu.InternalState.Event("disable")
302 }
Pragya Arya2225f202020-01-29 18:05:01 +0530303 }
304 }
305
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100306 // terminate the OLT's processOltMessages go routine
307 close(o.channel)
Matteo Scandolo90d08f62020-10-29 12:06:55 -0700308
Matteo Scandoloe9f5a6b2020-09-16 15:54:38 -0700309 o.enableContextCancel()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100311 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100312
313 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800314 oltLogger.WithFields(log.Fields{
315 "oltId": o.ID,
316 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100317 return err
318 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800319 oltLogger.WithFields(log.Fields{
320 "oltId": o.ID,
321 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100322 return nil
323}
324
325// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800326func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700327 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700328 lis, err := net.Listen("tcp", address)
329 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700330 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700331 }
332 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100333
Matteo Scandolo4747d292019-08-05 11:50:18 -0700334 openolt.RegisterOpenoltServer(grpcServer, o)
335
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100336 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700337
Shrey Baid688b4242020-07-10 20:40:10 +0530338 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100339 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700340
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100341 return grpcServer, nil
342}
343
344// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800345func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100346 // TODO handle poweroff vs graceful shutdown
347 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800348 oltLogger.WithFields(log.Fields{
349 "oltId": o.SerialNumber,
350 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351 oltServer.Stop()
352 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700353 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800354
Matteo Scandolo4747d292019-08-05 11:50:18 -0700355 return nil
356}
357
358// Device Methods
359
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100360// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530361func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700362 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530363 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700364
David Bainbridge103cf022019-12-16 20:11:35 +0000365 // If enabled has already been called then an enabled context has
366 // been created. If this is the case then we want to cancel all the
367 // proessing loops associated with that enable before we recreate
368 // new ones
369 o.Lock()
370 if o.enableContext != nil && o.enableContextCancel != nil {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -0700371 oltLogger.Info("This is an OLT reboot")
David Bainbridge103cf022019-12-16 20:11:35 +0000372 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530373 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000374 }
375 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
376 o.Unlock()
377
Matteo Scandolo4747d292019-08-05 11:50:18 -0700378 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800379 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700380
Matteo Scandolo4a036262020-08-17 15:56:13 -0700381 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530382
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100383 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000384 go o.processOltMessages(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700385
386 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100387 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700388 Type: OltIndication,
389 Data: OltIndicationMessage{
390 OperState: UP,
391 },
392 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100393 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700394
395 // send NNI Port Indications
396 for _, nni := range o.Nnis {
397 msg := Message{
398 Type: NniIndication,
399 Data: NniIndicationMessage{
400 OperState: UP,
401 NniPortID: nni.ID,
402 },
403 }
404 o.channel <- msg
405 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100406
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800407 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100408
Shrey Baid688b4242020-07-10 20:40:10 +0530409 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530410 for _, pon := range o.Pons {
411 if pon.InternalState.Current() == "disabled" {
412 msg := Message{
413 Type: PonIndication,
414 Data: PonIndicationMessage{
415 OperState: UP,
416 PonPortID: pon.ID,
417 },
418 }
419 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000420 }
Pragya Arya2225f202020-01-29 18:05:01 +0530421 }
422 } else {
423
424 // 1. controlledActivation == Default: Send both PON and ONUs indications
425 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
426
427 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
428 // send PON Port indications
429 for _, pon := range o.Pons {
430 msg := Message{
431 Type: PonIndication,
432 Data: PonIndicationMessage{
433 OperState: UP,
434 PonPortID: pon.ID,
435 },
436 }
437 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700438 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700439 }
440 }
441
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800442 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530443
444 if !o.enablePerf {
445 // Start a go routine to send periodic port stats to openolt adapter
446 go o.periodicPortStats(o.enableContext)
447 }
448
Matteo Scandolo4747d292019-08-05 11:50:18 -0700449 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700450}
451
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800452func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400453 ch := omcisim.GetChannel()
454
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100455 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400456
David Bainbridge103cf022019-12-16 20:11:35 +0000457loop:
458 for {
459 select {
460 case <-ctx.Done():
461 oltLogger.Debug("OMCI processing canceled via context")
462 break loop
463 case message, ok := <-ch:
464 if !ok || ctx.Err() != nil {
465 oltLogger.Debug("OMCI processing canceled via channel close")
466 break loop
467 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800468
469 oltLogger.WithFields(log.Fields{
470 "messageType": message.Type,
471 "OnuId": message.Data.OnuId,
472 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700473 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800474
David Bainbridge103cf022019-12-16 20:11:35 +0000475 onuId := message.Data.OnuId
476 intfId := message.Data.IntfId
477 onu, err := o.FindOnuById(intfId, onuId)
478 if err != nil {
479 oltLogger.Errorf("Failed to find onu: %v", err)
480 continue
481 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800482 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400483 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400484 }
David Bainbridge103cf022019-12-16 20:11:35 +0000485
486 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400487}
488
Pragya Arya996a0892020-03-09 21:47:52 +0530489func (o *OltDevice) periodicPortStats(ctx context.Context) {
490 var portStats *openolt.PortStatistics
491 for {
492 select {
493 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
494 // send NNI port stats
495 for _, port := range o.Nnis {
496 incrementStat := true
497 if port.OperState.Current() == "down" {
498 incrementStat = false
499 }
500 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
501 o.sendPortStatsIndication(portStats, port.ID, port.Type)
502 }
503
504 // send PON port stats
505 for _, port := range o.Pons {
506 incrementStat := true
507 // do not increment port stats if PON port is down or no ONU is activated on PON port
508 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
509 incrementStat = false
510 }
511 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
512 o.sendPortStatsIndication(portStats, port.ID, port.Type)
513 }
514 case <-ctx.Done():
515 log.Debug("Stop sending port stats")
516 return
517 }
518
519 }
520}
521
Matteo Scandolo4747d292019-08-05 11:50:18 -0700522// Helpers method
523
Shrey Baid688b4242020-07-10 20:40:10 +0530524func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700525 for _, pon := range o.Pons {
526 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700527 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700528 }
529 }
Shrey Baid688b4242020-07-10 20:40:10 +0530530 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700531}
532
Shrey Baid688b4242020-07-10 20:40:10 +0530533func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700534 for _, nni := range o.Nnis {
535 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700536 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700537 }
538 }
Shrey Baid688b4242020-07-10 20:40:10 +0530539 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540}
541
Scott Baker41724b82020-01-21 19:54:53 -0800542func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
543 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
544 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
545 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
546 return
547 }
548
549 oltLogger.WithFields(log.Fields{
550 "AlarmIndication": alarmInd,
551 }).Debug("Sent Indication_AlarmInd")
552}
553
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100554func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700555 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
556 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700557 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800558 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700559 }
560
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700561 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700562 "OperState": msg.OperState,
563 }).Debug("Sent Indication_OltInd")
564}
565
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100566func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700567 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800568 if msg.OperState == UP {
569 if err := nni.OperState.Event("enable"); err != nil {
570 log.WithFields(log.Fields{
571 "Type": nni.Type,
572 "IntfId": nni.ID,
573 "OperState": nni.OperState.Current(),
574 }).Errorf("Can't move NNI Port to enabled state: %v", err)
575 }
576 } else if msg.OperState == DOWN {
577 if err := nni.OperState.Event("disable"); err != nil {
578 log.WithFields(log.Fields{
579 "Type": nni.Type,
580 "IntfId": nni.ID,
581 "OperState": nni.OperState.Current(),
582 }).Errorf("Can't move NNI Port to disable state: %v", err)
583 }
584 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700585 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700586 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700587 Type: nni.Type,
588 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700589 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700590 }}
591
592 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700593 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800594 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700595 }
596
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700597 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700598 "Type": nni.Type,
599 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700600 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601 }).Debug("Sent Indication_IntfOperInd for NNI")
602}
603
Pragya Arya2225f202020-01-29 18:05:01 +0530604func (o *OltDevice) sendPonIndication(ponPortID uint32) {
605
Matteo Scandolo4a036262020-08-17 15:56:13 -0700606 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530607 pon, _ := o.GetPonById(ponPortID)
608 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700610 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700611 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612 }}
613
614 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700615 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800616 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617 }
618
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700619 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700620 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700621 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700622 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700623
Pragya Arya2225f202020-01-29 18:05:01 +0530624 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700625 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700626 Type: pon.Type,
627 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700628 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629 }}
630
631 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700632 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800633 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700634 }
635
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700636 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700637 "Type": pon.Type,
638 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700639 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700640 }).Debug("Sent Indication_IntfOperInd for PON")
641}
642
Pragya Arya996a0892020-03-09 21:47:52 +0530643func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530644 if o.InternalState.Current() == "enabled" {
645 oltLogger.WithFields(log.Fields{
646 "Type": portType,
647 "IntfId": portID,
648 }).Trace("Sending port stats")
649 stats.IntfId = InterfaceIDToPortNo(portID, portType)
650 data := &openolt.Indication_PortStats{
651 PortStats: stats,
652 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700653 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530654 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
655 oltLogger.Errorf("Failed to send PortStats: %v", err)
656 return
657 }
Pragya Arya996a0892020-03-09 21:47:52 +0530658 }
659}
660
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100661// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000662func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100663 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000664 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700665
David Bainbridge103cf022019-12-16 20:11:35 +0000666loop:
667 for {
668 select {
669 case <-ctx.Done():
670 oltLogger.Debug("OLT Indication processing canceled via context")
671 break loop
672 case message, ok := <-ch:
673 if !ok || ctx.Err() != nil {
674 oltLogger.Debug("OLT Indication processing canceled via closed channel")
675 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700676 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700677
David Bainbridge103cf022019-12-16 20:11:35 +0000678 oltLogger.WithFields(log.Fields{
679 "oltId": o.ID,
680 "messageType": message.Type,
681 }).Trace("Received message")
682
683 switch message.Type {
684 case OltIndication:
685 msg, _ := message.Data.(OltIndicationMessage)
686 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530687 _ = o.InternalState.Event("enable")
688 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000689 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530690 _ = o.InternalState.Event("disable")
691 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000692 }
693 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800694 case AlarmIndication:
695 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
696 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000697 case NniIndication:
698 msg, _ := message.Data.(NniIndicationMessage)
699 o.sendNniIndication(msg, stream)
700 case PonIndication:
701 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530702 pon, _ := o.GetPonById(msg.PonPortID)
703 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530704 if err := pon.OperState.Event("enable"); err != nil {
705 oltLogger.WithFields(log.Fields{
706 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800707 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530708 }).Error("Can't Enable Oper state for PON Port")
709 }
710 if err := pon.InternalState.Event("enable"); err != nil {
711 oltLogger.WithFields(log.Fields{
712 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800713 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530714 }).Error("Can't Enable Internal state for PON Port")
715 }
Pragya Arya2225f202020-01-29 18:05:01 +0530716 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530717 if err := pon.OperState.Event("disable"); err != nil {
718 oltLogger.WithFields(log.Fields{
719 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800720 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530721 }).Error("Can't Disable Oper state for PON Port")
722 }
723 if err := pon.InternalState.Event("disable"); err != nil {
724 oltLogger.WithFields(log.Fields{
725 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800726 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530727 }).Error("Can't Disable Internal state for PON Port")
728 }
Pragya Arya2225f202020-01-29 18:05:01 +0530729 }
David Bainbridge103cf022019-12-16 20:11:35 +0000730 default:
731 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
732 }
733 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700734 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100735 wg.Done()
736 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700737}
738
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700739// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530740func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200741 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700742 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700743 for _, pon := range o.Pons {
744 for _, onu := range pon.Onus {
745 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700746 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700747 }
748 }
749 }
750
Shrey Baid688b4242020-07-10 20:40:10 +0530751 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700752}
753
William Kurkian9dadc5b2019-10-22 13:51:57 -0400754// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530755func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200756 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400757 // memoizing it will remove the bottleneck
758 for _, pon := range o.Pons {
759 if pon.ID == intfId {
760 for _, onu := range pon.Onus {
761 if onu.ID == onuId {
762 return onu, nil
763 }
764 }
765 }
766 }
Shrey Baid688b4242020-07-10 20:40:10 +0530767 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400768}
769
Matteo Scandolo4a036262020-08-17 15:56:13 -0700770// returns a Service with a given Mac Address
771func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200772 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700773 // memoizing it will remove the bottleneck
774 for _, pon := range o.Pons {
775 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700776 s, err := onu.findServiceByMacAddress(mac)
777 if err == nil {
778 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700779 }
780 }
781 }
782
Matteo Scandolo4a036262020-08-17 15:56:13 -0700783 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700784}
785
Matteo Scandolo4747d292019-08-05 11:50:18 -0700786// GRPC Endpoints
787
Shrey Baid688b4242020-07-10 20:40:10 +0530788func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700789 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700790 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700791 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530792 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700793
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700794 pon, _ := o.GetPonById(onu.IntfId)
795 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500796 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700797
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700798 if err := _onu.OperState.Event("enable"); err != nil {
799 oltLogger.WithFields(log.Fields{
800 "IntfId": _onu.PonPortID,
801 "OnuSn": _onu.Sn(),
802 "OnuId": _onu.ID,
803 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700804 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700805 if err := _onu.InternalState.Event("enable"); err != nil {
806 oltLogger.WithFields(log.Fields{
807 "IntfId": _onu.PonPortID,
808 "OnuSn": _onu.Sn(),
809 "OnuId": _onu.ID,
810 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
811 }
812
813 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
814
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700815 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700816}
817
Shrey Baid688b4242020-07-10 20:40:10 +0530818func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700819 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700820 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700821}
822
Shrey Baid688b4242020-07-10 20:40:10 +0530823func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530824 oltLogger.WithFields(log.Fields{
825 "IntfId": onu.IntfId,
826 "OnuId": onu.OnuId,
827 }).Info("Received DeleteOnu call from VOLTHA")
828
829 pon, err := o.GetPonById(onu.IntfId)
830 if err != nil {
831 oltLogger.WithFields(log.Fields{
832 "OnuId": onu.OnuId,
833 "IntfId": onu.IntfId,
834 "err": err,
835 }).Error("Can't find PonPort")
836 }
837 _onu, err := pon.GetOnuById(onu.OnuId)
838 if err != nil {
839 oltLogger.WithFields(log.Fields{
840 "OnuId": onu.OnuId,
841 "IntfId": onu.IntfId,
842 "err": err,
843 }).Error("Can't find Onu")
844 }
845
Hardik Windlassad790cb2020-06-17 21:26:22 +0530846 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530847 oltLogger.WithFields(log.Fields{
848 "IntfId": _onu.PonPortID,
849 "OnuSn": _onu.Sn(),
850 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530851 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
852 }
853
Hardik Windlassad790cb2020-06-17 21:26:22 +0530854 // ONU Re-Discovery
855 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530856 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530857 }
858
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700859 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700860}
861
Shrey Baid688b4242020-07-10 20:40:10 +0530862func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700863 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800864 oltLogger.WithFields(log.Fields{
865 "oltId": o.ID,
866 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530867 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800868
Matteo Scandolo401503a2019-12-11 14:48:14 -0800869 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530870 if pon.InternalState.Current() == "enabled" {
871 // disable PONs
872 msg := Message{
873 Type: PonIndication,
874 Data: PonIndicationMessage{
875 OperState: DOWN,
876 PonPortID: pon.ID,
877 },
878 }
879 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800880 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800881 }
882
Matteo Scandolo401503a2019-12-11 14:48:14 -0800883 // Note that we are not disabling the NNI as the real OLT does not.
884 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800885
886 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100887 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700888 Type: OltIndication,
889 Data: OltIndicationMessage{
890 OperState: DOWN,
891 },
892 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100893 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700894 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700895}
896
Shrey Baid688b4242020-07-10 20:40:10 +0530897func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530898 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200899 ponID := intf.GetIntfId()
900 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200901
902 msg := Message{
903 Type: PonIndication,
904 Data: PonIndicationMessage{
905 OperState: DOWN,
906 PonPortID: ponID,
907 },
908 }
909 o.channel <- msg
910
911 for _, onu := range pon.Onus {
912
913 onuIndication := OnuIndicationMessage{
914 OperState: DOWN,
915 PonPortID: ponID,
916 OnuID: onu.ID,
917 OnuSN: onu.SerialNumber,
918 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700919 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200920
921 }
922
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700923 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700924}
925
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100926func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700927 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530928 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700929 o.Enable(stream)
930 return nil
931}
932
Shrey Baid688b4242020-07-10 20:40:10 +0530933func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530934 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530935 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200936 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200937
Pragya Arya2225f202020-01-29 18:05:01 +0530938 msg := Message{
939 Type: PonIndication,
940 Data: PonIndicationMessage{
941 OperState: UP,
942 PonPortID: ponID,
943 },
944 }
945 o.channel <- msg
946
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200947 for _, onu := range pon.Onus {
948
949 onuIndication := OnuIndicationMessage{
950 OperState: UP,
951 PonPortID: ponID,
952 OnuID: onu.ID,
953 OnuSN: onu.SerialNumber,
954 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700955 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200956
957 }
958
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700959 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700960}
961
Shrey Baid688b4242020-07-10 20:40:10 +0530962func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700963 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700964 "IntfId": flow.AccessIntfId,
965 "OnuId": flow.OnuId,
966 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700967 "InnerVlan": flow.Classifier.IVid,
968 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700969 "FlowType": flow.FlowType,
970 "FlowId": flow.FlowId,
971 "UniID": flow.UniId,
972 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +0530973 }).Tracef("OLT receives FlowAdd")
974
975 flowKey := FlowKey{}
976 if !o.enablePerf {
977 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
978 olt.Flows[flowKey] = *flow
979 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700980
981 if flow.AccessIntfId == -1 {
982 oltLogger.WithFields(log.Fields{
983 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700984 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -0700985 } else if flow.FlowType == "multicast" {
986 oltLogger.WithFields(log.Fields{
Matteo Scandolo618a6582020-09-09 12:21:29 -0700987 "Cookie": flow.Cookie,
988 "DstPort": flow.Classifier.DstPort,
989 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
990 "FlowId": flow.FlowId,
991 "FlowType": flow.FlowType,
992 "GemportId": flow.GemportId,
993 "InnerVlan": flow.Classifier.IVid,
994 "IntfId": flow.AccessIntfId,
995 "IpProto": flow.Classifier.IpProto,
996 "OnuId": flow.OnuId,
997 "OuterVlan": flow.Classifier.OVid,
998 "PortNo": flow.PortNo,
999 "SrcPort": flow.Classifier.SrcPort,
1000 "UniID": flow.UniId,
1001 "ClassifierOPbits": flow.Classifier.OPbits,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001002 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001003 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001004 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001005 if err != nil {
1006 oltLogger.WithFields(log.Fields{
1007 "OnuId": flow.OnuId,
1008 "IntfId": flow.AccessIntfId,
1009 "err": err,
1010 }).Error("Can't find PonPort")
1011 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001012 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001013 if err != nil {
1014 oltLogger.WithFields(log.Fields{
1015 "OnuId": flow.OnuId,
1016 "IntfId": flow.AccessIntfId,
1017 "err": err,
1018 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001019 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001020 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301021 if !o.enablePerf {
1022 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301023 // Generate event on first flow for ONU
1024 if len(onu.Flows) == 1 {
1025 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1026 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301027 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001028
1029 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001030 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001031 Data: OnuFlowUpdateMessage{
1032 PonPortID: pon.ID,
1033 OnuID: onu.ID,
1034 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001035 },
1036 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001037 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001038 }
1039
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001040 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001041}
1042
Pragya Arya8bdb4532020-03-02 17:08:09 +05301043// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301044func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001045
Pragya Arya8bdb4532020-03-02 17:08:09 +05301046 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301047 "FlowId": flow.FlowId,
1048 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001049 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301050
1051 if !o.enablePerf { // remove only if flow were stored
1052 flowKey := FlowKey{
1053 ID: flow.FlowId,
1054 Direction: flow.FlowType,
1055 }
1056
1057 // Check if flow exists
1058 storedFlow, ok := o.Flows[flowKey]
1059 if !ok {
1060 oltLogger.Errorf("Flow %v not found", flow)
1061 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1062 }
1063
1064 // if its ONU flow remove it from ONU also
1065 if storedFlow.AccessIntfId != -1 {
1066 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1067 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1068 if err != nil {
1069 oltLogger.WithFields(log.Fields{
1070 "OnuId": storedFlow.OnuId,
1071 "IntfId": storedFlow.AccessIntfId,
1072 "err": err,
1073 }).Error("ONU not found")
1074 return new(openolt.Empty), nil
1075 }
1076 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301077 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301078 }
1079
1080 // delete from olt flows
1081 delete(o.Flows, flowKey)
1082 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001083
1084 if flow.AccessIntfId == -1 {
1085 oltLogger.WithFields(log.Fields{
1086 "FlowId": flow.FlowId,
1087 }).Debug("Removing OLT flow")
1088 } else if flow.FlowType == "multicast" {
1089 oltLogger.WithFields(log.Fields{
1090 "FlowId": flow.FlowId,
1091 }).Debug("Removing OLT multicast flow")
1092 } else {
1093
1094 onu, err := o.GetOnuByFlowId(flow.FlowId)
1095 if err != nil {
1096 oltLogger.WithFields(log.Fields{
1097 "OnuId": flow.OnuId,
1098 "IntfId": flow.AccessIntfId,
1099 "err": err,
1100 }).Error("Can't find Onu")
1101 return nil, err
1102 }
1103
1104 msg := Message{
1105 Type: FlowRemoved,
1106 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301107 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001108 },
1109 }
1110 onu.Channel <- msg
1111 }
1112
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001113 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001114}
1115
Shrey Baid688b4242020-07-10 20:40:10 +05301116func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001117 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1118 oltLogger.WithFields(log.Fields{
1119 "signature": res.HeartbeatSignature,
1120 }).Trace("HeartbeatCheck")
1121 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001122}
1123
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001124func (o *OltDevice) GetOnuByFlowId(flowId uint64) (*Onu, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001125 for _, pon := range o.Pons {
1126 for _, onu := range pon.Onus {
1127 for _, fId := range onu.FlowIds {
1128 if fId == flowId {
1129 return onu, nil
1130 }
1131 }
1132 }
1133 }
Shrey Baid688b4242020-07-10 20:40:10 +05301134 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001135}
1136
Shrey Baid688b4242020-07-10 20:40:10 +05301137func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001138
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001139 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001140 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001141 "PonPorts": o.NumPon,
1142 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001143 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001144 devinfo.Vendor = common.Config.Olt.Vendor
1145 devinfo.Model = common.Config.Olt.Model
1146 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1147 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1148 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001149 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001150 devinfo.OnuIdStart = 1
1151 devinfo.OnuIdEnd = 255
1152 devinfo.AllocIdStart = 1024
1153 devinfo.AllocIdEnd = 16383
1154 devinfo.GemportIdStart = 1024
1155 devinfo.GemportIdEnd = 65535
1156 devinfo.FlowIdStart = 1
1157 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001158 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001159 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001160
1161 return devinfo, nil
1162}
1163
Shrey Baid688b4242020-07-10 20:40:10 +05301164func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001165 pon, err := o.GetPonById(omci_msg.IntfId)
1166 if err != nil {
1167 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001168 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001169 "onu_id": omci_msg.OnuId,
1170 "pon_id": omci_msg.IntfId,
1171 }).Error("pon ID not found")
1172 return nil, err
1173 }
1174
1175 onu, err := pon.GetOnuById(omci_msg.OnuId)
1176 if err != nil {
1177 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001178 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001179 "onu_id": omci_msg.OnuId,
1180 "pon_id": omci_msg.IntfId,
1181 }).Error("onu ID not found")
1182 return nil, err
1183 }
1184
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001185 oltLogger.WithFields(log.Fields{
1186 "IntfId": onu.PonPortID,
1187 "OnuId": onu.ID,
1188 "OnuSn": onu.Sn(),
1189 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001190 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001191 Type: OMCI,
1192 Data: OmciMessage{
1193 OnuSN: onu.SerialNumber,
1194 OnuID: onu.ID,
1195 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001196 },
1197 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001198 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001199 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001200}
1201
Shrey Baid688b4242020-07-10 20:40:10 +05301202func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001203 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001204 if err != nil {
1205 oltLogger.WithFields(log.Fields{
1206 "OnuId": onuPkt.OnuId,
1207 "IntfId": onuPkt.IntfId,
1208 "err": err,
1209 }).Error("Can't find PonPort")
1210 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001211 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001212 if err != nil {
1213 oltLogger.WithFields(log.Fields{
1214 "OnuId": onuPkt.OnuId,
1215 "IntfId": onuPkt.IntfId,
1216 "err": err,
1217 }).Error("Can't find Onu")
1218 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001219
Matteo Scandolo075b1892019-10-07 12:11:07 -07001220 oltLogger.WithFields(log.Fields{
1221 "IntfId": onu.PonPortID,
1222 "OnuId": onu.ID,
1223 "OnuSn": onu.Sn(),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001224 "Packet": hex.EncodeToString(onuPkt.Pkt),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001225 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001226
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001227 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo618a6582020-09-09 12:21:29 -07001228
1229 pktType, err := packetHandlers.GetPktType(rawpkt)
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001230 if err != nil {
1231 onuLogger.WithFields(log.Fields{
1232 "IntfId": onu.PonPortID,
1233 "OnuId": onu.ID,
1234 "OnuSn": onu.Sn(),
Matteo Scandolo618a6582020-09-09 12:21:29 -07001235 "Pkt": hex.EncodeToString(rawpkt.Data()),
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001236 }).Error("Can't find pktType in packet, droppint it")
1237 return new(openolt.Empty), nil
1238 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001239
Matteo Scandolo4a036262020-08-17 15:56:13 -07001240 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001241 if err != nil {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001242 onuLogger.WithFields(log.Fields{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001243 "IntfId": onu.PonPortID,
1244 "OnuId": onu.ID,
1245 "OnuSn": onu.Sn(),
1246 "Pkt": rawpkt.Data(),
1247 }).Error("Can't find Dst MacAddress in packet, droppint it")
1248 return new(openolt.Empty), nil
1249 }
1250
Matteo Scandolo075b1892019-10-07 12:11:07 -07001251 msg := Message{
1252 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001253 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001254 IntfId: onuPkt.IntfId,
1255 OnuId: onuPkt.OnuId,
1256 Packet: rawpkt,
1257 Type: pktType,
1258 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001259 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001260 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001261
Matteo Scandolo075b1892019-10-07 12:11:07 -07001262 onu.Channel <- msg
1263
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001264 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001265}
1266
Shrey Baid688b4242020-07-10 20:40:10 +05301267func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo635b2bf2020-09-04 10:23:40 -07001268
1269 // OLT Reboot is called in two cases:
1270 // - 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)
1271 // - when an OLT needs to be rebooted (voltcl device reboot)
1272
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001273 oltLogger.WithFields(log.Fields{
1274 "oltId": o.ID,
1275 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301276 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301277 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001278 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001279}
1280
Shrey Baid688b4242020-07-10 20:40:10 +05301281func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301282 oltLogger.WithFields(log.Fields{
1283 "oltId": o.ID,
1284 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301285 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301286
Pragya Arya2225f202020-01-29 18:05:01 +05301287 // enable OLT
1288 oltMsg := Message{
1289 Type: OltIndication,
1290 Data: OltIndicationMessage{
1291 OperState: UP,
1292 },
Pragya Arya1881df02020-01-29 18:05:01 +05301293 }
Pragya Arya2225f202020-01-29 18:05:01 +05301294 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301295
Pragya Arya2225f202020-01-29 18:05:01 +05301296 for _, pon := range o.Pons {
1297 if pon.InternalState.Current() == "disabled" {
1298 msg := Message{
1299 Type: PonIndication,
1300 Data: PonIndicationMessage{
1301 OperState: UP,
1302 PonPortID: pon.ID,
1303 },
1304 }
1305 o.channel <- msg
1306 }
1307 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001308
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001309 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001310}
1311
Shrey Baid688b4242020-07-10 20:40:10 +05301312func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001313 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1314
Matteo Scandolo90d08f62020-10-29 12:06:55 -07001315 err := o.Nnis[0].handleNniPacket(pkt) // FIXME we are assuming we have only one NNI
1316
1317 if err != nil {
1318 return nil, err
1319 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001320 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001321}
1322
Shrey Baid688b4242020-07-10 20:40:10 +05301323func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001324 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001325 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001326}
1327
Shrey Baid688b4242020-07-10 20:40:10 +05301328func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001329 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001330 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001331}
1332
Shrey Baid688b4242020-07-10 20:40:10 +05301333func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001334 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001335 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001336}
1337
Shrey Baid688b4242020-07-10 20:40:10 +05301338func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001339 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001340 return new(openolt.Empty), nil
1341}
1342
Shrey Baid688b4242020-07-10 20:40:10 +05301343func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001344 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001345 return new(openolt.Empty), nil
1346}
1347
Shrey Baid688b4242020-07-10 20:40:10 +05301348func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301349 oltLogger.WithFields(log.Fields{
1350 "OnuId": trafficSchedulers.OnuId,
1351 "IntfId": trafficSchedulers.IntfId,
1352 "OnuPortNo": trafficSchedulers.PortNo,
1353 }).Info("received CreateTrafficSchedulers")
1354
1355 if !s.enablePerf {
1356 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1357 if err != nil {
1358 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1359 return new(openolt.Empty), err
1360 }
1361 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1362 if err != nil {
1363 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1364 return new(openolt.Empty), err
1365 }
1366 onu.TrafficSchedulers = trafficSchedulers
1367 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001368 return new(openolt.Empty), nil
1369}
1370
Shrey Baid688b4242020-07-10 20:40:10 +05301371func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301372 oltLogger.WithFields(log.Fields{
1373 "OnuId": trafficSchedulers.OnuId,
1374 "IntfId": trafficSchedulers.IntfId,
1375 "OnuPortNo": trafficSchedulers.PortNo,
1376 }).Info("received RemoveTrafficSchedulers")
1377 if !s.enablePerf {
1378 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1379 if err != nil {
1380 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1381 return new(openolt.Empty), err
1382 }
1383 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1384 if err != nil {
1385 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1386 return new(openolt.Empty), err
1387 }
1388
1389 onu.TrafficSchedulers = nil
1390 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001391 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001392}
Scott Baker41724b82020-01-21 19:54:53 -08001393
1394// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301395func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001396 msg := Message{
1397 Type: AlarmIndication,
1398 Data: ind,
1399 }
1400
1401 o.channel <- msg
1402 return nil
1403}
Matteo Scandolo618a6582020-09-09 12:21:29 -07001404
1405func (o *OltDevice) PerformGroupOperation(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1406 oltLogger.WithFields(log.Fields{
1407 "GroupId": group.GroupId,
1408 "Command": group.Command,
1409 "Members": group.Members,
1410 "Action": group.Action,
1411 }).Debug("received PerformGroupOperation")
1412 return &openolt.Empty{}, nil
1413}
1414
1415func (o *OltDevice) DeleteGroup(ctx context.Context, group *openolt.Group) (*openolt.Empty, error) {
1416 oltLogger.WithFields(log.Fields{
1417 "GroupId": group.GroupId,
1418 "Command": group.Command,
1419 "Members": group.Members,
1420 "Action": group.Action,
1421 }).Debug("received PerformGroupOperation")
1422 return &openolt.Empty{}, nil
1423}
1424
1425func (o *OltDevice) GetExtValue(ctx context.Context, in *openolt.ValueParam) (*common_protos.ReturnValues, error) {
1426 return &common_protos.ReturnValues{}, nil
1427}
1428
1429func (o *OltDevice) OnuItuPonAlarmSet(ctx context.Context, in *config.OnuItuPonAlarm) (*openolt.Empty, error) {
1430 return &openolt.Empty{}, nil
1431}
1432
1433func (o *OltDevice) GetLogicalOnuDistanceZero(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1434 return &openolt.OnuLogicalDistance{}, nil
1435}
1436
1437func (o *OltDevice) GetLogicalOnuDistance(ctx context.Context, in *openolt.Onu) (*openolt.OnuLogicalDistance, error) {
1438 return &openolt.OnuLogicalDistance{}, nil
1439}