blob: 21b57f2fbd329107a0adbdc1d6a34647f2097fbd [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 Scandolo4747d292019-08-05 11:50:18 -070021 "fmt"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020022 "net"
23 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010024 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020025
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070026 "github.com/google/gopacket"
27 "github.com/google/gopacket/layers"
Matteo Scandolodf3f85d2020-01-15 12:50:48 -080028 "github.com/google/gopacket/pcap"
Matteo Scandolo4747d292019-08-05 11:50:18 -070029 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070030 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070031 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010032 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040033 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080034 "github.com/opencord/voltha-protos/v2/go/openolt"
Matteo Scandolof65e6872020-04-15 15:18:43 -070035 "github.com/opencord/voltha-protos/v2/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070036 log "github.com/sirupsen/logrus"
37 "google.golang.org/grpc"
Pragya Arya8bdb4532020-03-02 17:08:09 +053038 "google.golang.org/grpc/codes"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010039 "google.golang.org/grpc/reflection"
Pragya Arya8bdb4532020-03-02 17:08:09 +053040 "google.golang.org/grpc/status"
Matteo Scandolo4747d292019-08-05 11:50:18 -070041)
42
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070043var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070044 "module": "OLT",
45})
46
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070047type OltDevice struct {
David Bainbridge103cf022019-12-16 20:11:35 +000048 sync.Mutex
49
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070050 // BBSIM Internals
Pragya Arya2225f202020-01-29 18:05:01 +053051 ID int
52 SerialNumber string
53 NumNni int
54 NumPon int
55 NumOnuPerPon int
56 InternalState *fsm.FSM
57 channel chan Message
58 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
59 nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
Pragya Arya8bdb4532020-03-02 17:08:09 +053060 Flows map[FlowKey]openolt.Flow
Pragya Arya2225f202020-01-29 18:05:01 +053061 Delay int
62 ControlledActivation mode
Pragya Arya324337e2020-02-20 14:35:08 +053063 EventChannel chan common.Event
64 PublishEvents bool
Pragya Arya996a0892020-03-09 21:47:52 +053065 PortStatsInterval int
Matteo Scandoloe33447a2019-10-31 12:38:23 -070066
Matteo Scandolo27428702019-10-11 16:21:16 -070067 Pons []*PonPort
68 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070069
70 // OLT Attributes
71 OperState *fsm.FSM
David Bainbridge103cf022019-12-16 20:11:35 +000072
73 enableContext context.Context
74 enableContextCancel context.CancelFunc
Pragya Arya1cbefa42020-01-13 12:15:29 +053075
76 OpenoltStream *openolt.Openolt_EnableIndicationServer
Anand S Katti09541352020-01-29 15:54:01 +053077 enablePerf bool
Matteo Scandolo4747d292019-08-05 11:50:18 -070078}
79
Matteo Scandolo27428702019-10-11 16:21:16 -070080var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010081var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070082
Matteo Scandolo27428702019-10-11 16:21:16 -070083func GetOLT() *OltDevice {
84 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070085}
86
Pragya Arya996a0892020-03-09 21:47:52 +053087func CreateOLT(options common.BBSimYamlConfig, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070088 oltLogger.WithFields(log.Fields{
Pragya Arya996a0892020-03-09 21:47:52 +053089 "ID": options.Olt.ID,
90 "NumNni": options.Olt.NniPorts,
91 "NumPon": options.Olt.PonPorts,
92 "NumOnuPerPon": options.Olt.OnusPonPort,
Matteo Scandolo4747d292019-08-05 11:50:18 -070093 }).Debug("CreateOLT")
94
Matteo Scandolo84f7d482019-08-08 19:00:47 -070095 olt = OltDevice{
Pragya Arya996a0892020-03-09 21:47:52 +053096 ID: options.Olt.ID,
97 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", options.Olt.ID),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070098 OperState: getOperStateFSM(func(e *fsm.Event) {
99 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
100 }),
Pragya Arya996a0892020-03-09 21:47:52 +0530101 NumNni: int(options.Olt.NniPorts),
102 NumPon: int(options.Olt.PonPorts),
103 NumOnuPerPon: int(options.Olt.OnusPonPort),
104 Pons: []*PonPort{},
105 Nnis: []*NniPort{},
106 Delay: options.BBSim.Delay,
107 Flows: make(map[FlowKey]openolt.Flow),
108 enablePerf: options.BBSim.EnablePerf,
109 PublishEvents: options.BBSim.Events,
110 PortStatsInterval: options.Olt.PortStatsInterval,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700111 }
112
Pragya Arya996a0892020-03-09 21:47:52 +0530113 if val, ok := ControlledActivationModes[options.BBSim.ControlledActivation]; ok {
Pragya Arya2225f202020-01-29 18:05:01 +0530114 olt.ControlledActivation = val
115 } else {
116 oltLogger.Warn("Unknown ControlledActivation Mode given, running in Default mode")
117 olt.ControlledActivation = Default
118 }
119
Matteo Scandolo4747d292019-08-05 11:50:18 -0700120 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700121 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700122 olt.InternalState = fsm.NewFSM(
123 "created",
124 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800125 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100126 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700127 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Mahir Gunyel6dad4452020-01-06 12:59:04 -0800128 //delete event in enabled state below is for reboot OLT case.
129 {Name: "delete", Src: []string{"disabled", "enabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700130 },
131 fsm.Callbacks{
132 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700133 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700134 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100135 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 },
137 )
138
Shrey Baid688b4242020-07-10 20:40:10 +0530139 if !isMock {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700140 // create NNI Port
141 nniPort, err := CreateNNI(&olt)
142 if err != nil {
143 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
144 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700145
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700146 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700147 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700148
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149 // create PON ports
Matteo Scandolo4747d292019-08-05 11:50:18 -0700150
Matteo Scandolof65e6872020-04-15 15:18:43 -0700151 if options.BBSim.STagAllocation == common.TagAllocationShared && options.BBSim.CTagAllocation == common.TagAllocationShared {
152 oltLogger.Fatalf("This configuration will result in duplicate C/S tags combination")
153 } else if options.BBSim.STagAllocation == common.TagAllocationUnique && options.BBSim.CTagAllocation == common.TagAllocationUnique {
154 oltLogger.Fatalf("This configuration is not supported yet")
155 } else if options.BBSim.STagAllocation == common.TagAllocationShared && options.BBSim.CTagAllocation == common.TagAllocationUnique {
156 // ATT case
157 availableCTag := options.BBSim.CTag
158 for i := 0; i < olt.NumPon; i++ {
159 p := CreatePonPort(&olt, uint32(i))
160
161 // create ONU devices
162 for j := 0; j < olt.NumOnuPerPon; j++ {
163 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700164 o := CreateONU(&olt, p, uint32(j+1), options.BBSim.STag, availableCTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700165 p.Onus = append(p.Onus, o)
166 availableCTag = availableCTag + 1
167 }
168
169 olt.Pons = append(olt.Pons, p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700170 }
Matteo Scandolof65e6872020-04-15 15:18:43 -0700171 } else if options.BBSim.STagAllocation == common.TagAllocationUnique && options.BBSim.CTagAllocation == common.TagAllocationShared {
172 // DT case
173 availableSTag := options.BBSim.STag
174 for i := 0; i < olt.NumPon; i++ {
175 p := CreatePonPort(&olt, uint32(i))
Matteo Scandolo4747d292019-08-05 11:50:18 -0700176
Matteo Scandolof65e6872020-04-15 15:18:43 -0700177 // create ONU devices
178 for j := 0; j < olt.NumOnuPerPon; j++ {
179 delay := time.Duration(olt.Delay*j) * time.Millisecond
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700180 o := CreateONU(&olt, p, uint32(j+1), availableSTag, options.BBSim.CTag, options.BBSim.EnableAuth, options.BBSim.EnableDhcp, delay, isMock)
Matteo Scandolof65e6872020-04-15 15:18:43 -0700181 p.Onus = append(p.Onus, o)
182 availableSTag = availableSTag + 1
183 }
184
185 olt.Pons = append(olt.Pons, p)
186 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700187 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100188
Shrey Baid688b4242020-07-10 20:40:10 +0530189 if !isMock {
Matteo Scandolod32c3822019-11-26 15:57:46 -0700190 if err := olt.InternalState.Event("initialize"); err != nil {
191 log.Errorf("Error initializing OLT: %v", err)
192 return nil
193 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100194 }
195
Pragya Arya324337e2020-02-20 14:35:08 +0530196 if olt.PublishEvents {
197 log.Debugf("BBSim event publishing is enabled")
198 // Create a channel to write event messages
199 olt.EventChannel = make(chan common.Event, 100)
200 }
201
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700202 return &olt
203}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700204
Shrey Baid688b4242020-07-10 20:40:10 +0530205func (o *OltDevice) InitOlt() {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206
207 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800208 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100209 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800210 // FIXME there should never be a server running if we are initializing the OLT
211 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 }
213
214 // create new channel for processOltMessages Go routine
215 o.channel = make(chan Message)
216
217 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
218 // FIXME we are assuming we have only one NNI
219 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800220 // NOTE we want to make sure the state is down when we initialize the OLT,
221 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
222 // in-band management
223 o.Nnis[0].OperState.SetState("down")
224 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100225 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800226 oltLogger.WithFields(log.Fields{
227 "Type": o.Nnis[0].Type,
228 "IntfId": o.Nnis[0].ID,
229 "OperState": o.Nnis[0].OperState.Current(),
230 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800232 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100233 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800234 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100235 }
236 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700237}
238
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800239func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100240
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800241 rebootDelay := common.Options.Olt.OltRebootDelay
242
243 oltLogger.WithFields(log.Fields{
244 "oltId": o.ID,
245 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
246
247 // transition internal state to deleted
248 if err := o.InternalState.Event("delete"); err != nil {
249 oltLogger.WithFields(log.Fields{
250 "oltId": o.ID,
251 }).Errorf("Error deleting OLT: %v", err)
252 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100253 }
254
255 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800256 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
257 if err := o.StopOltServer(); err != nil {
Pragya Arya2225f202020-01-29 18:05:01 +0530258 oltLogger.Errorf("Error in stopping OLT server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100259 return err
260 }
261
Pragya Arya2225f202020-01-29 18:05:01 +0530262 for _, pon := range olt.Pons {
263 msg := Message{
264 Type: PonIndication,
265 Data: PonIndicationMessage{
266 OperState: DOWN,
267 PonPortID: pon.ID,
268 },
269 }
270 o.channel <- msg
271
272 for _, onu := range pon.Onus {
273 if onu.InternalState.Current() != "initialized" {
Shrey Baid688b4242020-07-10 20:40:10 +0530274 _ = onu.InternalState.Event("disable")
Pragya Arya2225f202020-01-29 18:05:01 +0530275 }
276 }
277 }
278
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100279 // terminate the OLT's processOltMessages go routine
280 close(o.channel)
281 // terminate the OLT's processNniPacketIns go routine
Andy Bavier421f4d52020-01-21 15:39:22 -0700282 go o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100283 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100284
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100285 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100286
287 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800288 oltLogger.WithFields(log.Fields{
289 "oltId": o.ID,
290 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100291 return err
292 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800293 oltLogger.WithFields(log.Fields{
294 "oltId": o.ID,
295 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100296 return nil
297}
298
299// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800300func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100301 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700302 lis, err := net.Listen("tcp", address)
303 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700304 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700305 }
306 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100307
Matteo Scandolo4747d292019-08-05 11:50:18 -0700308 openolt.RegisterOpenoltServer(grpcServer, o)
309
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100310 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700311
Shrey Baid688b4242020-07-10 20:40:10 +0530312 go func() { _ = grpcServer.Serve(lis) }()
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100313 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700314
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100315 return grpcServer, nil
316}
317
318// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800319func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320 // TODO handle poweroff vs graceful shutdown
321 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800322 oltLogger.WithFields(log.Fields{
323 "oltId": o.SerialNumber,
324 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100325 oltServer.Stop()
326 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700327 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800328
Matteo Scandolo4747d292019-08-05 11:50:18 -0700329 return nil
330}
331
332// Device Methods
333
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100334// Enable implements the OpenOLT EnableIndicationServer functionality
Shrey Baid688b4242020-07-10 20:40:10 +0530335func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700336 oltLogger.Debug("Enable OLT called")
Pragya Arya2225f202020-01-29 18:05:01 +0530337 rebootFlag := false
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700338
David Bainbridge103cf022019-12-16 20:11:35 +0000339 // If enabled has already been called then an enabled context has
340 // been created. If this is the case then we want to cancel all the
341 // proessing loops associated with that enable before we recreate
342 // new ones
343 o.Lock()
344 if o.enableContext != nil && o.enableContextCancel != nil {
345 o.enableContextCancel()
Pragya Arya2225f202020-01-29 18:05:01 +0530346 rebootFlag = true
David Bainbridge103cf022019-12-16 20:11:35 +0000347 }
348 o.enableContext, o.enableContextCancel = context.WithCancel(context.TODO())
349 o.Unlock()
350
Matteo Scandolo4747d292019-08-05 11:50:18 -0700351 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800352 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700353
Pragya Arya1cbefa42020-01-13 12:15:29 +0530354 o.OpenoltStream = &stream
355
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100356 // create Go routine to process all OLT events
David Bainbridge103cf022019-12-16 20:11:35 +0000357 go o.processOltMessages(o.enableContext, stream, &wg)
358 go o.processNniPacketIns(o.enableContext, stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700359
360 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100361 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700362 Type: OltIndication,
363 Data: OltIndicationMessage{
364 OperState: UP,
365 },
366 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100367 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700368
369 // send NNI Port Indications
370 for _, nni := range o.Nnis {
371 msg := Message{
372 Type: NniIndication,
373 Data: NniIndicationMessage{
374 OperState: UP,
375 NniPortID: nni.ID,
376 },
377 }
378 o.channel <- msg
379 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100380
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800381 go o.processOmciMessages(o.enableContext, stream, &wg)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100382
Shrey Baid688b4242020-07-10 20:40:10 +0530383 if rebootFlag {
Pragya Arya2225f202020-01-29 18:05:01 +0530384 for _, pon := range o.Pons {
385 if pon.InternalState.Current() == "disabled" {
386 msg := Message{
387 Type: PonIndication,
388 Data: PonIndicationMessage{
389 OperState: UP,
390 PonPortID: pon.ID,
391 },
392 }
393 o.channel <- msg
Matteo Scandoloe60a5052020-02-07 00:31:14 +0000394 }
Pragya Arya2225f202020-01-29 18:05:01 +0530395 }
396 } else {
397
398 // 1. controlledActivation == Default: Send both PON and ONUs indications
399 // 2. controlledActivation == only-onu: that means only ONUs will be controlled activated, so auto send PON indications
400
401 if o.ControlledActivation == Default || o.ControlledActivation == OnlyONU {
402 // send PON Port indications
403 for _, pon := range o.Pons {
404 msg := Message{
405 Type: PonIndication,
406 Data: PonIndicationMessage{
407 OperState: UP,
408 PonPortID: pon.ID,
409 },
410 }
411 o.channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700412 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700413 }
414 }
415
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800416 oltLogger.Debug("Enable OLT Done")
Pragya Arya996a0892020-03-09 21:47:52 +0530417
418 if !o.enablePerf {
419 // Start a go routine to send periodic port stats to openolt adapter
420 go o.periodicPortStats(o.enableContext)
421 }
422
Matteo Scandolo4747d292019-08-05 11:50:18 -0700423 wg.Wait()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700424}
425
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800426func (o *OltDevice) processOmciMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400427 ch := omcisim.GetChannel()
428
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100429 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400430
David Bainbridge103cf022019-12-16 20:11:35 +0000431loop:
432 for {
433 select {
434 case <-ctx.Done():
435 oltLogger.Debug("OMCI processing canceled via context")
436 break loop
437 case message, ok := <-ch:
438 if !ok || ctx.Err() != nil {
439 oltLogger.Debug("OMCI processing canceled via channel close")
440 break loop
441 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800442
443 oltLogger.WithFields(log.Fields{
444 "messageType": message.Type,
445 "OnuId": message.Data.OnuId,
446 "IntfId": message.Data.IntfId,
447 }).Info("Received message on OMCI Sim channel")
448
David Bainbridge103cf022019-12-16 20:11:35 +0000449 onuId := message.Data.OnuId
450 intfId := message.Data.IntfId
451 onu, err := o.FindOnuById(intfId, onuId)
452 if err != nil {
453 oltLogger.Errorf("Failed to find onu: %v", err)
454 continue
455 }
Matteo Scandolodf3f85d2020-01-15 12:50:48 -0800456 go onu.processOmciMessage(message, stream)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400457 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400458 }
David Bainbridge103cf022019-12-16 20:11:35 +0000459
460 wg.Done()
William Kurkian9dadc5b2019-10-22 13:51:57 -0400461}
462
Pragya Arya996a0892020-03-09 21:47:52 +0530463func (o *OltDevice) periodicPortStats(ctx context.Context) {
464 var portStats *openolt.PortStatistics
465 for {
466 select {
467 case <-time.After(time.Duration(o.PortStatsInterval) * time.Second):
468 // send NNI port stats
469 for _, port := range o.Nnis {
470 incrementStat := true
471 if port.OperState.Current() == "down" {
472 incrementStat = false
473 }
474 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
475 o.sendPortStatsIndication(portStats, port.ID, port.Type)
476 }
477
478 // send PON port stats
479 for _, port := range o.Pons {
480 incrementStat := true
481 // do not increment port stats if PON port is down or no ONU is activated on PON port
482 if port.OperState.Current() == "down" || port.GetNumOfActiveOnus() < 1 {
483 incrementStat = false
484 }
485 portStats, port.PacketCount = getPortStats(port.PacketCount, incrementStat)
486 o.sendPortStatsIndication(portStats, port.ID, port.Type)
487 }
488 case <-ctx.Done():
489 log.Debug("Stop sending port stats")
490 return
491 }
492
493 }
494}
495
Matteo Scandolo4747d292019-08-05 11:50:18 -0700496// Helpers method
497
Shrey Baid688b4242020-07-10 20:40:10 +0530498func (o *OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700499 for _, pon := range o.Pons {
500 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700501 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700502 }
503 }
Shrey Baid688b4242020-07-10 20:40:10 +0530504 return nil, fmt.Errorf("Cannot find PonPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700505}
506
Shrey Baid688b4242020-07-10 20:40:10 +0530507func (o *OltDevice) getNniById(id uint32) (*NniPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700508 for _, nni := range o.Nnis {
509 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700510 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700511 }
512 }
Shrey Baid688b4242020-07-10 20:40:10 +0530513 return nil, fmt.Errorf("Cannot find NniPort with id %d in OLT %d", id, o.ID)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700514}
515
Scott Baker41724b82020-01-21 19:54:53 -0800516func (o *OltDevice) sendAlarmIndication(alarmInd *openolt.AlarmIndication, stream openolt.Openolt_EnableIndicationServer) {
517 data := &openolt.Indication_AlarmInd{AlarmInd: alarmInd}
518 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
519 oltLogger.Errorf("Failed to send Alarm Indication: %v", err)
520 return
521 }
522
523 oltLogger.WithFields(log.Fields{
524 "AlarmIndication": alarmInd,
525 }).Debug("Sent Indication_AlarmInd")
526}
527
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100528func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700529 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
530 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700531 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800532 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700533 }
534
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700535 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700536 "OperState": msg.OperState,
537 }).Debug("Sent Indication_OltInd")
538}
539
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100540func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700541 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800542 if msg.OperState == UP {
543 if err := nni.OperState.Event("enable"); err != nil {
544 log.WithFields(log.Fields{
545 "Type": nni.Type,
546 "IntfId": nni.ID,
547 "OperState": nni.OperState.Current(),
548 }).Errorf("Can't move NNI Port to enabled state: %v", err)
549 }
550 } else if msg.OperState == DOWN {
551 if err := nni.OperState.Event("disable"); err != nil {
552 log.WithFields(log.Fields{
553 "Type": nni.Type,
554 "IntfId": nni.ID,
555 "OperState": nni.OperState.Current(),
556 }).Errorf("Can't move NNI Port to disable state: %v", err)
557 }
558 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700559 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700560 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700561 Type: nni.Type,
562 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700563 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700564 }}
565
566 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700567 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800568 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700569 }
570
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700571 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700572 "Type": nni.Type,
573 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700574 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700575 }).Debug("Sent Indication_IntfOperInd for NNI")
576}
577
Pragya Arya2225f202020-01-29 18:05:01 +0530578func (o *OltDevice) sendPonIndication(ponPortID uint32) {
579
580 stream := *o.OpenoltStream
581 pon, _ := o.GetPonById(ponPortID)
582 // Send IntfIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700583 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700584 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700585 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700586 }}
587
588 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700589 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800590 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700591 }
592
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700593 oltLogger.WithFields(log.Fields{
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 }).Debug("Sent Indication_IntfInd")
597
Pragya Arya2225f202020-01-29 18:05:01 +0530598 // Send IntfOperIndication for PON port
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700600 Type: pon.Type,
601 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700602 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603 }}
604
605 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700606 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800607 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700608 }
609
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700610 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700611 "Type": pon.Type,
612 "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_IntfOperInd for PON")
615}
616
Pragya Arya996a0892020-03-09 21:47:52 +0530617func (o *OltDevice) sendPortStatsIndication(stats *openolt.PortStatistics, portID uint32, portType string) {
Shrey Baid55f328c2020-07-07 19:20:42 +0530618 if o.InternalState.Current() == "enabled" {
619 oltLogger.WithFields(log.Fields{
620 "Type": portType,
621 "IntfId": portID,
622 }).Trace("Sending port stats")
623 stats.IntfId = InterfaceIDToPortNo(portID, portType)
624 data := &openolt.Indication_PortStats{
625 PortStats: stats,
626 }
627 stream := *o.OpenoltStream
628 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
629 oltLogger.Errorf("Failed to send PortStats: %v", err)
630 return
631 }
Pragya Arya996a0892020-03-09 21:47:52 +0530632 }
633}
634
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100635// processOltMessages handles messages received over the OpenOLT interface
David Bainbridge103cf022019-12-16 20:11:35 +0000636func (o *OltDevice) processOltMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100637 oltLogger.Debug("Starting OLT Indication Channel")
David Bainbridge103cf022019-12-16 20:11:35 +0000638 ch := o.channel
Matteo Scandolo4747d292019-08-05 11:50:18 -0700639
David Bainbridge103cf022019-12-16 20:11:35 +0000640loop:
641 for {
642 select {
643 case <-ctx.Done():
644 oltLogger.Debug("OLT Indication processing canceled via context")
645 break loop
646 case message, ok := <-ch:
647 if !ok || ctx.Err() != nil {
648 oltLogger.Debug("OLT Indication processing canceled via closed channel")
649 break loop
Matteo Scandolo4747d292019-08-05 11:50:18 -0700650 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700651
David Bainbridge103cf022019-12-16 20:11:35 +0000652 oltLogger.WithFields(log.Fields{
653 "oltId": o.ID,
654 "messageType": message.Type,
655 }).Trace("Received message")
656
657 switch message.Type {
658 case OltIndication:
659 msg, _ := message.Data.(OltIndicationMessage)
660 if msg.OperState == UP {
Shrey Baid688b4242020-07-10 20:40:10 +0530661 _ = o.InternalState.Event("enable")
662 _ = o.OperState.Event("enable")
David Bainbridge103cf022019-12-16 20:11:35 +0000663 } else if msg.OperState == DOWN {
Shrey Baid688b4242020-07-10 20:40:10 +0530664 _ = o.InternalState.Event("disable")
665 _ = o.OperState.Event("disable")
David Bainbridge103cf022019-12-16 20:11:35 +0000666 }
667 o.sendOltIndication(msg, stream)
Scott Baker41724b82020-01-21 19:54:53 -0800668 case AlarmIndication:
669 alarmInd, _ := message.Data.(*openolt.AlarmIndication)
670 o.sendAlarmIndication(alarmInd, stream)
David Bainbridge103cf022019-12-16 20:11:35 +0000671 case NniIndication:
672 msg, _ := message.Data.(NniIndicationMessage)
673 o.sendNniIndication(msg, stream)
674 case PonIndication:
675 msg, _ := message.Data.(PonIndicationMessage)
Pragya Arya2225f202020-01-29 18:05:01 +0530676 pon, _ := o.GetPonById(msg.PonPortID)
677 if msg.OperState == UP {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530678 if err := pon.OperState.Event("enable"); err != nil {
679 oltLogger.WithFields(log.Fields{
680 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800681 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530682 }).Error("Can't Enable Oper state for PON Port")
683 }
684 if err := pon.InternalState.Event("enable"); err != nil {
685 oltLogger.WithFields(log.Fields{
686 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800687 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530688 }).Error("Can't Enable Internal state for PON Port")
689 }
Pragya Arya2225f202020-01-29 18:05:01 +0530690 } else if msg.OperState == DOWN {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530691 if err := pon.OperState.Event("disable"); err != nil {
692 oltLogger.WithFields(log.Fields{
693 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800694 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530695 }).Error("Can't Disable Oper state for PON Port")
696 }
697 if err := pon.InternalState.Event("disable"); err != nil {
698 oltLogger.WithFields(log.Fields{
699 "IntfId": msg.PonPortID,
Matteo Scandolo5ff80082019-12-20 13:20:57 -0800700 "Err": err,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530701 }).Error("Can't Disable Internal state for PON Port")
702 }
Pragya Arya2225f202020-01-29 18:05:01 +0530703 }
David Bainbridge103cf022019-12-16 20:11:35 +0000704 default:
705 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
706 }
707 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700708 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100709 wg.Done()
710 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700711}
712
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100713// processNniPacketIns handles messages received over the NNI interface
David Bainbridge103cf022019-12-16 20:11:35 +0000714func (o *OltDevice) processNniPacketIns(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700715 oltLogger.WithFields(log.Fields{
716 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800717 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700718 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700719
David Bainbridge103cf022019-12-16 20:11:35 +0000720 ch := o.nniPktInChannel
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700721
David Bainbridge103cf022019-12-16 20:11:35 +0000722loop:
723 for {
724 select {
725 case <-ctx.Done():
726 oltLogger.Debug("NNI Indication processing canceled via context")
727 break loop
728 case message, ok := <-ch:
729 if !ok || ctx.Err() != nil {
730 oltLogger.Debug("NNI Indication processing canceled via channel closed")
731 break loop
732 }
733 oltLogger.Tracef("Received packets on NNI Channel")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700734
David Bainbridge103cf022019-12-16 20:11:35 +0000735 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700736
David Bainbridge103cf022019-12-16 20:11:35 +0000737 if err != nil {
738 log.WithFields(log.Fields{
739 "IntfType": "nni",
740 "IntfId": nniId,
741 "Pkt": message.Pkt.Data(),
742 }).Error("Can't find Dst MacAddress in packet")
743 return
744 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700745
David Bainbridge103cf022019-12-16 20:11:35 +0000746 onu, err := o.FindOnuByMacAddress(onuMac)
747 if err != nil {
748 log.WithFields(log.Fields{
749 "IntfType": "nni",
750 "IntfId": nniId,
751 "Pkt": message.Pkt.Data(),
752 "MacAddress": onuMac.String(),
753 }).Error("Can't find ONU with MacAddress")
754 return
755 }
756
757 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
758 if err != nil {
759 log.Error("Fail to add double tag to packet")
760 }
761
762 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
763 IntfType: "nni",
764 IntfId: nniId,
765 Pkt: doubleTaggedPkt.Data()}}
766 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
767 oltLogger.WithFields(log.Fields{
768 "IntfType": data.PktInd.IntfType,
769 "IntfId": nniId,
770 "Pkt": doubleTaggedPkt.Data(),
771 }).Errorf("Fail to send PktInd indication: %v", err)
772 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700773 oltLogger.WithFields(log.Fields{
774 "IntfType": data.PktInd.IntfType,
775 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700776 "Pkt": doubleTaggedPkt.Data(),
David Bainbridge103cf022019-12-16 20:11:35 +0000777 "OnuSn": onu.Sn(),
778 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700779 }
780 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100781 wg.Done()
782 oltLogger.WithFields(log.Fields{
783 "nniChannel": o.nniPktInChannel,
784 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700785}
786
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700787// returns an ONU with a given Serial Number
Shrey Baid688b4242020-07-10 20:40:10 +0530788func (o *OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200789 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700790 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700791 for _, pon := range o.Pons {
792 for _, onu := range pon.Onus {
793 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700794 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700795 }
796 }
797 }
798
Shrey Baid688b4242020-07-10 20:40:10 +0530799 return &Onu{}, fmt.Errorf("cannot-find-onu-by-serial-number-%s", serialNumber)
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700800}
801
William Kurkian9dadc5b2019-10-22 13:51:57 -0400802// returns an ONU with a given interface/Onu Id
Shrey Baid688b4242020-07-10 20:40:10 +0530803func (o *OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200804 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400805 // memoizing it will remove the bottleneck
806 for _, pon := range o.Pons {
807 if pon.ID == intfId {
808 for _, onu := range pon.Onus {
809 if onu.ID == onuId {
810 return onu, nil
811 }
812 }
813 }
814 }
Shrey Baid688b4242020-07-10 20:40:10 +0530815 return &Onu{}, fmt.Errorf("cannot-find-onu-by-id-%v-%v", intfId, onuId)
William Kurkian9dadc5b2019-10-22 13:51:57 -0400816}
817
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700818// returns an ONU with a given Mac Address
Shrey Baid688b4242020-07-10 20:40:10 +0530819func (o *OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200820 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700821 // memoizing it will remove the bottleneck
822 for _, pon := range o.Pons {
823 for _, onu := range pon.Onus {
824 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700825 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700826 }
827 }
828 }
829
Shrey Baid688b4242020-07-10 20:40:10 +0530830 return &Onu{}, fmt.Errorf("cannot-find-onu-by-mac-address-%s", mac)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700831}
832
Matteo Scandolo4747d292019-08-05 11:50:18 -0700833// GRPC Endpoints
834
Shrey Baid688b4242020-07-10 20:40:10 +0530835func (o *OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700836 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700837 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700838 }).Info("Received ActivateOnu call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530839 publishEvent("ONU-activate-indication-received", int32(onu.IntfId), int32(onu.OnuId), onuSnToString(onu.SerialNumber))
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700840
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700841 pon, _ := o.GetPonById(onu.IntfId)
842 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500843 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700844
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700845 if err := _onu.OperState.Event("enable"); err != nil {
846 oltLogger.WithFields(log.Fields{
847 "IntfId": _onu.PonPortID,
848 "OnuSn": _onu.Sn(),
849 "OnuId": _onu.ID,
850 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700851 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700852 if err := _onu.InternalState.Event("enable"); err != nil {
853 oltLogger.WithFields(log.Fields{
854 "IntfId": _onu.PonPortID,
855 "OnuSn": _onu.Sn(),
856 "OnuId": _onu.ID,
857 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
858 }
859
860 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
861
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700862 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700863}
864
Shrey Baid688b4242020-07-10 20:40:10 +0530865func (o *OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700866 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700867 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700868}
869
Shrey Baid688b4242020-07-10 20:40:10 +0530870func (o *OltDevice) DeleteOnu(_ context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530871 oltLogger.WithFields(log.Fields{
872 "IntfId": onu.IntfId,
873 "OnuId": onu.OnuId,
874 }).Info("Received DeleteOnu call from VOLTHA")
875
876 pon, err := o.GetPonById(onu.IntfId)
877 if err != nil {
878 oltLogger.WithFields(log.Fields{
879 "OnuId": onu.OnuId,
880 "IntfId": onu.IntfId,
881 "err": err,
882 }).Error("Can't find PonPort")
883 }
884 _onu, err := pon.GetOnuById(onu.OnuId)
885 if err != nil {
886 oltLogger.WithFields(log.Fields{
887 "OnuId": onu.OnuId,
888 "IntfId": onu.IntfId,
889 "err": err,
890 }).Error("Can't find Onu")
891 }
892
Hardik Windlassad790cb2020-06-17 21:26:22 +0530893 if err := _onu.InternalState.Event("disable"); err != nil {
Pragya Arya1cbefa42020-01-13 12:15:29 +0530894 oltLogger.WithFields(log.Fields{
895 "IntfId": _onu.PonPortID,
896 "OnuSn": _onu.Sn(),
897 "OnuId": _onu.ID,
Hardik Windlassad790cb2020-06-17 21:26:22 +0530898 }).Infof("Failed to transition ONU to disabled state: %s", err.Error())
899 }
900
Hardik Windlassad790cb2020-06-17 21:26:22 +0530901 // ONU Re-Discovery
902 if o.InternalState.Current() == "enabled" && pon.InternalState.Current() == "enabled" {
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530903 go _onu.ReDiscoverOnu()
Pragya Arya1cbefa42020-01-13 12:15:29 +0530904 }
905
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700906 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700907}
908
Shrey Baid688b4242020-07-10 20:40:10 +0530909func (o *OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700910 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800911 oltLogger.WithFields(log.Fields{
912 "oltId": o.ID,
913 }).Info("Disabling OLT")
Pragya Arya324337e2020-02-20 14:35:08 +0530914 publishEvent("OLT-disable-received", -1, -1, "")
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800915
Matteo Scandolo401503a2019-12-11 14:48:14 -0800916 for _, pon := range o.Pons {
Pragya Arya2225f202020-01-29 18:05:01 +0530917 if pon.InternalState.Current() == "enabled" {
918 // disable PONs
919 msg := Message{
920 Type: PonIndication,
921 Data: PonIndicationMessage{
922 OperState: DOWN,
923 PonPortID: pon.ID,
924 },
925 }
926 o.channel <- msg
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800927 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800928 }
929
Matteo Scandolo401503a2019-12-11 14:48:14 -0800930 // Note that we are not disabling the NNI as the real OLT does not.
931 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800932
933 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100934 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700935 Type: OltIndication,
936 Data: OltIndicationMessage{
937 OperState: DOWN,
938 },
939 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100940 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700941 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700942}
943
Shrey Baid688b4242020-07-10 20:40:10 +0530944func (o *OltDevice) DisablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530945 oltLogger.Infof("DisablePonIf request received for PON %d", intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200946 ponID := intf.GetIntfId()
947 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200948
949 msg := Message{
950 Type: PonIndication,
951 Data: PonIndicationMessage{
952 OperState: DOWN,
953 PonPortID: ponID,
954 },
955 }
956 o.channel <- msg
957
958 for _, onu := range pon.Onus {
959
960 onuIndication := OnuIndicationMessage{
961 OperState: DOWN,
962 PonPortID: ponID,
963 OnuID: onu.ID,
964 OnuSN: onu.SerialNumber,
965 }
966 onu.sendOnuIndication(onuIndication, *o.OpenoltStream)
967
968 }
969
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700970 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700971}
972
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100973func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700974 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +0530975 publishEvent("OLT-enable-received", -1, -1, "")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700976 o.Enable(stream)
977 return nil
978}
979
Shrey Baid688b4242020-07-10 20:40:10 +0530980func (o *OltDevice) EnablePonIf(_ context.Context, intf *openolt.Interface) (*openolt.Empty, error) {
Hardik Windlassad790cb2020-06-17 21:26:22 +0530981 oltLogger.Infof("EnablePonIf request received for PON %d", intf.IntfId)
Pragya Arya2225f202020-01-29 18:05:01 +0530982 ponID := intf.GetIntfId()
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200983 pon, _ := o.GetPonById(intf.IntfId)
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200984
Pragya Arya2225f202020-01-29 18:05:01 +0530985 msg := Message{
986 Type: PonIndication,
987 Data: PonIndicationMessage{
988 OperState: UP,
989 PonPortID: ponID,
990 },
991 }
992 o.channel <- msg
993
Andrea Campanella340b9ea2020-04-28 18:34:01 +0200994 for _, onu := range pon.Onus {
995
996 onuIndication := OnuIndicationMessage{
997 OperState: UP,
998 PonPortID: ponID,
999 OnuID: onu.ID,
1000 OnuSN: onu.SerialNumber,
1001 }
1002 onu.sendOnuIndication(onuIndication, *o.OpenoltStream)
1003
1004 }
1005
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001006 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001007}
1008
Shrey Baid688b4242020-07-10 20:40:10 +05301009func (o *OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001010 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001011 "IntfId": flow.AccessIntfId,
1012 "OnuId": flow.OnuId,
1013 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001014 "InnerVlan": flow.Classifier.IVid,
1015 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001016 "FlowType": flow.FlowType,
1017 "FlowId": flow.FlowId,
1018 "UniID": flow.UniId,
1019 "PortNo": flow.PortNo,
Pragya Arya8bdb4532020-03-02 17:08:09 +05301020 }).Tracef("OLT receives FlowAdd")
1021
1022 flowKey := FlowKey{}
1023 if !o.enablePerf {
1024 flowKey = FlowKey{ID: flow.FlowId, Direction: flow.FlowType}
1025 olt.Flows[flowKey] = *flow
1026 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001027
1028 if flow.AccessIntfId == -1 {
1029 oltLogger.WithFields(log.Fields{
1030 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001031 }).Debug("Adding OLT flow")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001032 } else if flow.FlowType == "multicast" {
1033 oltLogger.WithFields(log.Fields{
1034 "FlowId": flow.FlowId,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001035 }).Debug("Adding OLT multicast flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001036 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001037 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001038 if err != nil {
1039 oltLogger.WithFields(log.Fields{
1040 "OnuId": flow.OnuId,
1041 "IntfId": flow.AccessIntfId,
1042 "err": err,
1043 }).Error("Can't find PonPort")
1044 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001045 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -07001046 if err != nil {
1047 oltLogger.WithFields(log.Fields{
1048 "OnuId": flow.OnuId,
1049 "IntfId": flow.AccessIntfId,
1050 "err": err,
1051 }).Error("Can't find Onu")
Jonathan Hartb5fc46a2020-03-31 16:42:31 -07001052 return nil, err
Matteo Scandolo27428702019-10-11 16:21:16 -07001053 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301054 if !o.enablePerf {
1055 onu.Flows = append(onu.Flows, flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301056 // Generate event on first flow for ONU
1057 if len(onu.Flows) == 1 {
1058 publishEvent("Flow-add-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
1059 }
Pragya Arya8bdb4532020-03-02 17:08:09 +05301060 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001061
1062 msg := Message{
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001063 Type: FlowAdd,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001064 Data: OnuFlowUpdateMessage{
1065 PonPortID: pon.ID,
1066 OnuID: onu.ID,
1067 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001068 },
1069 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001070 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001071 }
1072
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001073 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001074}
1075
Pragya Arya8bdb4532020-03-02 17:08:09 +05301076// FlowRemove request from VOLTHA
Shrey Baid688b4242020-07-10 20:40:10 +05301077func (o *OltDevice) FlowRemove(_ context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001078
Pragya Arya8bdb4532020-03-02 17:08:09 +05301079 oltLogger.WithFields(log.Fields{
Shrey Baid55f328c2020-07-07 19:20:42 +05301080 "FlowId": flow.FlowId,
1081 "FlowType": flow.FlowType,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001082 }).Debug("OLT receives FlowRemove")
Pragya Arya8bdb4532020-03-02 17:08:09 +05301083
1084 if !o.enablePerf { // remove only if flow were stored
1085 flowKey := FlowKey{
1086 ID: flow.FlowId,
1087 Direction: flow.FlowType,
1088 }
1089
1090 // Check if flow exists
1091 storedFlow, ok := o.Flows[flowKey]
1092 if !ok {
1093 oltLogger.Errorf("Flow %v not found", flow)
1094 return new(openolt.Empty), status.Errorf(codes.NotFound, "Flow not found")
1095 }
1096
1097 // if its ONU flow remove it from ONU also
1098 if storedFlow.AccessIntfId != -1 {
1099 pon := o.Pons[uint32(storedFlow.AccessIntfId)]
1100 onu, err := pon.GetOnuById(uint32(storedFlow.OnuId))
1101 if err != nil {
1102 oltLogger.WithFields(log.Fields{
1103 "OnuId": storedFlow.OnuId,
1104 "IntfId": storedFlow.AccessIntfId,
1105 "err": err,
1106 }).Error("ONU not found")
1107 return new(openolt.Empty), nil
1108 }
1109 onu.DeleteFlow(flowKey)
Pragya Arya1d5ffb82020-03-20 18:51:37 +05301110 publishEvent("Flow-remove-received", int32(onu.PonPortID), int32(onu.ID), onuSnToString(onu.SerialNumber))
Pragya Arya8bdb4532020-03-02 17:08:09 +05301111 }
1112
1113 // delete from olt flows
1114 delete(o.Flows, flowKey)
1115 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001116
1117 if flow.AccessIntfId == -1 {
1118 oltLogger.WithFields(log.Fields{
1119 "FlowId": flow.FlowId,
1120 }).Debug("Removing OLT flow")
1121 } else if flow.FlowType == "multicast" {
1122 oltLogger.WithFields(log.Fields{
1123 "FlowId": flow.FlowId,
1124 }).Debug("Removing OLT multicast flow")
1125 } else {
1126
1127 onu, err := o.GetOnuByFlowId(flow.FlowId)
1128 if err != nil {
1129 oltLogger.WithFields(log.Fields{
1130 "OnuId": flow.OnuId,
1131 "IntfId": flow.AccessIntfId,
1132 "err": err,
1133 }).Error("Can't find Onu")
1134 return nil, err
1135 }
1136
1137 msg := Message{
1138 Type: FlowRemoved,
1139 Data: OnuFlowUpdateMessage{
Shrey Baid55f328c2020-07-07 19:20:42 +05301140 Flow: flow,
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001141 },
1142 }
1143 onu.Channel <- msg
1144 }
1145
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001146 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001147}
1148
Shrey Baid688b4242020-07-10 20:40:10 +05301149func (o *OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo18859852020-01-15 13:33:57 -08001150 res := openolt.Heartbeat{HeartbeatSignature: uint32(time.Now().Unix())}
1151 oltLogger.WithFields(log.Fields{
1152 "signature": res.HeartbeatSignature,
1153 }).Trace("HeartbeatCheck")
1154 return &res, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001155}
1156
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001157func (o *OltDevice) GetOnuByFlowId(flowId uint32) (*Onu, error) {
1158 for _, pon := range o.Pons {
1159 for _, onu := range pon.Onus {
1160 for _, fId := range onu.FlowIds {
1161 if fId == flowId {
1162 return onu, nil
1163 }
1164 }
1165 }
1166 }
Shrey Baid688b4242020-07-10 20:40:10 +05301167 return nil, fmt.Errorf("Cannot find Onu by flowId %d", flowId)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001168}
1169
Shrey Baid688b4242020-07-10 20:40:10 +05301170func (o *OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -07001171
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001172 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001173 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001174 "PonPorts": o.NumPon,
1175 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -07001176 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001177 devinfo.Vendor = common.Options.Olt.Vendor
1178 devinfo.Model = common.Options.Olt.Model
1179 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
1180 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
1181 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -07001182 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -07001183 devinfo.OnuIdStart = 1
1184 devinfo.OnuIdEnd = 255
1185 devinfo.AllocIdStart = 1024
1186 devinfo.AllocIdEnd = 16383
1187 devinfo.GemportIdStart = 1024
1188 devinfo.GemportIdEnd = 65535
1189 devinfo.FlowIdStart = 1
1190 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -07001191 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +01001192 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -07001193
1194 return devinfo, nil
1195}
1196
Shrey Baid688b4242020-07-10 20:40:10 +05301197func (o *OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001198 pon, err := o.GetPonById(omci_msg.IntfId)
1199 if err != nil {
1200 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001201 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001202 "onu_id": omci_msg.OnuId,
1203 "pon_id": omci_msg.IntfId,
1204 }).Error("pon ID not found")
1205 return nil, err
1206 }
1207
1208 onu, err := pon.GetOnuById(omci_msg.OnuId)
1209 if err != nil {
1210 oltLogger.WithFields(log.Fields{
Matteo Scandolof65e6872020-04-15 15:18:43 -07001211 "error": err,
Jonathan Hartacfa20e2020-03-31 15:20:14 -07001212 "onu_id": omci_msg.OnuId,
1213 "pon_id": omci_msg.IntfId,
1214 }).Error("onu ID not found")
1215 return nil, err
1216 }
1217
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001218 oltLogger.WithFields(log.Fields{
1219 "IntfId": onu.PonPortID,
1220 "OnuId": onu.ID,
1221 "OnuSn": onu.Sn(),
1222 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001223 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001224 Type: OMCI,
1225 Data: OmciMessage{
1226 OnuSN: onu.SerialNumber,
1227 OnuID: onu.ID,
1228 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001229 },
1230 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -07001231 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001232 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001233}
1234
Shrey Baid688b4242020-07-10 20:40:10 +05301235func (o *OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001236 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001237 if err != nil {
1238 oltLogger.WithFields(log.Fields{
1239 "OnuId": onuPkt.OnuId,
1240 "IntfId": onuPkt.IntfId,
1241 "err": err,
1242 }).Error("Can't find PonPort")
1243 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001244 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -07001245 if err != nil {
1246 oltLogger.WithFields(log.Fields{
1247 "OnuId": onuPkt.OnuId,
1248 "IntfId": onuPkt.IntfId,
1249 "err": err,
1250 }).Error("Can't find Onu")
1251 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001252
Matteo Scandolo075b1892019-10-07 12:11:07 -07001253 oltLogger.WithFields(log.Fields{
1254 "IntfId": onu.PonPortID,
1255 "OnuId": onu.ID,
1256 "OnuSn": onu.Sn(),
1257 }).Tracef("Received OnuPacketOut")
1258
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001259 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Shrey Baid688b4242020-07-10 20:40:10 +05301260 pktType, _ := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001261
Matteo Scandolo075b1892019-10-07 12:11:07 -07001262 msg := Message{
1263 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001264 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -07001265 IntfId: onuPkt.IntfId,
1266 OnuId: onuPkt.OnuId,
1267 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001268 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -07001269 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -07001270 }
Matteo Scandolo075b1892019-10-07 12:11:07 -07001271 onu.Channel <- msg
1272
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001273 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001274}
1275
Shrey Baid688b4242020-07-10 20:40:10 +05301276func (o *OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -08001277 oltLogger.WithFields(log.Fields{
1278 "oltId": o.ID,
1279 }).Info("Shutting down")
Pragya Arya324337e2020-02-20 14:35:08 +05301280 publishEvent("OLT-reboot-received", -1, -1, "")
Shrey Baid688b4242020-07-10 20:40:10 +05301281 go func() { _ = o.RestartOLT() }()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001282 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001283}
1284
Shrey Baid688b4242020-07-10 20:40:10 +05301285func (o *OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Pragya Arya6a708d62020-01-01 17:17:20 +05301286 oltLogger.WithFields(log.Fields{
1287 "oltId": o.ID,
1288 }).Info("Received ReenableOlt request from VOLTHA")
Pragya Arya324337e2020-02-20 14:35:08 +05301289 publishEvent("OLT-reenable-received", -1, -1, "")
Pragya Arya6a708d62020-01-01 17:17:20 +05301290
Pragya Arya2225f202020-01-29 18:05:01 +05301291 // enable OLT
1292 oltMsg := Message{
1293 Type: OltIndication,
1294 Data: OltIndicationMessage{
1295 OperState: UP,
1296 },
Pragya Arya1881df02020-01-29 18:05:01 +05301297 }
Pragya Arya2225f202020-01-29 18:05:01 +05301298 o.channel <- oltMsg
Pragya Arya6a708d62020-01-01 17:17:20 +05301299
Pragya Arya2225f202020-01-29 18:05:01 +05301300 for _, pon := range o.Pons {
1301 if pon.InternalState.Current() == "disabled" {
1302 msg := Message{
1303 Type: PonIndication,
1304 Data: PonIndicationMessage{
1305 OperState: UP,
1306 PonPortID: pon.ID,
1307 },
1308 }
1309 o.channel <- msg
1310 }
1311 }
Matteo Scandoloe60a5052020-02-07 00:31:14 +00001312
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001313 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001314}
1315
Shrey Baid688b4242020-07-10 20:40:10 +05301316func (o *OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001317 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
1318
Shrey Baid688b4242020-07-10 20:40:10 +05301319 _ = o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001320 // NOTE should we return an error if sendNniPakcet fails?
1321 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001322}
1323
Shrey Baid688b4242020-07-10 20:40:10 +05301324func (o *OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001325 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001326 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001327}
1328
Shrey Baid688b4242020-07-10 20:40:10 +05301329func (o *OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001330 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001331 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -07001332}
1333
Shrey Baid688b4242020-07-10 20:40:10 +05301334func (o *OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -07001335 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001336 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -07001337}
1338
Shrey Baid688b4242020-07-10 20:40:10 +05301339func (s *OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001340 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001341 return new(openolt.Empty), nil
1342}
1343
Shrey Baid688b4242020-07-10 20:40:10 +05301344func (s *OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001345 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -07001346 return new(openolt.Empty), nil
1347}
1348
Shrey Baid688b4242020-07-10 20:40:10 +05301349func (s *OltDevice) CreateTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301350 oltLogger.WithFields(log.Fields{
1351 "OnuId": trafficSchedulers.OnuId,
1352 "IntfId": trafficSchedulers.IntfId,
1353 "OnuPortNo": trafficSchedulers.PortNo,
1354 }).Info("received CreateTrafficSchedulers")
1355
1356 if !s.enablePerf {
1357 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1358 if err != nil {
1359 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1360 return new(openolt.Empty), err
1361 }
1362 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1363 if err != nil {
1364 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1365 return new(openolt.Empty), err
1366 }
1367 onu.TrafficSchedulers = trafficSchedulers
1368 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001369 return new(openolt.Empty), nil
1370}
1371
Shrey Baid688b4242020-07-10 20:40:10 +05301372func (s *OltDevice) RemoveTrafficSchedulers(context context.Context, trafficSchedulers *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Anand S Katti09541352020-01-29 15:54:01 +05301373 oltLogger.WithFields(log.Fields{
1374 "OnuId": trafficSchedulers.OnuId,
1375 "IntfId": trafficSchedulers.IntfId,
1376 "OnuPortNo": trafficSchedulers.PortNo,
1377 }).Info("received RemoveTrafficSchedulers")
1378 if !s.enablePerf {
1379 pon, err := s.GetPonById(trafficSchedulers.IntfId)
1380 if err != nil {
1381 oltLogger.Errorf("Error retrieving PON by IntfId: %v", err)
1382 return new(openolt.Empty), err
1383 }
1384 onu, err := pon.GetOnuById(trafficSchedulers.OnuId)
1385 if err != nil {
1386 oltLogger.Errorf("Error retrieving ONU from pon by OnuId: %v", err)
1387 return new(openolt.Empty), err
1388 }
1389
1390 onu.TrafficSchedulers = nil
1391 }
Matteo Scandolod54283a2019-08-13 16:22:31 -07001392 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001393}
Scott Baker41724b82020-01-21 19:54:53 -08001394
1395// assumes caller has properly formulated an openolt.AlarmIndication
Shrey Baid688b4242020-07-10 20:40:10 +05301396func (o *OltDevice) SendAlarmIndication(context context.Context, ind *openolt.AlarmIndication) error {
Scott Baker41724b82020-01-21 19:54:53 -08001397 msg := Message{
1398 Type: AlarmIndication,
1399 Data: ind,
1400 }
1401
1402 o.channel <- msg
1403 return nil
1404}