blob: eff9c867f662d8b42050b0a36f5bc42bc1749b4a [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
Pragya Arya2225f202020-01-29 18:05:01 +0530280 for _, pon := range olt.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 for _, onu := range pon.Onus {
291 if onu.InternalState.Current() != "initialized" {
Shrey Baid688b4242020-07-10 20:40:10 +0530292 _ = onu.InternalState.Event("disable")
Pragya Arya2225f202020-01-29 18:05:01 +0530293 }
294 }
295 }
296
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100297 // terminate the OLT's processOltMessages go routine
298 close(o.channel)
299 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700300 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100301 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100302
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100303 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100304
305 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800306 oltLogger.WithFields(log.Fields{
307 "oltId": o.ID,
308 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100309 return err
310 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800311 oltLogger.WithFields(log.Fields{
312 "oltId": o.ID,
313 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100314 return nil
315}
316
317// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800318func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700319 address := common.Config.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700320 lis, err := net.Listen("tcp", address)
321 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700322 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700323 }
324 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100325
Matteo Scandolo4747d292019-08-05 11:50:18 -0700326 openolt.RegisterOpenoltServer(grpcServer, o)
327
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100328 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700329
Shrey Baid688b4242020-07-10 20:40:10 +0530330 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100331 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100333 return grpcServer, nil
334}
335
336// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800337func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100338 // TODO handle poweroff vs graceful shutdown
339 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800340 oltLogger.WithFields(log.Fields{
341 "oltId": o.SerialNumber,
342 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100343 oltServer.Stop()
344 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700345 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800346
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347 return nil
348}
349
350// Device Methods
351
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100352// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530353func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700354 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530355 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700356
David Bainbridge103cf022019-12-16 20:11:35 +0000357 // If enabled has already been called then an enabled context has
358 // been created. If this is the case then we want to cancel all the
359 // proessing loops associated with that enable before we recreate
360 // new ones
361 o.Lock()
362 if o.enableContext != nil && o.enableContextCancel != nil {
363 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530364 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000365 }
366 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
367 o.Unlock()
368
Matteo Scandolo4747d292019-08-05 11:50:18 -0700369 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800370 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700371
Matteo Scandolo4a036262020-08-17 15:56:13 -0700372 o.OpenoltStream = stream
Pragya Arya1cbefa42020-01-13 12:15:29 +0530373
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100374 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000375 go o.processOltMessages(o.enableContext, stream, &wg)
376 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700377
378 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100379 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700380 Type: OltIndication,
381 Data: OltIndicationMessage{
382 OperState: UP,
383 },
384 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100385 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700386
387 // send NNI Port Indications
388 for _, nni := range o.Nnis {
389 msg := Message{
390 Type: NniIndication,
391 Data: NniIndicationMessage{
392 OperState: UP,
393 NniPortID: nni.ID,
394 },
395 }
396 o.channel <- msg
397 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100398
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800399 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100400
Shrey Baid688b4242020-07-10 20:40:10 +0530401 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530402 for _, pon := range o.Pons {
403 if pon.InternalState.Current() == "disabled" {
404 msg := Message{
405 Type: PonIndication,
406 Data: PonIndicationMessage{
407 OperState: UP,
408 PonPortID: pon.ID,
409 },
410 }
411 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000412 }
Pragya Arya2225f202020-01-29 18:05:01 +0530413 }
414 } else {
415
416 // 1. controlledActivation == Default: Send both PON and ONUs indications
417 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
418
419 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
420 // send PON Port indications
421 for _, pon := range o.Pons {
422 msg := Message{
423 Type: PonIndication,
424 Data: PonIndicationMessage{
425 OperState: UP,
426 PonPortID: pon.ID,
427 },
428 }
429 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700430 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431 }
432 }
433
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800434 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530435
436 if !o.enablePerf {
437 // Start a go routine to send periodic port stats to openolt adapter
438 go o.periodicPortStats(o.enableContext)
439 }
440
Matteo Scandolo4747d292019-08-05 11:50:18 -0700441 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700442}
443
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800444func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400445 ch := omcisim.GetChannel()
446
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100447 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400448
David Bainbridge103cf022019-12-16 20:11:35 +0000449loop:
450 for {
451 select {
452 case <-ctx.Done():
453 oltLogger.Debug("OMCI processing canceled via context")
454 break loop
455 case message, ok := <-ch:
456 if !ok || ctx.Err() != nil {
457 oltLogger.Debug("OMCI processing canceled via channel close")
458 break loop
459 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800460
461 oltLogger.WithFields(log.Fields{
462 "messageType": message.Type,
463 "OnuId": message.Data.OnuId,
464 "IntfId": message.Data.IntfId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700465 }).Debug("Received message on OMCI Sim channel")
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800466
David Bainbridge103cf022019-12-16 20:11:35 +0000467 onuId := message.Data.OnuId
468 intfId := message.Data.IntfId
469 onu, err := o.FindOnuById(intfId, onuId)
470 if err != nil {
471 oltLogger.Errorf("Failed to find onu: %v", err)
472 continue
473 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800474 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400475 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400476 }
David Bainbridge103cf022019-12-16 20:11:35 +0000477
478 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400479}
480
Pragya Arya996a0892020-03-09 21:47:52 +0530481func (o *OltDevice) periodicPortStats(ctx context.Context) {
482 var portStats *openolt.PortStatistics
483 for {
484 select {
485 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
486 // send NNI port stats
487 for _, port := range o.Nnis {
488 incrementStat := true
489 if port.OperState.Current() == "down" {
490 incrementStat = false
491 }
492 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
493 o.sendPortStatsIndication(portStats, port.ID, port.Type)
494 }
495
496 // send PON port stats
497 for _, port := range o.Pons {
498 incrementStat := true
499 // do not increment port stats if PON port is down or no ONU is activated on PON port
500 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
501 incrementStat = false
502 }
503 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
504 o.sendPortStatsIndication(portStats, port.ID, port.Type)
505 }
506 case <-ctx.Done():
507 log.Debug("Stop sending port stats")
508 return
509 }
510
511 }
512}
513
Matteo Scandolo4747d292019-08-05 11:50:18 -0700514// Helpers method
515
Shrey Baid688b4242020-07-10 20:40:10 +0530516func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700517 for _, pon := range o.Pons {
518 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700519 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700520 }
521 }
Shrey Baid688b4242020-07-10 20:40:10 +0530522 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700523}
524
Shrey Baid688b4242020-07-10 20:40:10 +0530525func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700526 for _, nni := range o.Nnis {
527 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700528 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700529 }
530 }
Shrey Baid688b4242020-07-10 20:40:10 +0530531 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700532}
533
Scott Baker41724b82020-01-21 19:54:53 -0800534func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
535 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
536 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
537 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
538 return
539 }
540
541 oltLogger.WithFields(log.Fields{
542 "AlarmIndication": alarmInd,
543 }).Debug("Sent Indication_AlarmInd")
544}
545
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100546func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
548 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700549 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800550 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700551 }
552
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700553 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700554 "OperState": msg.OperState,
555 }).Debug("Sent Indication_OltInd")
556}
557
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100558func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700559 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800560 if msg.OperState == UP {
561 if err := nni.OperState.Event("enable"); 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 enabled state: %v", err)
567 }
568 } else if msg.OperState == DOWN {
569 if err := nni.OperState.Event("disable"); 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 disable state: %v", err)
575 }
576 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700577 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700579 Type: nni.Type,
580 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700581 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582 }}
583
584 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700585 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800586 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587 }
588
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700589 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700590 "Type": nni.Type,
591 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700592 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700593 }).Debug("Sent Indication_IntfOperInd for NNI")
594}
595
Pragya Arya2225f202020-01-29 18:05:01 +0530596func (o *OltDevice) sendPonIndication(ponPortID uint32) {
597
Matteo Scandolo4a036262020-08-17 15:56:13 -0700598 stream := o.OpenoltStream
Pragya Arya2225f202020-01-29 18:05:01 +0530599 pon, _ := o.GetPonById(ponPortID)
600 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700602 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700603 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700604 }}
605
606 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700607 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800608 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700609 }
610
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700611 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700612 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700613 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700614 }).Debug("Sent Indication_IntfInd")
615
Pragya Arya2225f202020-01-29 18:05:01 +0530616 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700618 Type: pon.Type,
619 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700620 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700621 }}
622
623 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700624 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800625 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700626 }
627
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700628 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700629 "Type": pon.Type,
630 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700631 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700632 }).Debug("Sent Indication_IntfOperInd for PON")
633}
634
Pragya Arya996a0892020-03-09 21:47:52 +0530635func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530636 if o.InternalState.Current() == "enabled" {
637 oltLogger.WithFields(log.Fields{
638 "Type": portType,
639 "IntfId": portID,
640 }).Trace("Sending port stats")
641 stats.IntfId = InterfaceIDToPortNo(portID, portType)
642 data := &openolt.Indication_PortStats{
643 PortStats: stats,
644 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700645 stream := o.OpenoltStream
Shrey Baid55f328c2020-07-07 19:20:42 +0530646 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
647 oltLogger.Errorf("Failed to send PortStats: %v", err)
648 return
649 }
Pragya Arya996a0892020-03-09 21:47:52 +0530650 }
651}
652
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100653// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000654func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100655 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000656 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700657
David Bainbridge103cf022019-12-16 20:11:35 +0000658loop:
659 for {
660 select {
661 case <-ctx.Done():
662 oltLogger.Debug("OLT Indication processing canceled via context")
663 break loop
664 case message, ok := <-ch:
665 if !ok || ctx.Err() != nil {
666 oltLogger.Debug("OLT Indication processing canceled via closed channel")
667 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700668 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669
David Bainbridge103cf022019-12-16 20:11:35 +0000670 oltLogger.WithFields(log.Fields{
671 "oltId": o.ID,
672 "messageType": message.Type,
673 }).Trace("Received message")
674
675 switch message.Type {
676 case OltIndication:
677 msg, _ := message.Data.(OltIndicationMessage)
678 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530679 _ = o.InternalState.Event("enable")
680 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000681 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530682 _ = o.InternalState.Event("disable")
683 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000684 }
685 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800686 case AlarmIndication:
687 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
688 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000689 case NniIndication:
690 msg, _ := message.Data.(NniIndicationMessage)
691 o.sendNniIndication(msg, stream)
692 case PonIndication:
693 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530694 pon, _ := o.GetPonById(msg.PonPortID)
695 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530696 if err := pon.OperState.Event("enable"); err != nil {
697 oltLogger.WithFields(log.Fields{
698 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800699 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530700 }).Error("Can't Enable Oper state for PON Port")
701 }
702 if err := pon.InternalState.Event("enable"); err != nil {
703 oltLogger.WithFields(log.Fields{
704 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800705 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530706 }).Error("Can't Enable Internal state for PON Port")
707 }
Pragya Arya2225f202020-01-29 18:05:01 +0530708 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530709 if err := pon.OperState.Event("disable"); err != nil {
710 oltLogger.WithFields(log.Fields{
711 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800712 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530713 }).Error("Can't Disable Oper state for PON Port")
714 }
715 if err := pon.InternalState.Event("disable"); err != nil {
716 oltLogger.WithFields(log.Fields{
717 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800718 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530719 }).Error("Can't Disable Internal state for PON Port")
720 }
Pragya Arya2225f202020-01-29 18:05:01 +0530721 }
David Bainbridge103cf022019-12-16 20:11:35 +0000722 default:
723 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
724 }
725 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700726 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100727 wg.Done()
728 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700729}
730
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100731// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000732func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700733 oltLogger.WithFields(log.Fields{
734 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800735 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700736 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700737
David Bainbridge103cf022019-12-16 20:11:35 +0000738 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700739
David Bainbridge103cf022019-12-16 20:11:35 +0000740loop:
741 for {
742 select {
743 case <-ctx.Done():
744 oltLogger.Debug("NNI Indication processing canceled via context")
745 break loop
746 case message, ok := <-ch:
747 if !ok || ctx.Err() != nil {
748 oltLogger.Debug("NNI Indication processing canceled via channel closed")
749 break loop
750 }
751 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700752
David Bainbridge103cf022019-12-16 20:11:35 +0000753 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700754
David Bainbridge103cf022019-12-16 20:11:35 +0000755 if err != nil {
756 log.WithFields(log.Fields{
757 "IntfType": "nni",
758 "IntfId": nniId,
759 "Pkt": message.Pkt.Data(),
760 }).Error("Can't find Dst MacAddress in packet")
761 return
762 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700763
Matteo Scandolo4a036262020-08-17 15:56:13 -0700764 s, err := o.FindServiceByMacAddress(onuMac)
David Bainbridge103cf022019-12-16 20:11:35 +0000765 if err != nil {
766 log.WithFields(log.Fields{
767 "IntfType": "nni",
768 "IntfId": nniId,
769 "Pkt": message.Pkt.Data(),
770 "MacAddress": onuMac.String(),
771 }).Error("Can't find ONU with MacAddress")
772 return
773 }
774
Matteo Scandolo4a036262020-08-17 15:56:13 -0700775 service := s.(*Service)
776
777 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(service.STag, service.CTag, message.Pkt)
David Bainbridge103cf022019-12-16 20:11:35 +0000778 if err != nil {
779 log.Error("Fail to add double tag to packet")
780 }
781
782 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
783 IntfType: "nni",
784 IntfId: nniId,
785 Pkt: doubleTaggedPkt.Data()}}
786 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
787 oltLogger.WithFields(log.Fields{
788 "IntfType": data.PktInd.IntfType,
789 "IntfId": nniId,
790 "Pkt": doubleTaggedPkt.Data(),
791 }).Errorf("Fail to send PktInd indication: %v", err)
792 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700793 oltLogger.WithFields(log.Fields{
794 "IntfType": data.PktInd.IntfType,
795 "IntfId": nniId,
Matteo Scandolo4a036262020-08-17 15:56:13 -0700796 "Pkt": hex.EncodeToString(doubleTaggedPkt.Data()),
797 "OnuSn": service.Onu.Sn(),
798 }).Trace("Sent PktInd indication (from NNI to VOLTHA)")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700799 }
800 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100801 wg.Done()
802 oltLogger.WithFields(log.Fields{
803 "nniChannel": o.nniPktInChannel,
804 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700805}
806
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700807// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530808func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200809 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700810 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700811 for _, pon := range o.Pons {
812 for _, onu := range pon.Onus {
813 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700814 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700815 }
816 }
817 }
818
Shrey Baid688b4242020-07-10 20:40:10 +0530819 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700820}
821
William Kurkian9dadc5b2019-10-22 13:51:57 -0400822// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530823func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200824 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400825 // memoizing it will remove the bottleneck
826 for _, pon := range o.Pons {
827 if pon.ID == intfId {
828 for _, onu := range pon.Onus {
829 if onu.ID == onuId {
830 return onu, nil
831 }
832 }
833 }
834 }
Shrey Baid688b4242020-07-10 20:40:10 +0530835 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400836}
837
Matteo Scandolo4a036262020-08-17 15:56:13 -0700838// returns a Service with a given Mac Address
839func (o *OltDevice) FindServiceByMacAddress(mac net.HardwareAddr) (ServiceIf, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200840 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700841 // memoizing it will remove the bottleneck
842 for _, pon := range o.Pons {
843 for _, onu := range pon.Onus {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700844 s, err := onu.findServiceByMacAddress(mac)
845 if err == nil {
846 return s, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700847 }
848 }
849 }
850
Matteo Scandolo4a036262020-08-17 15:56:13 -0700851 return nil, fmt.Errorf("cannot-find-service-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700852}
853
Matteo Scandolo4747d292019-08-05 11:50:18 -0700854// GRPC Endpoints
855
Shrey Baid688b4242020-07-10 20:40:10 +0530856func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700857 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700858 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700859 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530860 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700861
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700862 pon, _ := o.GetPonById(onu.IntfId)
863 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500864 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700865
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700866 if err := _onu.OperState.Event("enable"); err != nil {
867 oltLogger.WithFields(log.Fields{
868 "IntfId": _onu.PonPortID,
869 "OnuSn": _onu.Sn(),
870 "OnuId": _onu.ID,
871 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700872 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700873 if err := _onu.InternalState.Event("enable"); err != nil {
874 oltLogger.WithFields(log.Fields{
875 "IntfId": _onu.PonPortID,
876 "OnuSn": _onu.Sn(),
877 "OnuId": _onu.ID,
878 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
879 }
880
881 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
882
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700883 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700884}
885
Shrey Baid688b4242020-07-10 20:40:10 +0530886func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700887 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700888 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700889}
890
Shrey Baid688b4242020-07-10 20:40:10 +0530891func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530892 oltLogger.WithFields(log.Fields{
893 "IntfId": onu.IntfId,
894 "OnuId": onu.OnuId,
895 }).Info("Received DeleteOnu call from VOLTHA")
896
897 pon, err := o.GetPonById(onu.IntfId)
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 PonPort")
904 }
905 _onu, err := pon.GetOnuById(onu.OnuId)
906 if err != nil {
907 oltLogger.WithFields(log.Fields{
908 "OnuId": onu.OnuId,
909 "IntfId": onu.IntfId,
910 "err": err,
911 }).Error("Can't find Onu")
912 }
913
Hardik Windlassad790cb2020-06-17 21:26:22 +0530914 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530915 oltLogger.WithFields(log.Fields{
916 "IntfId": _onu.PonPortID,
917 "OnuSn": _onu.Sn(),
918 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530919 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
920 }
921
Hardik Windlassad790cb2020-06-17 21:26:22 +0530922 // ONU Re-Discovery
923 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530924 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530925 }
926
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700927 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700928}
929
Shrey Baid688b4242020-07-10 20:40:10 +0530930func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700931 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800932 oltLogger.WithFields(log.Fields{
933 "oltId": o.ID,
934 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530935 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800936
Matteo Scandolo401503a2019-12-11 14:48:14 -0800937 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530938 if pon.InternalState.Current() == "enabled" {
939 // disable PONs
940 msg := Message{
941 Type: PonIndication,
942 Data: PonIndicationMessage{
943 OperState: DOWN,
944 PonPortID: pon.ID,
945 },
946 }
947 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800948 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800949 }
950
Matteo Scandolo401503a2019-12-11 14:48:14 -0800951 // Note that we are not disabling the NNI as the real OLT does not.
952 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800953
954 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100955 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700956 Type: OltIndication,
957 Data: OltIndicationMessage{
958 OperState: DOWN,
959 },
960 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100961 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700962 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700963}
964
Shrey Baid688b4242020-07-10 20:40:10 +0530965func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530966 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200967 ponID := intf.GetIntfId()
968 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200969
970 msg := Message{
971 Type: PonIndication,
972 Data: PonIndicationMessage{
973 OperState: DOWN,
974 PonPortID: ponID,
975 },
976 }
977 o.channel <- msg
978
979 for _, onu := range pon.Onus {
980
981 onuIndication := OnuIndicationMessage{
982 OperState: DOWN,
983 PonPortID: ponID,
984 OnuID: onu.ID,
985 OnuSN: onu.SerialNumber,
986 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700987 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200988
989 }
990
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700991 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700992}
993
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100994func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700995 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530996 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700997 o.Enable(stream)
998 return nil
999}
1000
Shrey Baid688b4242020-07-10 20:40:10 +05301001func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +05301002 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +05301003 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001004 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001005
Pragya Arya2225f202020-01-29 18:05:01 +05301006 msg := Message{
1007 Type: PonIndication,
1008 Data: PonIndicationMessage{
1009 OperState: UP,
1010 PonPortID: ponID,
1011 },
1012 }
1013 o.channel <- msg
1014
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001015 for _, onu := range pon.Onus {
1016
1017 onuIndication := OnuIndicationMessage{
1018 OperState: UP,
1019 PonPortID: ponID,
1020 OnuID: onu.ID,
1021 OnuSN: onu.SerialNumber,
1022 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001023 onu.sendOnuIndication(onuIndication, o.OpenoltStream)
Andrea Campanella340b9ea2020-04-28 18:34:01 +02001024
1025 }
1026
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001027 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001028}
1029
Shrey Baid688b4242020-07-10 20:40:10 +05301030func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001031 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001032 "IntfId": flow.AccessIntfId,
1033 "OnuId": flow.OnuId,
1034 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001035 "InnerVlan": flow.Classifier.IVid,
1036 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001037 "FlowType": flow.FlowType,
1038 "FlowId": flow.FlowId,
1039 "UniID": flow.UniId,
1040 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301041 }).Tracef("OLT receives FlowAdd")
1042
1043 flowKey := FlowKey{}
1044 if !o.enablePerf {
1045 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
1046 olt.Flows[flowKey] = *flow
1047 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001048
1049 if flow.AccessIntfId == -1 {
1050 oltLogger.WithFields(log.Fields{
1051 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001052 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001053 } else if flow.FlowType == "multicast" {
1054 oltLogger.WithFields(log.Fields{
1055 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001056 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001057 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001058 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
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 PonPort")
1065 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001066 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001067 if err != nil {
1068 oltLogger.WithFields(log.Fields{
1069 "OnuId": flow.OnuId,
1070 "IntfId": flow.AccessIntfId,
1071 "err": err,
1072 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001073 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001074 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301075 if !o.enablePerf {
1076 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301077 // Generate event on first flow for ONU
1078 if len(onu.Flows) == 1 {
1079 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1080 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301081 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001082
1083 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001084 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001085 Data: OnuFlowUpdateMessage{
1086 PonPortID: pon.ID,
1087 OnuID: onu.ID,
1088 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001089 },
1090 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001091 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001092 }
1093
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001094 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001095}
1096
Pragya Arya8bdb4532020-03-02 17:08:09 +05301097// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301098func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001099
Pragya Arya8bdb4532020-03-02 17:08:09 +05301100 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301101 "FlowId": flow.FlowId,
1102 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001103 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301104
1105 if !o.enablePerf { // remove only if flow were stored
1106 flowKey := FlowKey{
1107 ID: flow.FlowId,
1108 Direction: flow.FlowType,
1109 }
1110
1111 // Check if flow exists
1112 storedFlow, ok := o.Flows[flowKey]
1113 if !ok {
1114 oltLogger.Errorf("Flow %v not found", flow)
1115 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1116 }
1117
1118 // if its ONU flow remove it from ONU also
1119 if storedFlow.AccessIntfId != -1 {
1120 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1121 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1122 if err != nil {
1123 oltLogger.WithFields(log.Fields{
1124 "OnuId": storedFlow.OnuId,
1125 "IntfId": storedFlow.AccessIntfId,
1126 "err": err,
1127 }).Error("ONU not found")
1128 return new(openolt.Empty), nil
1129 }
1130 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301131 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301132 }
1133
1134 // delete from olt flows
1135 delete(o.Flows, flowKey)
1136 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001137
1138 if flow.AccessIntfId == -1 {
1139 oltLogger.WithFields(log.Fields{
1140 "FlowId": flow.FlowId,
1141 }).Debug("Removing OLT flow")
1142 } else if flow.FlowType == "multicast" {
1143 oltLogger.WithFields(log.Fields{
1144 "FlowId": flow.FlowId,
1145 }).Debug("Removing OLT multicast flow")
1146 } else {
1147
1148 onu, err := o.GetOnuByFlowId(flow.FlowId)
1149 if err != nil {
1150 oltLogger.WithFields(log.Fields{
1151 "OnuId": flow.OnuId,
1152 "IntfId": flow.AccessIntfId,
1153 "err": err,
1154 }).Error("Can't find Onu")
1155 return nil, err
1156 }
1157
1158 msg := Message{
1159 Type: FlowRemoved,
1160 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301161 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001162 },
1163 }
1164 onu.Channel <- msg
1165 }
1166
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001167 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001168}
1169
Shrey Baid688b4242020-07-10 20:40:10 +05301170func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001171 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1172 oltLogger.WithFields(log.Fields{
1173 "signature": res.HeartbeatSignature,
1174 }).Trace("HeartbeatCheck")
1175 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001176}
1177
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001178func (o *OltDevice) GetOnuByFlowId(flowId uint32) (*Onu, error) {
1179 for _, pon := range o.Pons {
1180 for _, onu := range pon.Onus {
1181 for _, fId := range onu.FlowIds {
1182 if fId == flowId {
1183 return onu, nil
1184 }
1185 }
1186 }
1187 }
Shrey Baid688b4242020-07-10 20:40:10 +05301188 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001189}
1190
Shrey Baid688b4242020-07-10 20:40:10 +05301191func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001192
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001193 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001194 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001195 "PonPorts": o.NumPon,
1196 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001197 devinfo := new(openolt.DeviceInfo)
Matteo Scandolo4a036262020-08-17 15:56:13 -07001198 devinfo.Vendor = common.Config.Olt.Vendor
1199 devinfo.Model = common.Config.Olt.Model
1200 devinfo.HardwareVersion = common.Config.Olt.HardwareVersion
1201 devinfo.FirmwareVersion = common.Config.Olt.FirmwareVersion
1202 devinfo.Technology = common.Config.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001203 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001204 devinfo.OnuIdStart = 1
1205 devinfo.OnuIdEnd = 255
1206 devinfo.AllocIdStart = 1024
1207 devinfo.AllocIdEnd = 16383
1208 devinfo.GemportIdStart = 1024
1209 devinfo.GemportIdEnd = 65535
1210 devinfo.FlowIdStart = 1
1211 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001212 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4a036262020-08-17 15:56:13 -07001213 devinfo.DeviceId = common.Config.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001214
1215 return devinfo, nil
1216}
1217
Shrey Baid688b4242020-07-10 20:40:10 +05301218func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001219 pon, err := o.GetPonById(omci_msg.IntfId)
1220 if err != nil {
1221 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001222 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001223 "onu_id": omci_msg.OnuId,
1224 "pon_id": omci_msg.IntfId,
1225 }).Error("pon ID not found")
1226 return nil, err
1227 }
1228
1229 onu, err := pon.GetOnuById(omci_msg.OnuId)
1230 if err != nil {
1231 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001232 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001233 "onu_id": omci_msg.OnuId,
1234 "pon_id": omci_msg.IntfId,
1235 }).Error("onu ID not found")
1236 return nil, err
1237 }
1238
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001239 oltLogger.WithFields(log.Fields{
1240 "IntfId": onu.PonPortID,
1241 "OnuId": onu.ID,
1242 "OnuSn": onu.Sn(),
1243 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001244 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001245 Type: OMCI,
1246 Data: OmciMessage{
1247 OnuSN: onu.SerialNumber,
1248 OnuID: onu.ID,
1249 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001250 },
1251 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001252 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001253 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001254}
1255
Shrey Baid688b4242020-07-10 20:40:10 +05301256func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001257 pon, err := o.GetPonById(onuPkt.IntfId)
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 PonPort")
1264 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001265 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001266 if err != nil {
1267 oltLogger.WithFields(log.Fields{
1268 "OnuId": onuPkt.OnuId,
1269 "IntfId": onuPkt.IntfId,
1270 "err": err,
1271 }).Error("Can't find Onu")
1272 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001273
Matteo Scandolo075b1892019-10-07 12:11:07 -07001274 oltLogger.WithFields(log.Fields{
1275 "IntfId": onu.PonPortID,
1276 "OnuId": onu.ID,
1277 "OnuSn": onu.Sn(),
Matteo Scandolo4a036262020-08-17 15:56:13 -07001278 }).Info("Received OnuPacketOut")
Matteo Scandolo075b1892019-10-07 12:11:07 -07001279
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001280 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Shrey Baid688b4242020-07-10 20:40:10 +05301281 pktType, _ := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001282
Matteo Scandolo4a036262020-08-17 15:56:13 -07001283 pktMac, err := packetHandlers.GetDstMacAddressFromPacket(rawpkt)
1284
1285 if err != nil {
1286 log.WithFields(log.Fields{
1287 "IntfId": onu.PonPortID,
1288 "OnuId": onu.ID,
1289 "OnuSn": onu.Sn(),
1290 "Pkt": rawpkt.Data(),
1291 }).Error("Can't find Dst MacAddress in packet, droppint it")
1292 return new(openolt.Empty), nil
1293 }
1294
Matteo Scandolo075b1892019-10-07 12:11:07 -07001295 msg := Message{
1296 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001297 Data: OnuPacketMessage{
Matteo Scandolo4a036262020-08-17 15:56:13 -07001298 IntfId: onuPkt.IntfId,
1299 OnuId: onuPkt.OnuId,
1300 Packet: rawpkt,
1301 Type: pktType,
1302 MacAddress: pktMac,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001303 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001304 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001305
Matteo Scandolo075b1892019-10-07 12:11:07 -07001306 onu.Channel <- msg
1307
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001308 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001309}
1310
Shrey Baid688b4242020-07-10 20:40:10 +05301311func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001312 oltLogger.WithFields(log.Fields{
1313 "oltId": o.ID,
1314 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301315 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301316 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001317 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001318}
1319
Shrey Baid688b4242020-07-10 20:40:10 +05301320func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301321 oltLogger.WithFields(log.Fields{
1322 "oltId": o.ID,
1323 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301324 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301325
Pragya Arya2225f202020-01-29 18:05:01 +05301326 // enable OLT
1327 oltMsg := Message{
1328 Type: OltIndication,
1329 Data: OltIndicationMessage{
1330 OperState: UP,
1331 },
Pragya Arya1881df02020-01-29 18:05:01 +05301332 }
Pragya Arya2225f202020-01-29 18:05:01 +05301333 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301334
Pragya Arya2225f202020-01-29 18:05:01 +05301335 for _, pon := range o.Pons {
1336 if pon.InternalState.Current() == "disabled" {
1337 msg := Message{
1338 Type: PonIndication,
1339 Data: PonIndicationMessage{
1340 OperState: UP,
1341 PonPortID: pon.ID,
1342 },
1343 }
1344 o.channel <- msg
1345 }
1346 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001347
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001348 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001349}
1350
Shrey Baid688b4242020-07-10 20:40:10 +05301351func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001352 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1353
Shrey Baid688b4242020-07-10 20:40:10 +05301354 _ = o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001355 // NOTE should we return an error if sendNniPakcet fails?
1356 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001357}
1358
Shrey Baid688b4242020-07-10 20:40:10 +05301359func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001360 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001361 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001362}
1363
Shrey Baid688b4242020-07-10 20:40:10 +05301364func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001365 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001366 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001367}
1368
Shrey Baid688b4242020-07-10 20:40:10 +05301369func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001370 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001371 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001372}
1373
Shrey Baid688b4242020-07-10 20:40:10 +05301374func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001375 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001376 return new(openolt.Empty), nil
1377}
1378
Shrey Baid688b4242020-07-10 20:40:10 +05301379func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001380 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001381 return new(openolt.Empty), nil
1382}
1383
Shrey Baid688b4242020-07-10 20:40:10 +05301384func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301385 oltLogger.WithFields(log.Fields{
1386 "OnuId": trafficSchedulers.OnuId,
1387 "IntfId": trafficSchedulers.IntfId,
1388 "OnuPortNo": trafficSchedulers.PortNo,
1389 }).Info("received CreateTrafficSchedulers")
1390
1391 if !s.enablePerf {
1392 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1393 if err != nil {
1394 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1395 return new(openolt.Empty), err
1396 }
1397 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1398 if err != nil {
1399 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1400 return new(openolt.Empty), err
1401 }
1402 onu.TrafficSchedulers = trafficSchedulers
1403 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001404 return new(openolt.Empty), nil
1405}
1406
Shrey Baid688b4242020-07-10 20:40:10 +05301407func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301408 oltLogger.WithFields(log.Fields{
1409 "OnuId": trafficSchedulers.OnuId,
1410 "IntfId": trafficSchedulers.IntfId,
1411 "OnuPortNo": trafficSchedulers.PortNo,
1412 }).Info("received RemoveTrafficSchedulers")
1413 if !s.enablePerf {
1414 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1415 if err != nil {
1416 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1417 return new(openolt.Empty), err
1418 }
1419 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1420 if err != nil {
1421 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1422 return new(openolt.Empty), err
1423 }
1424
1425 onu.TrafficSchedulers = nil
1426 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001427 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001428}
Scott Baker41724b82020-01-21 19:54:53 -08001429
1430// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301431func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001432 msg := Message{
1433 Type: AlarmIndication,
1434 Data: ind,
1435 }
1436
1437 o.channel <- msg
1438 return nil
1439}