blob: e6248e89aababca8a3285095d965a193162bf0ea [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 Scandolo4b3fc7e2019-09-17 16:49:54 -070026 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070027 "github.com/opencord/voltha-protos/go/openolt"
Matteo Scandolod54283a2019-08-13 16:22:31 -070028 "github.com/opencord/voltha-protos/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070029 log "github.com/sirupsen/logrus"
30 "google.golang.org/grpc"
31 "net"
32 "sync"
33)
34
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070035var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070036 "module": "OLT",
37})
38
Matteo Scandolo4747d292019-08-05 11:50:18 -070039func init() {
40 //log.SetReportCaller(true)
41 log.SetLevel(log.DebugLevel)
42}
43
Matteo Scandolo84f7d482019-08-08 19:00:47 -070044var olt = OltDevice{}
45
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070046func GetOLT() OltDevice {
Matteo Scandolo84f7d482019-08-08 19:00:47 -070047 return olt
48}
49
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070050func CreateOLT(seq int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, oltDoneChannel *chan bool, apiDoneChannel *chan bool, group *sync.WaitGroup) OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070051 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070052 "ID": seq,
53 "NumNni": nni,
54 "NumPon": pon,
55 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070056 }).Debug("CreateOLT")
57
Matteo Scandolo84f7d482019-08-08 19:00:47 -070058 olt = OltDevice{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070059 ID: seq,
Matteo Scandolo8df63df2019-09-12 10:34:32 -070060 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", seq),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070061 OperState: getOperStateFSM(func(e *fsm.Event) {
62 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
63 }),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070064 NumNni: nni,
65 NumPon: pon,
66 NumOnuPerPon: onuPerPon,
67 Pons: []PonPort{},
68 Nnis: []NniPort{},
69 channel: make(chan Message),
70 oltDoneChannel: oltDoneChannel,
71 apiDoneChannel: apiDoneChannel,
72 nniPktInChannel: make(chan *bbsim.PacketMsg, 1024), // packets coming in from the NNI and going to VOLTHA
Matteo Scandolo4747d292019-08-05 11:50:18 -070073 }
74
75 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070076 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -070077 olt.InternalState = fsm.NewFSM(
78 "created",
79 fsm.Events{
80 {Name: "enable", Src: []string{"created"}, Dst: "enabled"},
81 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
82 },
83 fsm.Callbacks{
84 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070085 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -070086 },
87 },
88 )
89
90 // create NNI Port
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070091 nniPort, err := CreateNNI(&olt)
92
93 if err != nil {
94 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -070095 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070096
Matteo Scandolo4747d292019-08-05 11:50:18 -070097 olt.Nnis = append(olt.Nnis, nniPort)
98
99 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700100 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700101 for i := 0; i < pon; i++ {
102 p := PonPort{
103 NumOnu: olt.NumOnuPerPon,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700104 ID: uint32(i),
105 Type: "pon",
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700106 Olt: olt,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700107 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700108 p.OperState = getOperStateFSM(func(e *fsm.Event) {
109 oltLogger.WithFields(log.Fields{
110 "ID": p.ID,
111 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
112 })
Matteo Scandolo4747d292019-08-05 11:50:18 -0700113
114 // create ONU devices
115 for j := 0; j < onuPerPon; j++ {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700116 //o := CreateONU(olt, p, uint32(onuId))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700117 o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700118 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700119 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700120 }
121
122 olt.Pons = append(olt.Pons, p)
123 }
124
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700125 newOltServer(olt)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700126
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700127 group.Done()
Matteo Scandolo4747d292019-08-05 11:50:18 -0700128 return olt
129}
130
131func newOltServer(o OltDevice) error {
132 // TODO make configurable
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700133 address := "0.0.0.0:50060"
Matteo Scandolo4747d292019-08-05 11:50:18 -0700134 lis, err := net.Listen("tcp", address)
135 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700136 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137 }
138 grpcServer := grpc.NewServer()
139 openolt.RegisterOpenoltServer(grpcServer, o)
140
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700141 wg := sync.WaitGroup{}
142 wg.Add(1)
143
Matteo Scandolo4747d292019-08-05 11:50:18 -0700144 go grpcServer.Serve(lis)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700145 oltLogger.Debugf("OLT Listening on: %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700147 for {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700148 _, ok := <-*o.oltDoneChannel
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700149 if !ok {
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700150 // if the olt Channel is closed, stop the gRPC server
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700151 log.Warnf("Stopping OLT gRPC server")
152 grpcServer.Stop()
153 wg.Done()
154 break
155 }
156 }
157
158 wg.Wait()
159
Matteo Scandolo4747d292019-08-05 11:50:18 -0700160 return nil
161}
162
163// Device Methods
164
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700165func (o OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700166
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700167 oltLogger.Debug("Enable OLT called")
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700168
Matteo Scandolo4747d292019-08-05 11:50:18 -0700169 wg := sync.WaitGroup{}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700170 wg.Add(2)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700171
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700172 // create a Channel for all the OLT events
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700173 go o.processOltMessages(stream)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700174 go o.processNniPacketIns(stream)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700175
176 // enable the OLT
177 olt_msg := Message{
178 Type: OltIndication,
179 Data: OltIndicationMessage{
180 OperState: UP,
181 },
182 }
183 o.channel <- olt_msg
184
185 // send NNI Port Indications
186 for _, nni := range o.Nnis {
187 msg := Message{
188 Type: NniIndication,
189 Data: NniIndicationMessage{
190 OperState: UP,
191 NniPortID: nni.ID,
192 },
193 }
194 o.channel <- msg
195 }
196
197 // send PON Port indications
198 for _, pon := range o.Pons {
199 msg := Message{
200 Type: PonIndication,
201 Data: PonIndicationMessage{
202 OperState: UP,
203 PonPortID: pon.ID,
204 },
205 }
206 o.channel <- msg
207
208 for _, onu := range pon.Onus {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700209 go onu.processOnuMessages(stream)
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700210 go onu.processOmciMessages(stream)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700211 // FIXME move the message generation in the state transition
212 // from here only invoke the state transition
Matteo Scandolo4747d292019-08-05 11:50:18 -0700213 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700214 Type: OnuDiscIndication,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700215 Data: OnuDiscIndicationMessage{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700216 Onu: onu,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700217 OperState: UP,
218 },
219 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700220 onu.Channel <- msg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700221 }
222 }
223
224 wg.Wait()
225 return nil
226}
227
228// Helpers method
229
230func (o OltDevice) getPonById(id uint32) (*PonPort, error) {
231 for _, pon := range o.Pons {
232 if pon.ID == id {
233 return &pon, nil
234 }
235 }
236 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
237}
238
239func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
240 for _, nni := range o.Nnis {
241 if nni.ID == id {
242 return &nni, nil
243 }
244 }
245 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
246}
247
Matteo Scandolo4747d292019-08-05 11:50:18 -0700248func (o OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
249 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
250 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700251 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700252 }
253
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700254 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700255 "OperState": msg.OperState,
256 }).Debug("Sent Indication_OltInd")
257}
258
259func (o OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
260 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700261 nni.OperState.Event("enable")
262 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700263 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700264 Type: nni.Type,
265 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700266 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700267 }}
268
269 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700270 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700271 }
272
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700273 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700274 "Type": nni.Type,
275 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700276 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700277 }).Debug("Sent Indication_IntfOperInd for NNI")
278}
279
280func (o OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
281 pon, _ := o.getPonById(msg.PonPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700282 pon.OperState.Event("enable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700283 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700284 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700285 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700286 }}
287
288 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700289 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700290 }
291
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700292 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700293 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700294 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700295 }).Debug("Sent Indication_IntfInd")
296
297 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700298 Type: pon.Type,
299 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700300 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700301 }}
302
303 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700304 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700305 }
306
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700307 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700308 "Type": pon.Type,
309 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700310 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700311 }).Debug("Sent Indication_IntfOperInd for PON")
312}
313
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700314func (o OltDevice) processOltMessages(stream openolt.Openolt_EnableIndicationServer) {
315 oltLogger.Debug("Started OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700316 for message := range o.channel {
317
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700318 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700319 "oltId": o.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700320 "messageType": message.Type,
321 }).Trace("Received message")
322
323 switch message.Type {
324 case OltIndication:
325 msg, _ := message.Data.(OltIndicationMessage)
326 if msg.OperState == UP {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700327 o.InternalState.Event("enable")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700328 o.OperState.Event("enable")
329 } else if msg.OperState == DOWN {
330 o.InternalState.Event("disable")
331 o.OperState.Event("disable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700332 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700333 o.sendOltIndication(msg, stream)
334 case NniIndication:
335 msg, _ := message.Data.(NniIndicationMessage)
336 o.sendNniIndication(msg, stream)
337 case PonIndication:
338 msg, _ := message.Data.(PonIndicationMessage)
339 o.sendPonIndication(msg, stream)
340 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700341 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700342 }
343
344 }
345}
346
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700347func (o OltDevice) processNniPacketIns(stream openolt.Openolt_EnableIndicationServer) {
348 oltLogger.WithFields(log.Fields{
349 "nniChannel": o.nniPktInChannel,
350 }).Debug("Started NNI Channel")
351 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
352 for message := range o.nniPktInChannel {
353 oltLogger.Debug("Received packets on NNI Channel")
354 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
355 IntfType: "nni",
356 IntfId: nniId,
357 Pkt: message.Pkt.Data()}}
358 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
359 oltLogger.WithFields(log.Fields{
360 "IntfType": data.PktInd.IntfType,
361 "IntfId": nniId,
362 "Pkt": message.Pkt.Data(),
363 }).Errorf("Fail to send PktInd indication: %v", err)
364 }
365 }
366}
367
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700368func (o OltDevice) FindOnu(serialNumber string) (*Onu, error) {
369
370 for _, pon := range o.Pons {
371 for _, onu := range pon.Onus {
372 if onu.Sn() == serialNumber {
373 return &onu, nil
374 }
375 }
376 }
377
378 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-%s", serialNumber))
379}
380
Matteo Scandolo4747d292019-08-05 11:50:18 -0700381// GRPC Endpoints
382
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700383func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700384 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700385 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700386 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700387
388 pon, _ := o.getPonById(onu.IntfId)
389 _onu, _ := pon.getOnuBySn(onu.SerialNumber)
390
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700391 if err := _onu.OperState.Event("enable"); err != nil {
392 oltLogger.WithFields(log.Fields{
393 "IntfId": _onu.PonPortID,
394 "OnuSn": _onu.Sn(),
395 "OnuId": _onu.ID,
396 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700397 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700398 if err := _onu.InternalState.Event("enable"); err != nil {
399 oltLogger.WithFields(log.Fields{
400 "IntfId": _onu.PonPortID,
401 "OnuSn": _onu.Sn(),
402 "OnuId": _onu.ID,
403 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
404 }
405
406 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
407
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700408 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700409}
410
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700411func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700412 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700413 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700414}
415
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700416func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700417 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700418 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700419}
420
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700421func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700422 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
423 olt_msg := Message{
424 Type: OltIndication,
425 Data: OltIndicationMessage{
426 OperState: DOWN,
427 },
428 }
429 o.channel <- olt_msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700430 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431}
432
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700433func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700434 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700435 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700436}
437
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700438func (o OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700439 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700440 o.Enable(stream)
441 return nil
442}
443
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700444func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700445 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700446 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700447}
448
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700449func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700450 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700451 "IntfId": flow.AccessIntfId,
452 "OnuId": flow.OnuId,
453 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700454 "InnerVlan": flow.Classifier.IVid,
455 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700456 "FlowType": flow.FlowType,
457 "FlowId": flow.FlowId,
458 "UniID": flow.UniId,
459 "PortNo": flow.PortNo,
460 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700461 // TODO optionally store flows somewhere
462
463 if flow.AccessIntfId == -1 {
464 oltLogger.WithFields(log.Fields{
465 "FlowId": flow.FlowId,
466 }).Debugf("This is an OLT flow")
467 } else {
468 pon, _ := o.getPonById(uint32(flow.AccessIntfId))
469 onu, _ := pon.getOnuById(uint32(flow.OnuId))
470
471 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700472 Type: FlowUpdate,
473 Data: OnuFlowUpdateMessage{
474 PonPortID: pon.ID,
475 OnuID: onu.ID,
476 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700477 },
478 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700479 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700480 }
481
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700482 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700483}
484
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700485func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
486 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700487 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700488 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700489}
490
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700491func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700492 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700493 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700494}
495
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700496func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700497
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700498 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700499 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700500 "PonPorts": o.NumPon,
501 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700502 devinfo := new(openolt.DeviceInfo)
503 devinfo.Vendor = "BBSim"
504 devinfo.Model = "asfvolt16"
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700505 devinfo.HardwareVersion = "emulated"
Matteo Scandolo4747d292019-08-05 11:50:18 -0700506 devinfo.FirmwareVersion = ""
507 devinfo.Technology = "xgspon"
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700508 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700509 devinfo.OnuIdStart = 1
510 devinfo.OnuIdEnd = 255
511 devinfo.AllocIdStart = 1024
512 devinfo.AllocIdEnd = 16383
513 devinfo.GemportIdStart = 1024
514 devinfo.GemportIdEnd = 65535
515 devinfo.FlowIdStart = 1
516 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700517 devinfo.DeviceSerialNumber = o.SerialNumber
Matteo Scandolo4747d292019-08-05 11:50:18 -0700518
519 return devinfo, nil
520}
521
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700522func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700523 pon, _ := o.getPonById(omci_msg.IntfId)
524 onu, _ := pon.getOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700525 oltLogger.WithFields(log.Fields{
526 "IntfId": onu.PonPortID,
527 "OnuId": onu.ID,
528 "OnuSn": onu.Sn(),
529 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700530 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700531 Type: OMCI,
532 Data: OmciMessage{
533 OnuSN: onu.SerialNumber,
534 OnuID: onu.ID,
535 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700536 },
537 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700538 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700539 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540}
541
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700542func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700543 pon, _ := o.getPonById(onuPkt.IntfId)
544 onu, _ := pon.getOnuById(onuPkt.OnuId)
545
546 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
547
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700548 etherType := rawpkt.Layer(layers.LayerTypeEthernet).(*layers.Ethernet).EthernetType
549
550 if etherType == layers.EthernetTypeEAPOL {
551 eapolPkt := bbsim.ByteMsg{IntfId: onuPkt.IntfId, OnuId: onuPkt.OnuId, Bytes: rawpkt.Data()}
552 onu.eapolPktOutCh <- &eapolPkt
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700553 } else if layerDHCP := rawpkt.Layer(layers.LayerTypeDHCPv4); layerDHCP != nil {
554 // TODO use IsDhcpPacket
555 // TODO we need to untag the packets
556 // NOTE here we receive packets going from the DHCP Server to the ONU
557 // for now we expect them to be double-tagged, but ideally the should be single tagged
558 dhcpPkt := bbsim.ByteMsg{IntfId: onuPkt.IntfId, OnuId: onuPkt.OnuId, Bytes: rawpkt.Data()}
559 onu.dhcpPktOutCh <- &dhcpPkt
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700560 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700561 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700562}
563
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700564func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700565 oltLogger.Info("Shutting Down")
566 close(*o.oltDoneChannel)
567 close(*o.apiDoneChannel)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700568 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700569}
570
571func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700572 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700573 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700574}
575
576func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700577 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
578
579 sendNniPacket(pkt)
580 // NOTE should we return an error if sendNniPakcet fails?
581 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582}
583
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700584func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700585 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700586 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700587}
588
Matteo Scandolo4747d292019-08-05 11:50:18 -0700589func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700590 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700591 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700592}
593
594func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700595 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700596 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700597}
598
599func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700600 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700601 return new(openolt.Empty), nil
602}
603
604func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700605 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700606 return new(openolt.Empty), nil
607}
608
609func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700610 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700611 return new(openolt.Empty), nil
612}
613
614func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700615 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700616 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700617}