blob: bfaa5fd17115430a7917df4a402265257a6da57b [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"
21 "errors"
22 "fmt"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070023 "github.com/google/gopacket"
24 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070025 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070026 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070027 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
William Kurkian9dadc5b2019-10-22 13:51:57 -040028 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070029 "github.com/opencord/voltha-protos/go/openolt"
Matteo Scandolod54283a2019-08-13 16:22:31 -070030 "github.com/opencord/voltha-protos/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070031 log "github.com/sirupsen/logrus"
32 "google.golang.org/grpc"
33 "net"
34 "sync"
35)
36
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070037var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070038 "module": "OLT",
39})
40
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070041type OltDevice struct {
42 // BBSIM Internals
43 ID int
44 SerialNumber string
45 NumNni int
46 NumPon int
47 NumOnuPerPon int
48 InternalState *fsm.FSM
49 channel chan Message
50 oltDoneChannel *chan bool
51 apiDoneChannel *chan bool
52 nniPktInChannel chan *bbsim.PacketMsg
53
Matteo Scandolo27428702019-10-11 16:21:16 -070054 Pons []*PonPort
55 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070056
57 // OLT Attributes
58 OperState *fsm.FSM
Matteo Scandolo4747d292019-08-05 11:50:18 -070059}
60
Matteo Scandolo27428702019-10-11 16:21:16 -070061var olt OltDevice
Matteo Scandolo84f7d482019-08-08 19:00:47 -070062
Matteo Scandolo27428702019-10-11 16:21:16 -070063func GetOLT() *OltDevice {
64 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070065}
66
Matteo Scandolo40e067f2019-10-16 16:59:41 -070067func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, oltDoneChannel *chan bool, apiDoneChannel *chan bool, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070068 oltLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070069 "ID": oltId,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070070 "NumNni": nni,
71 "NumPon": pon,
72 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070073 }).Debug("CreateOLT")
74
Matteo Scandolo84f7d482019-08-08 19:00:47 -070075 olt = OltDevice{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070076 ID: oltId,
77 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070078 OperState: getOperStateFSM(func(e *fsm.Event) {
79 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
80 }),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070081 NumNni: nni,
82 NumPon: pon,
83 NumOnuPerPon: onuPerPon,
Matteo Scandolo27428702019-10-11 16:21:16 -070084 Pons: []*PonPort{},
85 Nnis: []*NniPort{},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070086 channel: make(chan Message),
87 oltDoneChannel: oltDoneChannel,
88 apiDoneChannel: apiDoneChannel,
89 nniPktInChannel: make(chan *bbsim.PacketMsg, 1024), // packets coming in from the NNI and going to VOLTHA
Matteo Scandolo4747d292019-08-05 11:50:18 -070090 }
91
92 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070093 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -070094 olt.InternalState = fsm.NewFSM(
95 "created",
96 fsm.Events{
97 {Name: "enable", Src: []string{"created"}, Dst: "enabled"},
98 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
99 },
100 fsm.Callbacks{
101 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700102 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700103 },
104 },
105 )
106
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700107 if isMock != true {
108 // create NNI Port
109 nniPort, err := CreateNNI(&olt)
110 if err != nil {
111 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
112 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700113
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700114 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700115 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700116
Matteo Scandolo4747d292019-08-05 11:50:18 -0700117 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700118 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700119 for i := 0; i < pon; i++ {
120 p := PonPort{
121 NumOnu: olt.NumOnuPerPon,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700122 ID: uint32(i),
123 Type: "pon",
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700124 Olt: olt,
Matteo Scandolo27428702019-10-11 16:21:16 -0700125 Onus: []*Onu{},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700126 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700127 p.OperState = getOperStateFSM(func(e *fsm.Event) {
128 oltLogger.WithFields(log.Fields{
129 "ID": p.ID,
130 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
131 })
Matteo Scandolo4747d292019-08-05 11:50:18 -0700132
133 // create ONU devices
134 for j := 0; j < onuPerPon; j++ {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700135 o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700136 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700137 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700138 }
139
Matteo Scandolo27428702019-10-11 16:21:16 -0700140 olt.Pons = append(olt.Pons, &p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700141 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700142 return &olt
143}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700144
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700145// this function start the OLT gRPC server and blocks until it's done
146func StartOlt(olt *OltDevice, group *sync.WaitGroup) {
147 newOltServer(*olt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700148 group.Done()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700149}
150
151func newOltServer(o OltDevice) error {
152 // TODO make configurable
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700153 address := "0.0.0.0:50060"
Matteo Scandolo4747d292019-08-05 11:50:18 -0700154 lis, err := net.Listen("tcp", address)
155 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700156 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157 }
158 grpcServer := grpc.NewServer()
159 openolt.RegisterOpenoltServer(grpcServer, o)
160
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700161 wg := sync.WaitGroup{}
162 wg.Add(1)
163
Matteo Scandolo4747d292019-08-05 11:50:18 -0700164 go grpcServer.Serve(lis)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700165 oltLogger.Debugf("OLT Listening on: %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700167 for {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700168 _, ok := <-*o.oltDoneChannel
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700169 if !ok {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700170 // if the olt Channel is closed, stop the gRPC server
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700171 log.Warnf("Stopping OLT gRPC server")
172 grpcServer.Stop()
173 wg.Done()
174 break
175 }
176 }
177
178 wg.Wait()
179
Matteo Scandolo4747d292019-08-05 11:50:18 -0700180 return nil
181}
182
183// Device Methods
184
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700185func (o OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700186
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700187 oltLogger.Debug("Enable OLT called")
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700188
Matteo Scandolo4747d292019-08-05 11:50:18 -0700189 wg := sync.WaitGroup{}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700190 wg.Add(2)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700191
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700192 // create a Channel for all the OLT events
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700193 go o.processOltMessages(stream)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700194 go o.processNniPacketIns(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700195
196 // enable the OLT
197 olt_msg := Message{
198 Type: OltIndication,
199 Data: OltIndicationMessage{
200 OperState: UP,
201 },
202 }
203 o.channel <- olt_msg
204
205 // send NNI Port Indications
206 for _, nni := range o.Nnis {
207 msg := Message{
208 Type: NniIndication,
209 Data: NniIndicationMessage{
210 OperState: UP,
211 NniPortID: nni.ID,
212 },
213 }
214 o.channel <- msg
215 }
William Kurkian9dadc5b2019-10-22 13:51:57 -0400216 go o.processOmciMessages()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700217 // send PON Port indications
218 for _, pon := range o.Pons {
219 msg := Message{
220 Type: PonIndication,
221 Data: PonIndicationMessage{
222 OperState: UP,
223 PonPortID: pon.ID,
224 },
225 }
226 o.channel <- msg
227
228 for _, onu := range pon.Onus {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700229 go onu.ProcessOnuMessages(stream, nil)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700230 // FIXME move the message generation in the state transition
231 // from here only invoke the state transition
Matteo Scandolo4747d292019-08-05 11:50:18 -0700232 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700233 Type: OnuDiscIndication,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700234 Data: OnuDiscIndicationMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700235 Onu: onu,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700236 OperState: UP,
237 },
238 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700239 onu.Channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700240 }
241 }
242
243 wg.Wait()
244 return nil
245}
246
William Kurkian9dadc5b2019-10-22 13:51:57 -0400247func (o OltDevice) processOmciMessages() {
248 ch := omcisim.GetChannel()
249
250 oltLogger.Debug("Started OMCI Indication Channel")
251
252 for message := range ch {
253 onuId := message.Data.OnuId
254 intfId := message.Data.IntfId
255 onu, err := o.FindOnuById(intfId, onuId)
256 if err != nil {
257 oltLogger.Errorf("Failed to find onu: %v", err)
258 }
259 go onu.processOmciMessage(message)
260 }
261}
262
Matteo Scandolo4747d292019-08-05 11:50:18 -0700263// Helpers method
264
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700265func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700266 for _, pon := range o.Pons {
267 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700268 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700269 }
270 }
271 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
272}
273
274func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
275 for _, nni := range o.Nnis {
276 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700277 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700278 }
279 }
280 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
281}
282
Matteo Scandolo4747d292019-08-05 11:50:18 -0700283func (o OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
284 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
285 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700286 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700287 }
288
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700289 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700290 "OperState": msg.OperState,
291 }).Debug("Sent Indication_OltInd")
292}
293
294func (o OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
295 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700296 nni.OperState.Event("enable")
297 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700298 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700299 Type: nni.Type,
300 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700301 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700302 }}
303
304 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700305 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700306 }
307
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700308 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700309 "Type": nni.Type,
310 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700311 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700312 }).Debug("Sent Indication_IntfOperInd for NNI")
313}
314
315func (o OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700316 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700317 pon.OperState.Event("enable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700318 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700319 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700320 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700321 }}
322
323 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700324 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700325 }
326
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700327 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700328 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700329 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700330 }).Debug("Sent Indication_IntfInd")
331
332 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700333 Type: pon.Type,
334 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700335 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700336 }}
337
338 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700339 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700340 }
341
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700342 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700343 "Type": pon.Type,
344 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700345 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700346 }).Debug("Sent Indication_IntfOperInd for PON")
347}
348
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700349func (o OltDevice) processOltMessages(stream openolt.Openolt_EnableIndicationServer) {
350 oltLogger.Debug("Started OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700351 for message := range o.channel {
352
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700353 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700354 "oltId": o.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700355 "messageType": message.Type,
356 }).Trace("Received message")
357
358 switch message.Type {
359 case OltIndication:
360 msg, _ := message.Data.(OltIndicationMessage)
361 if msg.OperState == UP {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700362 o.InternalState.Event("enable")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700363 o.OperState.Event("enable")
364 } else if msg.OperState == DOWN {
365 o.InternalState.Event("disable")
366 o.OperState.Event("disable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700367 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700368 o.sendOltIndication(msg, stream)
369 case NniIndication:
370 msg, _ := message.Data.(NniIndicationMessage)
371 o.sendNniIndication(msg, stream)
372 case PonIndication:
373 msg, _ := message.Data.(PonIndicationMessage)
374 o.sendPonIndication(msg, stream)
375 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700376 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700377 }
378
379 }
380}
381
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700382func (o OltDevice) processNniPacketIns(stream openolt.Openolt_EnableIndicationServer) {
383 oltLogger.WithFields(log.Fields{
384 "nniChannel": o.nniPktInChannel,
385 }).Debug("Started NNI Channel")
386 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
387 for message := range o.nniPktInChannel {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700388 oltLogger.Tracef("Received packets on NNI Channel")
389
390 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
391
392 if err != nil {
393 log.WithFields(log.Fields{
394 "IntfType": "nni",
395 "IntfId": nniId,
396 "Pkt": message.Pkt.Data(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700397 }).Error("Can't find Dst MacAddress in packet")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700398 return
399 }
400
401 onu, err := o.FindOnuByMacAddress(onuMac)
402 if err != nil {
403 log.WithFields(log.Fields{
404 "IntfType": "nni",
405 "IntfId": nniId,
406 "Pkt": message.Pkt.Data(),
407 "MacAddress": onuMac.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700408 }).Error("Can't find ONU with MacAddress")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700409 return
410 }
411
412 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
413 if err != nil {
414 log.Error("Fail to add double tag to packet")
415 }
416
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700417 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
418 IntfType: "nni",
419 IntfId: nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700420 Pkt: doubleTaggedPkt.Data()}}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700421 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
422 oltLogger.WithFields(log.Fields{
423 "IntfType": data.PktInd.IntfType,
424 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700425 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700426 }).Errorf("Fail to send PktInd indication: %v", err)
427 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700428 oltLogger.WithFields(log.Fields{
429 "IntfType": data.PktInd.IntfType,
430 "IntfId": nniId,
431 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700432 "OnuSn": onu.Sn(),
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700433 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700434 }
435}
436
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700437// returns an ONU with a given Serial Number
438func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
439 // TODO this function can be a perfoormance bottlenec when we have many ONUs,
440 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700441 for _, pon := range o.Pons {
442 for _, onu := range pon.Onus {
443 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700444 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700445 }
446 }
447 }
448
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700449 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
450}
451
William Kurkian9dadc5b2019-10-22 13:51:57 -0400452// returns an ONU with a given interface/Onu Id
453func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
454 // TODO this function can be a performance bottlenec when we have many ONUs,
455 // memoizing it will remove the bottleneck
456 for _, pon := range o.Pons {
457 if pon.ID == intfId {
458 for _, onu := range pon.Onus {
459 if onu.ID == onuId {
460 return onu, nil
461 }
462 }
463 }
464 }
465 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
466}
467
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700468// returns an ONU with a given Mac Address
469func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
470 // TODO this function can be a perfoormance bottlenec when we have many ONUs,
471 // memoizing it will remove the bottleneck
472 for _, pon := range o.Pons {
473 for _, onu := range pon.Onus {
474 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700475 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700476 }
477 }
478 }
479
480 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700481}
482
Matteo Scandolo4747d292019-08-05 11:50:18 -0700483// GRPC Endpoints
484
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700485func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700486 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700487 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700488 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700489
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700490 pon, _ := o.GetPonById(onu.IntfId)
491 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700492
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700493 if err := _onu.OperState.Event("enable"); err != nil {
494 oltLogger.WithFields(log.Fields{
495 "IntfId": _onu.PonPortID,
496 "OnuSn": _onu.Sn(),
497 "OnuId": _onu.ID,
498 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700499 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700500 if err := _onu.InternalState.Event("enable"); err != nil {
501 oltLogger.WithFields(log.Fields{
502 "IntfId": _onu.PonPortID,
503 "OnuSn": _onu.Sn(),
504 "OnuId": _onu.ID,
505 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
506 }
507
508 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
509
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700510 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700511}
512
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700513func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700514 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700515 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700516}
517
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700518func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700519 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700520 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700521}
522
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700523func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700524 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
525 olt_msg := Message{
526 Type: OltIndication,
527 Data: OltIndicationMessage{
528 OperState: DOWN,
529 },
530 }
531 o.channel <- olt_msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700532 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700533}
534
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700535func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700536 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700537 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700538}
539
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700540func (o OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700541 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700542 o.Enable(stream)
543 return nil
544}
545
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700546func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700547 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700548 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700549}
550
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700551func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700552 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700553 "IntfId": flow.AccessIntfId,
554 "OnuId": flow.OnuId,
555 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700556 "InnerVlan": flow.Classifier.IVid,
557 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700558 "FlowType": flow.FlowType,
559 "FlowId": flow.FlowId,
560 "UniID": flow.UniId,
561 "PortNo": flow.PortNo,
562 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700563 // TODO optionally store flows somewhere
564
565 if flow.AccessIntfId == -1 {
566 oltLogger.WithFields(log.Fields{
567 "FlowId": flow.FlowId,
568 }).Debugf("This is an OLT flow")
569 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700570 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700571 if err != nil {
572 oltLogger.WithFields(log.Fields{
573 "OnuId": flow.OnuId,
574 "IntfId": flow.AccessIntfId,
575 "err": err,
576 }).Error("Can't find PonPort")
577 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700578 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700579 if err != nil {
580 oltLogger.WithFields(log.Fields{
581 "OnuId": flow.OnuId,
582 "IntfId": flow.AccessIntfId,
583 "err": err,
584 }).Error("Can't find Onu")
585 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700586
587 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700588 Type: FlowUpdate,
589 Data: OnuFlowUpdateMessage{
590 PonPortID: pon.ID,
591 OnuID: onu.ID,
592 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700593 },
594 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700595 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700596 }
597
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700598 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700599}
600
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700601func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
602 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700603 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700604 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700605}
606
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700607func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700608 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700609 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700610}
611
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700612func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700613
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700614 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700615 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700616 "PonPorts": o.NumPon,
617 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700618 devinfo := new(openolt.DeviceInfo)
619 devinfo.Vendor = "BBSim"
620 devinfo.Model = "asfvolt16"
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700621 devinfo.HardwareVersion = "emulated"
Matteo Scandolo4747d292019-08-05 11:50:18 -0700622 devinfo.FirmwareVersion = ""
623 devinfo.Technology = "xgspon"
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700624 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700625 devinfo.OnuIdStart = 1
626 devinfo.OnuIdEnd = 255
627 devinfo.AllocIdStart = 1024
628 devinfo.AllocIdEnd = 16383
629 devinfo.GemportIdStart = 1024
630 devinfo.GemportIdEnd = 65535
631 devinfo.FlowIdStart = 1
632 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700633 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4747d292019-08-05 11:50:18 -0700634
635 return devinfo, nil
636}
637
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700638func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700639 pon, _ := o.GetPonById(omci_msg.IntfId)
640 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700641 oltLogger.WithFields(log.Fields{
642 "IntfId": onu.PonPortID,
643 "OnuId": onu.ID,
644 "OnuSn": onu.Sn(),
645 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700646 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700647 Type: OMCI,
648 Data: OmciMessage{
649 OnuSN: onu.SerialNumber,
650 OnuID: onu.ID,
651 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700652 },
653 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700654 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700655 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700656}
657
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700658func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700659 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700660 if err != nil {
661 oltLogger.WithFields(log.Fields{
662 "OnuId": onuPkt.OnuId,
663 "IntfId": onuPkt.IntfId,
664 "err": err,
665 }).Error("Can't find PonPort")
666 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700667 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700668 if err != nil {
669 oltLogger.WithFields(log.Fields{
670 "OnuId": onuPkt.OnuId,
671 "IntfId": onuPkt.IntfId,
672 "err": err,
673 }).Error("Can't find Onu")
674 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700675
Matteo Scandolo075b1892019-10-07 12:11:07 -0700676 oltLogger.WithFields(log.Fields{
677 "IntfId": onu.PonPortID,
678 "OnuId": onu.ID,
679 "OnuSn": onu.Sn(),
680 }).Tracef("Received OnuPacketOut")
681
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700682 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700683 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700684
Matteo Scandolo075b1892019-10-07 12:11:07 -0700685 msg := Message{
686 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700687 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -0700688 IntfId: onuPkt.IntfId,
689 OnuId: onuPkt.OnuId,
690 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700691 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700692 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700693 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700694 onu.Channel <- msg
695
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700696 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700697}
698
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700699func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700700 oltLogger.Info("Shutting Down")
701 close(*o.oltDoneChannel)
702 close(*o.apiDoneChannel)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700703 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700704}
705
706func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700707 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700708 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700709}
710
711func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700712 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
713
714 sendNniPacket(pkt)
715 // NOTE should we return an error if sendNniPakcet fails?
716 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700717}
718
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700719func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700720 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700721 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700722}
723
Matteo Scandolo4747d292019-08-05 11:50:18 -0700724func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700725 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700726 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700727}
728
729func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700730 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700731 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700732}
733
734func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700735 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700736 return new(openolt.Empty), nil
737}
738
739func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700740 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700741 return new(openolt.Empty), nil
742}
743
744func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700745 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700746 return new(openolt.Empty), nil
747}
748
749func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700750 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700751 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700752}