blob: 49ea3febfde0062d69bcef836a1930537234700c [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"
24 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010025 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070027 "github.com/google/gopacket"
28 "github.com/google/gopacket/layers"
Matteo Scandolodf3f85d2020-01-15 12:50:48 -080029 "github.com/google/gopacket/pcap"
Matteo Scandolo4747d292019-08-05 11:50:18 -070030 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070031 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070032 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
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 Scandolo3de9de02019-11-14 13:40:03 -080035 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolof65e6872020-04-15 15:18:43 -070036 "github.com/opencord/voltha-protos/v2/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 log "github.com/sirupsen/logrus"
38 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053039 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010040 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053041 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070042)
43
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070044var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070045 "module": "OLT",
46})
47
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070048type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000049 sync.Mutex
50
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070051 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053052 ID int
53 SerialNumber string
54 NumNni int
55 NumPon int
56 NumOnuPerPon int
57 InternalState *fsm.FSM
58 channel chan Message
59 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
60 nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
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 Scandolo4747d292019-08-05 11:50:18 -0700112 }
113
Pragya Arya996a0892020-03-09 21:47:52 +0530114 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530115 olt.ControlledActivation = val
116 } else {
117 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
118 olt.ControlledActivation = Default
119 }
120
Matteo Scandolo4747d292019-08-05 11:50:18 -0700121 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700122 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700123 olt.InternalState = fsm.NewFSM(
124 "created",
125 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800126 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100127 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700128 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800129 //delete event in enabled state below is for reboot OLT case.
130 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700131 },
132 fsm.Callbacks{
133 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700134 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700135 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100136 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137 },
138 )
139
Shrey Baid688b4242020-07-10 20:40:10 +0530140 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700141 // create NNI Port
142 nniPort, err := CreateNNI(&olt)
143 if err != nil {
144 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
145 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700146
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700147 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149
Matteo Scandolo4a036262020-08-17 15:56:13 -0700150 // Create device and Services
151
152 nextCtag := map[string]int{}
153 nextStag := map[string]int{}
154
Matteo Scandolo4747d292019-08-05 11:50:18 -0700155 // create PON ports
Matteo Scandolo4a036262020-08-17 15:56:13 -0700156 for i := 0; i < olt.NumPon; i++ {
157 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700158
Matteo Scandolo4a036262020-08-17 15:56:13 -0700159 // create ONU devices
160 for j := 0; j < olt.NumOnuPerPon; j++ {
161 delay := time.Duration(olt.Delay*j) * time.Millisecond
162 o := CreateONU(&olt, p, uint32(j+1), delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700163
Matteo Scandolo4a036262020-08-17 15:56:13 -0700164 for k, s := range common.Services {
165
166 // find the correct cTag for this service
167 if _, ok := nextCtag[s.Name]; !ok {
168 // it's the first time we iterate over this service,
169 // so we start from the config value
170 nextCtag[s.Name] = s.CTag
171 } else {
172 // we have a previous value, so we check it
173 // if Allocation is unique, we increment,
174 // otherwise (shared) we do nothing
175 if s.CTagAllocation == common.TagAllocationUnique.String() {
176 nextCtag[s.Name] = nextCtag[s.Name] + 1
177 }
178 }
179
180 // find the correct sTag for this service
181 if _, ok := nextStag[s.Name]; !ok {
182 nextStag[s.Name] = s.STag
183 } else {
184 if s.STagAllocation == common.TagAllocationUnique.String() {
185 nextStag[s.Name] = nextStag[s.Name] + 1
186 }
187 }
188
189 mac := net.HardwareAddr{0x2e, 0x60, byte(olt.ID), byte(p.ID), byte(o.ID), byte(k)}
190 service, err := NewService(s.Name, mac, o, nextCtag[s.Name], nextStag[s.Name],
191 s.NeedsEapol, s.NeedsDchp, s.NeedsIgmp, s.TechnologyProfileID, s.UniTagMatch,
192 s.ConfigureMacAddress, s.UsPonCTagPriority, s.UsPonSTagPriority, s.DsPonCTagPriority, s.DsPonSTagPriority)
193
194 if err != nil {
195 oltLogger.WithFields(log.Fields{
196 "Err": err.Error(),
197 }).Fatal("Can't create Service")
198 }
199
200 o.Services = append(o.Services, service)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700201 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700202 p.Onus = append(p.Onus, o)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700203 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700204 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700205 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206
Shrey Baid688b4242020-07-10 20:40:10 +0530207 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700208 if err := olt.InternalState.Event("initialize"); err != nil {
209 log.Errorf("Error initializing OLT: %v", err)
210 return nil
211 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 }
213
Pragya Arya324337e2020-02-20 14:35:08 +0530214 if olt.PublishEvents {
215 log.Debugf("BBSim event publishing is enabled")
216 // Create a channel to write event messages
217 olt.EventChannel = make(chan common.Event, 100)
218 }
219
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700220 return &olt
221}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700222
Shrey Baid688b4242020-07-10 20:40:10 +0530223func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100224
225 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800226 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100227 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800228 // FIXME there should never be a server running if we are initializing the OLT
229 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100230 }
231
232 // create new channel for processOltMessages Go routine
233 o.channel = make(chan Message)
234
235 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
236 // FIXME we are assuming we have only one NNI
237 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800238 // NOTE we want to make sure the state is down when we initialize the OLT,
239 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
240 // in-band management
241 o.Nnis[0].OperState.SetState("down")
242 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100243 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800244 oltLogger.WithFields(log.Fields{
245 "Type": o.Nnis[0].Type,
246 "IntfId": o.Nnis[0].ID,
247 "OperState": o.Nnis[0].OperState.Current(),
248 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100249 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800250 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100251 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800252 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100253 }
254 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700255}
256
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800257func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100258
Matteo Scandolo4a036262020-08-17 15:56:13 -0700259 rebootDelay := common.Config.Olt.OltRebootDelay
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800260
261 oltLogger.WithFields(log.Fields{
262 "oltId": o.ID,
263 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
264
265 // transition internal state to deleted
266 if err := o.InternalState.Event("delete"); err != nil {
267 oltLogger.WithFields(log.Fields{
268 "oltId": o.ID,
269 }).Errorf("Error deleting OLT: %v", err)
270 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100271 }
272
273 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800274 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
275 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530276 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100277 return err
278 }
279
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700280 // PONs are already handled in the Disable call
Pragya Arya2225f202020-01-29 18:05:01 +0530281 for _, pon := range olt.Pons {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700282 // ONUs are not automatically disabled when a PON goes down
283 // as it's possible that it's an admin down and in that case the ONUs need to keep their state
Pragya Arya2225f202020-01-29 18:05:01 +0530284 for _, onu := range pon.Onus {
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700285 _ = onu.InternalState.Event("disable")
Pragya Arya2225f202020-01-29 18:05:01 +0530286 }
287 }
288
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289 // terminate the OLT's processOltMessages go routine
290 close(o.channel)
291 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700292 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100293 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100294
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100295 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100296
297 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800298 oltLogger.WithFields(log.Fields{
299 "oltId": o.ID,
300 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100301 return err
302 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800303 oltLogger.WithFields(log.Fields{
304 "oltId": o.ID,
305 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100306 return nil
307}
308
309// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800310func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700311 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700312 lis, err := net.Listen("tcp", address)
313 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700314 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700315 }
316 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100317
Matteo Scandolo4747d292019-08-05 11:50:18 -0700318 openolt.RegisterOpenoltServer(grpcServer, o)
319
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700321
Shrey Baid688b4242020-07-10 20:40:10 +0530322 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100323 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700324
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100325 return grpcServer, nil
326}
327
328// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800329func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100330 // TODO handle poweroff vs graceful shutdown
331 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800332 oltLogger.WithFields(log.Fields{
333 "oltId": o.SerialNumber,
334 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100335 oltServer.Stop()
336 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700337 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800338
Matteo Scandolo4747d292019-08-05 11:50:18 -0700339 return nil
340}
341
342// Device Methods
343
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100344// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530345func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700346 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530347 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700348
David Bainbridge103cf022019-12-16 20:11:35 +0000349 // If enabled has already been called then an enabled context has
350 // been created. If this is the case then we want to cancel all the
351 // proessing loops associated with that enable before we recreate
352 // new ones
353 o.Lock()
354 if o.enableContext != nil && o.enableContextCancel != nil {
355 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530356 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000357 }
358 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
359 o.Unlock()
360
Matteo Scandolo4747d292019-08-05 11:50:18 -0700361 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800362 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700363
Matteo Scandolo4a036262020-08-17 15:56:13 -0700364 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530365
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100366 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000367 go o.processOltMessages(o.enableContext, stream, &wg)
368 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700369
370 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100371 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700372 Type: OltIndication,
373 Data: OltIndicationMessage{
374 OperState: UP,
375 },
376 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100377 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700378
379 // send NNI Port Indications
380 for _, nni := range o.Nnis {
381 msg := Message{
382 Type: NniIndication,
383 Data: NniIndicationMessage{
384 OperState: UP,
385 NniPortID: nni.ID,
386 },
387 }
388 o.channel <- msg
389 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100390
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800391 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100392
Shrey Baid688b4242020-07-10 20:40:10 +0530393 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530394 for _, pon := range o.Pons {
395 if pon.InternalState.Current() == "disabled" {
396 msg := Message{
397 Type: PonIndication,
398 Data: PonIndicationMessage{
399 OperState: UP,
400 PonPortID: pon.ID,
401 },
402 }
403 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000404 }
Pragya Arya2225f202020-01-29 18:05:01 +0530405 }
406 } else {
407
408 // 1. controlledActivation == Default: Send both PON and ONUs indications
409 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
410
411 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
412 // send PON Port indications
413 for _, pon := range o.Pons {
414 msg := Message{
415 Type: PonIndication,
416 Data: PonIndicationMessage{
417 OperState: UP,
418 PonPortID: pon.ID,
419 },
420 }
421 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700422 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700423 }
424 }
425
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800426 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530427
428 if !o.enablePerf {
429 // Start a go routine to send periodic port stats to openolt adapter
430 go o.periodicPortStats(o.enableContext)
431 }
432
Matteo Scandolo4747d292019-08-05 11:50:18 -0700433 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700434}
435
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800436func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400437 ch := omcisim.GetChannel()
438
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100439 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400440
David Bainbridge103cf022019-12-16 20:11:35 +0000441loop:
442 for {
443 select {
444 case <-ctx.Done():
445 oltLogger.Debug("OMCI processing canceled via context")
446 break loop
447 case message, ok := <-ch:
448 if !ok || ctx.Err() != nil {
449 oltLogger.Debug("OMCI processing canceled via channel close")
450 break loop
451 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800452
453 oltLogger.WithFields(log.Fields{
454 "messageType": message.Type,
455 "OnuId": message.Data.OnuId,
456 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700457 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800458
David Bainbridge103cf022019-12-16 20:11:35 +0000459 onuId := message.Data.OnuId
460 intfId := message.Data.IntfId
461 onu, err := o.FindOnuById(intfId, onuId)
462 if err != nil {
463 oltLogger.Errorf("Failed to find onu: %v", err)
464 continue
465 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800466 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400467 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400468 }
David Bainbridge103cf022019-12-16 20:11:35 +0000469
470 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400471}
472
Pragya Arya996a0892020-03-09 21:47:52 +0530473func (o *OltDevice) periodicPortStats(ctx context.Context) {
474 var portStats *openolt.PortStatistics
475 for {
476 select {
477 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
478 // send NNI port stats
479 for _, port := range o.Nnis {
480 incrementStat := true
481 if port.OperState.Current() == "down" {
482 incrementStat = false
483 }
484 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
485 o.sendPortStatsIndication(portStats, port.ID, port.Type)
486 }
487
488 // send PON port stats
489 for _, port := range o.Pons {
490 incrementStat := true
491 // do not increment port stats if PON port is down or no ONU is activated on PON port
492 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
493 incrementStat = false
494 }
495 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
496 o.sendPortStatsIndication(portStats, port.ID, port.Type)
497 }
498 case <-ctx.Done():
499 log.Debug("Stop sending port stats")
500 return
501 }
502
503 }
504}
505
Matteo Scandolo4747d292019-08-05 11:50:18 -0700506// Helpers method
507
Shrey Baid688b4242020-07-10 20:40:10 +0530508func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700509 for _, pon := range o.Pons {
510 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700511 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700512 }
513 }
Shrey Baid688b4242020-07-10 20:40:10 +0530514 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700515}
516
Shrey Baid688b4242020-07-10 20:40:10 +0530517func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700518 for _, nni := range o.Nnis {
519 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700520 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700521 }
522 }
Shrey Baid688b4242020-07-10 20:40:10 +0530523 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700524}
525
Scott Baker41724b82020-01-21 19:54:53 -0800526func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
527 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
528 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
529 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
530 return
531 }
532
533 oltLogger.WithFields(log.Fields{
534 "AlarmIndication": alarmInd,
535 }).Debug("Sent Indication_AlarmInd")
536}
537
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100538func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700539 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
540 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700541 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800542 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700543 }
544
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700545 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700546 "OperState": msg.OperState,
547 }).Debug("Sent Indication_OltInd")
548}
549
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100550func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700551 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800552 if msg.OperState == UP {
553 if err := nni.OperState.Event("enable"); err != nil {
554 log.WithFields(log.Fields{
555 "Type": nni.Type,
556 "IntfId": nni.ID,
557 "OperState": nni.OperState.Current(),
558 }).Errorf("Can't move NNI Port to enabled state: %v", err)
559 }
560 } else if msg.OperState == DOWN {
561 if err := nni.OperState.Event("disable"); err != nil {
562 log.WithFields(log.Fields{
563 "Type": nni.Type,
564 "IntfId": nni.ID,
565 "OperState": nni.OperState.Current(),
566 }).Errorf("Can't move NNI Port to disable state: %v", err)
567 }
568 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700569 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700570 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700571 Type: nni.Type,
572 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700573 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700574 }}
575
576 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700577 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800578 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700579 }
580
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700581 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700582 "Type": nni.Type,
583 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700584 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700585 }).Debug("Sent Indication_IntfOperInd for NNI")
586}
587
Pragya Arya2225f202020-01-29 18:05:01 +0530588func (o *OltDevice) sendPonIndication(ponPortID uint32) {
589
Matteo Scandolo4a036262020-08-17 15:56:13 -0700590 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530591 pon, _ := o.GetPonById(ponPortID)
592 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700593 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700594 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700595 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700596 }}
597
598 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700599 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800600 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601 }
602
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700603 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700604 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700605 "OperState": pon.OperState.Current(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700606 }).Debug("Sent Indication_IntfInd for PON")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700607
Pragya Arya2225f202020-01-29 18:05:01 +0530608 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700610 Type: pon.Type,
611 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700612 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700613 }}
614
615 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700616 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800617 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700618 }
619
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700620 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700621 "Type": pon.Type,
622 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700623 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700624 }).Debug("Sent Indication_IntfOperInd for PON")
625}
626
Pragya Arya996a0892020-03-09 21:47:52 +0530627func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530628 if o.InternalState.Current() == "enabled" {
629 oltLogger.WithFields(log.Fields{
630 "Type": portType,
631 "IntfId": portID,
632 }).Trace("Sending port stats")
633 stats.IntfId = InterfaceIDToPortNo(portID, portType)
634 data := &openolt.Indication_PortStats{
635 PortStats: stats,
636 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700637 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530638 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
639 oltLogger.Errorf("Failed to send PortStats: %v", err)
640 return
641 }
Pragya Arya996a0892020-03-09 21:47:52 +0530642 }
643}
644
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100645// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000646func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100647 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000648 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700649
David Bainbridge103cf022019-12-16 20:11:35 +0000650loop:
651 for {
652 select {
653 case <-ctx.Done():
654 oltLogger.Debug("OLT Indication processing canceled via context")
655 break loop
656 case message, ok := <-ch:
657 if !ok || ctx.Err() != nil {
658 oltLogger.Debug("OLT Indication processing canceled via closed channel")
659 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700660 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700661
David Bainbridge103cf022019-12-16 20:11:35 +0000662 oltLogger.WithFields(log.Fields{
663 "oltId": o.ID,
664 "messageType": message.Type,
665 }).Trace("Received message")
666
667 switch message.Type {
668 case OltIndication:
669 msg, _ := message.Data.(OltIndicationMessage)
670 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530671 _ = o.InternalState.Event("enable")
672 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000673 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530674 _ = o.InternalState.Event("disable")
675 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000676 }
677 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800678 case AlarmIndication:
679 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
680 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000681 case NniIndication:
682 msg, _ := message.Data.(NniIndicationMessage)
683 o.sendNniIndication(msg, stream)
684 case PonIndication:
685 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530686 pon, _ := o.GetPonById(msg.PonPortID)
687 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530688 if err := pon.OperState.Event("enable"); err != nil {
689 oltLogger.WithFields(log.Fields{
690 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800691 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530692 }).Error("Can't Enable Oper state for PON Port")
693 }
694 if err := pon.InternalState.Event("enable"); err != nil {
695 oltLogger.WithFields(log.Fields{
696 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800697 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530698 }).Error("Can't Enable Internal state for PON Port")
699 }
Pragya Arya2225f202020-01-29 18:05:01 +0530700 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530701 if err := pon.OperState.Event("disable"); err != nil {
702 oltLogger.WithFields(log.Fields{
703 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800704 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530705 }).Error("Can't Disable Oper state for PON Port")
706 }
707 if err := pon.InternalState.Event("disable"); err != nil {
708 oltLogger.WithFields(log.Fields{
709 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800710 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530711 }).Error("Can't Disable Internal state for PON Port")
712 }
Pragya Arya2225f202020-01-29 18:05:01 +0530713 }
David Bainbridge103cf022019-12-16 20:11:35 +0000714 default:
715 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
716 }
717 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700718 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100719 wg.Done()
720 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700721}
722
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100723// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000724func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700725 oltLogger.WithFields(log.Fields{
726 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800727 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700728 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700729
David Bainbridge103cf022019-12-16 20:11:35 +0000730 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700731
David Bainbridge103cf022019-12-16 20:11:35 +0000732loop:
733 for {
734 select {
735 case <-ctx.Done():
736 oltLogger.Debug("NNI Indication processing canceled via context")
737 break loop
738 case message, ok := <-ch:
739 if !ok || ctx.Err() != nil {
740 oltLogger.Debug("NNI Indication processing canceled via channel closed")
741 break loop
742 }
743 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700744
David Bainbridge103cf022019-12-16 20:11:35 +0000745 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700746
David Bainbridge103cf022019-12-16 20:11:35 +0000747 if err != nil {
748 log.WithFields(log.Fields{
749 "IntfType": "nni",
750 "IntfId": nniId,
751 "Pkt": message.Pkt.Data(),
752 }).Error("Can't find Dst MacAddress in packet")
753 return
754 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700755
Matteo Scandolo4a036262020-08-17 15:56:13 -0700756 s, err := o.FindServiceByMacAddress(onuMac)
David Bainbridge103cf022019-12-16 20:11:35 +0000757 if err != nil {
758 log.WithFields(log.Fields{
759 "IntfType": "nni",
760 "IntfId": nniId,
761 "Pkt": message.Pkt.Data(),
762 "MacAddress": onuMac.String(),
763 }).Error("Can't find ONU with MacAddress")
764 return
765 }
766
Matteo Scandolo4a036262020-08-17 15:56:13 -0700767 service := s.(*Service)
768
769 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(service.STag, service.CTag, message.Pkt)
David Bainbridge103cf022019-12-16 20:11:35 +0000770 if err != nil {
771 log.Error("Fail to add double tag to packet")
772 }
773
774 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
775 IntfType: "nni",
776 IntfId: nniId,
777 Pkt: doubleTaggedPkt.Data()}}
778 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
779 oltLogger.WithFields(log.Fields{
780 "IntfType": data.PktInd.IntfType,
781 "IntfId": nniId,
782 "Pkt": doubleTaggedPkt.Data(),
783 }).Errorf("Fail to send PktInd indication: %v", err)
784 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700785 oltLogger.WithFields(log.Fields{
786 "IntfType": data.PktInd.IntfType,
787 "IntfId": nniId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700788 "Pkt": hex.EncodeToString(doubleTaggedPkt.Data()),
789 "OnuSn": service.Onu.Sn(),
790 }).Trace("Sent PktInd indication (from NNI to VOLTHA)")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700791 }
792 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100793 wg.Done()
794 oltLogger.WithFields(log.Fields{
795 "nniChannel": o.nniPktInChannel,
796 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700797}
798
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700799// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530800func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200801 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700802 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700803 for _, pon := range o.Pons {
804 for _, onu := range pon.Onus {
805 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700806 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700807 }
808 }
809 }
810
Shrey Baid688b4242020-07-10 20:40:10 +0530811 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700812}
813
William Kurkian9dadc5b2019-10-22 13:51:57 -0400814// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530815func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200816 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400817 // memoizing it will remove the bottleneck
818 for _, pon := range o.Pons {
819 if pon.ID == intfId {
820 for _, onu := range pon.Onus {
821 if onu.ID == onuId {
822 return onu, nil
823 }
824 }
825 }
826 }
Shrey Baid688b4242020-07-10 20:40:10 +0530827 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400828}
829
Matteo Scandolo4a036262020-08-17 15:56:13 -0700830// returns a Service with a given Mac Address
831func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200832 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700833 // memoizing it will remove the bottleneck
834 for _, pon := range o.Pons {
835 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700836 s, err := onu.findServiceByMacAddress(mac)
837 if err == nil {
838 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700839 }
840 }
841 }
842
Matteo Scandolo4a036262020-08-17 15:56:13 -0700843 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700844}
845
Matteo Scandolo4747d292019-08-05 11:50:18 -0700846// GRPC Endpoints
847
Shrey Baid688b4242020-07-10 20:40:10 +0530848func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700849 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700850 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700851 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530852 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700853
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700854 pon, _ := o.GetPonById(onu.IntfId)
855 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500856 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700857
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700858 if err := _onu.OperState.Event("enable"); err != nil {
859 oltLogger.WithFields(log.Fields{
860 "IntfId": _onu.PonPortID,
861 "OnuSn": _onu.Sn(),
862 "OnuId": _onu.ID,
863 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700864 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700865 if err := _onu.InternalState.Event("enable"); err != nil {
866 oltLogger.WithFields(log.Fields{
867 "IntfId": _onu.PonPortID,
868 "OnuSn": _onu.Sn(),
869 "OnuId": _onu.ID,
870 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
871 }
872
873 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
874
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700875 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700876}
877
Shrey Baid688b4242020-07-10 20:40:10 +0530878func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700879 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700880 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700881}
882
Shrey Baid688b4242020-07-10 20:40:10 +0530883func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530884 oltLogger.WithFields(log.Fields{
885 "IntfId": onu.IntfId,
886 "OnuId": onu.OnuId,
887 }).Info("Received DeleteOnu call from VOLTHA")
888
889 pon, err := o.GetPonById(onu.IntfId)
890 if err != nil {
891 oltLogger.WithFields(log.Fields{
892 "OnuId": onu.OnuId,
893 "IntfId": onu.IntfId,
894 "err": err,
895 }).Error("Can't find PonPort")
896 }
897 _onu, err := pon.GetOnuById(onu.OnuId)
898 if err != nil {
899 oltLogger.WithFields(log.Fields{
900 "OnuId": onu.OnuId,
901 "IntfId": onu.IntfId,
902 "err": err,
903 }).Error("Can't find Onu")
904 }
905
Hardik Windlassad790cb2020-06-17 21:26:22 +0530906 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530907 oltLogger.WithFields(log.Fields{
908 "IntfId": _onu.PonPortID,
909 "OnuSn": _onu.Sn(),
910 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530911 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
912 }
913
Hardik Windlassad790cb2020-06-17 21:26:22 +0530914 // ONU Re-Discovery
915 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530916 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530917 }
918
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700919 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700920}
921
Shrey Baid688b4242020-07-10 20:40:10 +0530922func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700923 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800924 oltLogger.WithFields(log.Fields{
925 "oltId": o.ID,
926 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530927 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800928
Matteo Scandolo401503a2019-12-11 14:48:14 -0800929 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530930 if pon.InternalState.Current() == "enabled" {
931 // disable PONs
932 msg := Message{
933 Type: PonIndication,
934 Data: PonIndicationMessage{
935 OperState: DOWN,
936 PonPortID: pon.ID,
937 },
938 }
939 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800940 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800941 }
942
Matteo Scandolo401503a2019-12-11 14:48:14 -0800943 // Note that we are not disabling the NNI as the real OLT does not.
944 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800945
946 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100947 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700948 Type: OltIndication,
949 Data: OltIndicationMessage{
950 OperState: DOWN,
951 },
952 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100953 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700954 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700955}
956
Shrey Baid688b4242020-07-10 20:40:10 +0530957func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530958 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200959 ponID := intf.GetIntfId()
960 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200961
962 msg := Message{
963 Type: PonIndication,
964 Data: PonIndicationMessage{
965 OperState: DOWN,
966 PonPortID: ponID,
967 },
968 }
969 o.channel <- msg
970
971 for _, onu := range pon.Onus {
972
973 onuIndication := OnuIndicationMessage{
974 OperState: DOWN,
975 PonPortID: ponID,
976 OnuID: onu.ID,
977 OnuSN: onu.SerialNumber,
978 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700979 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200980
981 }
982
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700983 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700984}
985
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100986func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700987 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530988 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700989 o.Enable(stream)
990 return nil
991}
992
Shrey Baid688b4242020-07-10 20:40:10 +0530993func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530994 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530995 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200996 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200997
Pragya Arya2225f202020-01-29 18:05:01 +0530998 msg := Message{
999 Type: PonIndication,
1000 Data: PonIndicationMessage{
1001 OperState: UP,
1002 PonPortID: ponID,
1003 },
1004 }
1005 o.channel <- msg
1006
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001007 for _, onu := range pon.Onus {
1008
1009 onuIndication := OnuIndicationMessage{
1010 OperState: UP,
1011 PonPortID: ponID,
1012 OnuID: onu.ID,
1013 OnuSN: onu.SerialNumber,
1014 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001015 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001016
1017 }
1018
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001019 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001020}
1021
Shrey Baid688b4242020-07-10 20:40:10 +05301022func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001023 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001024 "IntfId": flow.AccessIntfId,
1025 "OnuId": flow.OnuId,
1026 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001027 "InnerVlan": flow.Classifier.IVid,
1028 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001029 "FlowType": flow.FlowType,
1030 "FlowId": flow.FlowId,
1031 "UniID": flow.UniId,
1032 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301033 }).Tracef("OLT receives FlowAdd")
1034
1035 flowKey := FlowKey{}
1036 if !o.enablePerf {
1037 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
1038 olt.Flows[flowKey] = *flow
1039 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001040
1041 if flow.AccessIntfId == -1 {
1042 oltLogger.WithFields(log.Fields{
1043 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001044 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001045 } else if flow.FlowType == "multicast" {
1046 oltLogger.WithFields(log.Fields{
1047 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001048 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001049 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001050 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001051 if err != nil {
1052 oltLogger.WithFields(log.Fields{
1053 "OnuId": flow.OnuId,
1054 "IntfId": flow.AccessIntfId,
1055 "err": err,
1056 }).Error("Can't find PonPort")
1057 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001058 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001059 if err != nil {
1060 oltLogger.WithFields(log.Fields{
1061 "OnuId": flow.OnuId,
1062 "IntfId": flow.AccessIntfId,
1063 "err": err,
1064 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001065 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001066 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301067 if !o.enablePerf {
1068 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301069 // Generate event on first flow for ONU
1070 if len(onu.Flows) == 1 {
1071 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1072 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301073 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001074
1075 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001076 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001077 Data: OnuFlowUpdateMessage{
1078 PonPortID: pon.ID,
1079 OnuID: onu.ID,
1080 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001081 },
1082 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001083 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001084 }
1085
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001086 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001087}
1088
Pragya Arya8bdb4532020-03-02 17:08:09 +05301089// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301090func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001091
Pragya Arya8bdb4532020-03-02 17:08:09 +05301092 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301093 "FlowId": flow.FlowId,
1094 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001095 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301096
1097 if !o.enablePerf { // remove only if flow were stored
1098 flowKey := FlowKey{
1099 ID: flow.FlowId,
1100 Direction: flow.FlowType,
1101 }
1102
1103 // Check if flow exists
1104 storedFlow, ok := o.Flows[flowKey]
1105 if !ok {
1106 oltLogger.Errorf("Flow %v not found", flow)
1107 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1108 }
1109
1110 // if its ONU flow remove it from ONU also
1111 if storedFlow.AccessIntfId != -1 {
1112 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1113 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1114 if err != nil {
1115 oltLogger.WithFields(log.Fields{
1116 "OnuId": storedFlow.OnuId,
1117 "IntfId": storedFlow.AccessIntfId,
1118 "err": err,
1119 }).Error("ONU not found")
1120 return new(openolt.Empty), nil
1121 }
1122 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301123 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301124 }
1125
1126 // delete from olt flows
1127 delete(o.Flows, flowKey)
1128 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001129
1130 if flow.AccessIntfId == -1 {
1131 oltLogger.WithFields(log.Fields{
1132 "FlowId": flow.FlowId,
1133 }).Debug("Removing OLT flow")
1134 } else if flow.FlowType == "multicast" {
1135 oltLogger.WithFields(log.Fields{
1136 "FlowId": flow.FlowId,
1137 }).Debug("Removing OLT multicast flow")
1138 } else {
1139
1140 onu, err := o.GetOnuByFlowId(flow.FlowId)
1141 if err != nil {
1142 oltLogger.WithFields(log.Fields{
1143 "OnuId": flow.OnuId,
1144 "IntfId": flow.AccessIntfId,
1145 "err": err,
1146 }).Error("Can't find Onu")
1147 return nil, err
1148 }
1149
1150 msg := Message{
1151 Type: FlowRemoved,
1152 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301153 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001154 },
1155 }
1156 onu.Channel <- msg
1157 }
1158
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001159 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001160}
1161
Shrey Baid688b4242020-07-10 20:40:10 +05301162func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001163 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1164 oltLogger.WithFields(log.Fields{
1165 "signature": res.HeartbeatSignature,
1166 }).Trace("HeartbeatCheck")
1167 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001168}
1169
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001170func (o *OltDevice) GetOnuByFlowId(flowId uint32) (*Onu, error) {
1171 for _, pon := range o.Pons {
1172 for _, onu := range pon.Onus {
1173 for _, fId := range onu.FlowIds {
1174 if fId == flowId {
1175 return onu, nil
1176 }
1177 }
1178 }
1179 }
Shrey Baid688b4242020-07-10 20:40:10 +05301180 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001181}
1182
Shrey Baid688b4242020-07-10 20:40:10 +05301183func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001184
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001185 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001186 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001187 "PonPorts": o.NumPon,
1188 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001189 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001190 devinfo.Vendor = common.Config.Olt.Vendor
1191 devinfo.Model = common.Config.Olt.Model
1192 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1193 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1194 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001195 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001196 devinfo.OnuIdStart = 1
1197 devinfo.OnuIdEnd = 255
1198 devinfo.AllocIdStart = 1024
1199 devinfo.AllocIdEnd = 16383
1200 devinfo.GemportIdStart = 1024
1201 devinfo.GemportIdEnd = 65535
1202 devinfo.FlowIdStart = 1
1203 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001204 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001205 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001206
1207 return devinfo, nil
1208}
1209
Shrey Baid688b4242020-07-10 20:40:10 +05301210func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001211 pon, err := o.GetPonById(omci_msg.IntfId)
1212 if err != nil {
1213 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001214 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001215 "onu_id": omci_msg.OnuId,
1216 "pon_id": omci_msg.IntfId,
1217 }).Error("pon ID not found")
1218 return nil, err
1219 }
1220
1221 onu, err := pon.GetOnuById(omci_msg.OnuId)
1222 if err != nil {
1223 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001224 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001225 "onu_id": omci_msg.OnuId,
1226 "pon_id": omci_msg.IntfId,
1227 }).Error("onu ID not found")
1228 return nil, err
1229 }
1230
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001231 oltLogger.WithFields(log.Fields{
1232 "IntfId": onu.PonPortID,
1233 "OnuId": onu.ID,
1234 "OnuSn": onu.Sn(),
1235 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001236 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001237 Type: OMCI,
1238 Data: OmciMessage{
1239 OnuSN: onu.SerialNumber,
1240 OnuID: onu.ID,
1241 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001242 },
1243 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001244 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001245 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001246}
1247
Shrey Baid688b4242020-07-10 20:40:10 +05301248func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001249 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001250 if err != nil {
1251 oltLogger.WithFields(log.Fields{
1252 "OnuId": onuPkt.OnuId,
1253 "IntfId": onuPkt.IntfId,
1254 "err": err,
1255 }).Error("Can't find PonPort")
1256 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001257 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001258 if err != nil {
1259 oltLogger.WithFields(log.Fields{
1260 "OnuId": onuPkt.OnuId,
1261 "IntfId": onuPkt.IntfId,
1262 "err": err,
1263 }).Error("Can't find Onu")
1264 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001265
Matteo Scandolo075b1892019-10-07 12:11:07 -07001266 oltLogger.WithFields(log.Fields{
1267 "IntfId": onu.PonPortID,
1268 "OnuId": onu.ID,
1269 "OnuSn": onu.Sn(),
Matteo Scandolo75ed5b92020-09-03 09:03:16 -07001270 }).Trace("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001271
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001272 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Shrey Baid688b4242020-07-10 20:40:10 +05301273 pktType, _ := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001274
Matteo Scandolo4a036262020-08-17 15:56:13 -07001275 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
1276
1277 if err != nil {
1278 log.WithFields(log.Fields{
1279 "IntfId": onu.PonPortID,
1280 "OnuId": onu.ID,
1281 "OnuSn": onu.Sn(),
1282 "Pkt": rawpkt.Data(),
1283 }).Error("Can't find Dst MacAddress in packet, droppint it")
1284 return new(openolt.Empty), nil
1285 }
1286
Matteo Scandolo075b1892019-10-07 12:11:07 -07001287 msg := Message{
1288 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001289 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001290 IntfId: onuPkt.IntfId,
1291 OnuId: onuPkt.OnuId,
1292 Packet: rawpkt,
1293 Type: pktType,
1294 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001295 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001296 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001297
Matteo Scandolo075b1892019-10-07 12:11:07 -07001298 onu.Channel <- msg
1299
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001300 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001301}
1302
Shrey Baid688b4242020-07-10 20:40:10 +05301303func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001304 oltLogger.WithFields(log.Fields{
1305 "oltId": o.ID,
1306 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301307 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301308 go func() { _ = o.RestartOLT() }()
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) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301313 oltLogger.WithFields(log.Fields{
1314 "oltId": o.ID,
1315 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301316 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301317
Pragya Arya2225f202020-01-29 18:05:01 +05301318 // enable OLT
1319 oltMsg := Message{
1320 Type: OltIndication,
1321 Data: OltIndicationMessage{
1322 OperState: UP,
1323 },
Pragya Arya1881df02020-01-29 18:05:01 +05301324 }
Pragya Arya2225f202020-01-29 18:05:01 +05301325 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301326
Pragya Arya2225f202020-01-29 18:05:01 +05301327 for _, pon := range o.Pons {
1328 if pon.InternalState.Current() == "disabled" {
1329 msg := Message{
1330 Type: PonIndication,
1331 Data: PonIndicationMessage{
1332 OperState: UP,
1333 PonPortID: pon.ID,
1334 },
1335 }
1336 o.channel <- msg
1337 }
1338 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001339
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001340 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001341}
1342
Shrey Baid688b4242020-07-10 20:40:10 +05301343func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001344 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1345
Shrey Baid688b4242020-07-10 20:40:10 +05301346 _ = o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001347 // NOTE should we return an error if sendNniPakcet fails?
1348 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001349}
1350
Shrey Baid688b4242020-07-10 20:40:10 +05301351func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001352 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001353 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001354}
1355
Shrey Baid688b4242020-07-10 20:40:10 +05301356func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001357 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001358 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001359}
1360
Shrey Baid688b4242020-07-10 20:40:10 +05301361func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001362 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001363 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001364}
1365
Shrey Baid688b4242020-07-10 20:40:10 +05301366func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001367 oltLogger.Info("received CreateTrafficQueues")
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) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001372 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001373 return new(openolt.Empty), nil
1374}
1375
Shrey Baid688b4242020-07-10 20:40:10 +05301376func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301377 oltLogger.WithFields(log.Fields{
1378 "OnuId": trafficSchedulers.OnuId,
1379 "IntfId": trafficSchedulers.IntfId,
1380 "OnuPortNo": trafficSchedulers.PortNo,
1381 }).Info("received CreateTrafficSchedulers")
1382
1383 if !s.enablePerf {
1384 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1385 if err != nil {
1386 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1387 return new(openolt.Empty), err
1388 }
1389 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1390 if err != nil {
1391 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1392 return new(openolt.Empty), err
1393 }
1394 onu.TrafficSchedulers = trafficSchedulers
1395 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001396 return new(openolt.Empty), nil
1397}
1398
Shrey Baid688b4242020-07-10 20:40:10 +05301399func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301400 oltLogger.WithFields(log.Fields{
1401 "OnuId": trafficSchedulers.OnuId,
1402 "IntfId": trafficSchedulers.IntfId,
1403 "OnuPortNo": trafficSchedulers.PortNo,
1404 }).Info("received RemoveTrafficSchedulers")
1405 if !s.enablePerf {
1406 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1407 if err != nil {
1408 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1409 return new(openolt.Empty), err
1410 }
1411 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1412 if err != nil {
1413 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1414 return new(openolt.Empty), err
1415 }
1416
1417 onu.TrafficSchedulers = nil
1418 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001419 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001420}
Scott Baker41724b82020-01-21 19:54:53 -08001421
1422// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301423func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001424 msg := Message{
1425 Type: AlarmIndication,
1426 Data: ind,
1427 }
1428
1429 o.channel <- msg
1430 return nil
1431}