blob: 5d6e5719a152ab4f8c4d734917d9774d0c449184 [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"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020023 "net"
24 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010025 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020026
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070027 "github.com/google/gopacket"
28 "github.com/google/gopacket/layers"
Matteo 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"
35 "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"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010038 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070039)
40
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070041var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070042 "module": "OLT",
43})
44
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070045type OltDevice struct {
46 // BBSIM Internals
47 ID int
48 SerialNumber string
49 NumNni int
50 NumPon int
51 NumOnuPerPon int
52 InternalState *fsm.FSM
53 channel chan Message
Zdravko Bozakov681364d2019-11-10 14:28:46 +010054 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070055
Matteo Scandoloe33447a2019-10-31 12:38:23 -070056 Delay int
57
Matteo Scandolo27428702019-10-11 16:21:16 -070058 Pons []*PonPort
59 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070060
61 // OLT Attributes
62 OperState *fsm.FSM
Matteo Scandolo4747d292019-08-05 11:50:18 -070063}
64
Matteo Scandolo27428702019-10-11 16:21:16 -070065var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010066var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070067
Matteo Scandolo27428702019-10-11 16:21:16 -070068func GetOLT() *OltDevice {
69 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070070}
71
Zdravko Bozakov681364d2019-11-10 14:28:46 +010072func CreateOLT(oltId int, nni int, pon int, onuPerPon int, sTag int, cTagInit int, auth bool, dhcp bool, delay int, isMock bool) *OltDevice {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070073 oltLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070074 "ID": oltId,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070075 "NumNni": nni,
76 "NumPon": pon,
77 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070078 }).Debug("CreateOLT")
79
Matteo Scandolo84f7d482019-08-08 19:00:47 -070080 olt = OltDevice{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070081 ID: oltId,
82 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070083 OperState: getOperStateFSM(func(e *fsm.Event) {
84 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
85 }),
Zdravko Bozakov681364d2019-11-10 14:28:46 +010086 NumNni: nni,
87 NumPon: pon,
88 NumOnuPerPon: onuPerPon,
89 Pons: []*PonPort{},
90 Nnis: []*NniPort{},
91 Delay: delay,
Matteo Scandolo4747d292019-08-05 11:50:18 -070092 }
93
94 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070095 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -070096 olt.InternalState = fsm.NewFSM(
97 "created",
98 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -080099 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100100 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700101 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800102 {Name: "delete", Src: []string{"disabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700103 },
104 fsm.Callbacks{
105 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700106 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700107 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100108 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700109 },
110 )
111
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700112 if isMock != true {
113 // create NNI Port
114 nniPort, err := CreateNNI(&olt)
115 if err != nil {
116 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
117 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700118
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700119 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700120 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700121
Matteo Scandolo4747d292019-08-05 11:50:18 -0700122 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700123 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700124 for i := 0; i < pon; i++ {
125 p := PonPort{
126 NumOnu: olt.NumOnuPerPon,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700127 ID: uint32(i),
128 Type: "pon",
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700129 Olt: olt,
Matteo Scandolo27428702019-10-11 16:21:16 -0700130 Onus: []*Onu{},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700131 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700132 p.OperState = getOperStateFSM(func(e *fsm.Event) {
133 oltLogger.WithFields(log.Fields{
134 "ID": p.ID,
135 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
136 })
Matteo Scandolo4747d292019-08-05 11:50:18 -0700137
138 // create ONU devices
139 for j := 0; j < onuPerPon; j++ {
Matteo Scandoloc1147092019-10-29 09:38:33 -0700140 o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag, auth, dhcp)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700141 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700142 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700143 }
144
Matteo Scandolo27428702019-10-11 16:21:16 -0700145 olt.Pons = append(olt.Pons, &p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700146 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100147
Matteo Scandolod32c3822019-11-26 15:57:46 -0700148 if isMock != true {
149 if err := olt.InternalState.Event("initialize"); err != nil {
150 log.Errorf("Error initializing OLT: %v", err)
151 return nil
152 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100153 }
154
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700155 return &olt
156}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700157
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100158func (o *OltDevice) InitOlt() error {
159
160 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800161 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100162 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800163 // FIXME there should never be a server running if we are initializing the OLT
164 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100165 }
166
167 // create new channel for processOltMessages Go routine
168 o.channel = make(chan Message)
169
170 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
171 // FIXME we are assuming we have only one NNI
172 if o.Nnis[0] != nil {
173 ch, err := o.Nnis[0].NewVethChan()
174 if err == nil {
175 o.nniPktInChannel = ch
176 } else {
177 log.Errorf("Error getting NNI channel: %v", err)
178 }
179 }
180
181 for i := range olt.Pons {
182 for _, onu := range olt.Pons[i].Onus {
183 if err := onu.InternalState.Event("initialize"); err != nil {
184 log.Errorf("Error initializing ONU: %v", err)
185 return err
186 }
187 }
188 }
189
190 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700191}
192
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800193func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100194
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800195 rebootDelay := common.Options.Olt.OltRebootDelay
196
197 oltLogger.WithFields(log.Fields{
198 "oltId": o.ID,
199 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
200
201 // transition internal state to deleted
202 if err := o.InternalState.Event("delete"); err != nil {
203 oltLogger.WithFields(log.Fields{
204 "oltId": o.ID,
205 }).Errorf("Error deleting OLT: %v", err)
206 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100207 }
208
209 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800210 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
211 if err := o.StopOltServer(); err != nil {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 return err
213 }
214
215 // terminate the OLT's processOltMessages go routine
216 close(o.channel)
217 // terminate the OLT's processNniPacketIns go routine
218 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100219
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100220 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100221
222 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800223 oltLogger.WithFields(log.Fields{
224 "oltId": o.ID,
225 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100226 return err
227 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800228 oltLogger.WithFields(log.Fields{
229 "oltId": o.ID,
230 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 return nil
232}
233
234// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800235func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100236 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700237 lis, err := net.Listen("tcp", address)
238 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700239 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700240 }
241 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100242
Matteo Scandolo4747d292019-08-05 11:50:18 -0700243 openolt.RegisterOpenoltServer(grpcServer, o)
244
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100245 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700246
Matteo Scandolo4747d292019-08-05 11:50:18 -0700247 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100248 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700249
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100250 return grpcServer, nil
251}
252
253// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800254func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100255 // TODO handle poweroff vs graceful shutdown
256 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800257 oltLogger.WithFields(log.Fields{
258 "oltId": o.SerialNumber,
259 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100260 oltServer.Stop()
261 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700262 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800263
Matteo Scandolo4747d292019-08-05 11:50:18 -0700264 return nil
265}
266
267// Device Methods
268
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100269// Enable implements the OpenOLT EnableIndicationServer functionality
270func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700271 oltLogger.Debug("Enable OLT called")
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700272
Matteo Scandolo4747d292019-08-05 11:50:18 -0700273 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800274 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700275
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100276 // create Go routine to process all OLT events
277 go o.processOltMessages(stream, &wg)
278 go o.processNniPacketIns(stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700279
280 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100281 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700282 Type: OltIndication,
283 Data: OltIndicationMessage{
284 OperState: UP,
285 },
286 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100287 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700288
289 // send NNI Port Indications
290 for _, nni := range o.Nnis {
291 msg := Message{
292 Type: NniIndication,
293 Data: NniIndicationMessage{
294 OperState: UP,
295 NniPortID: nni.ID,
296 },
297 }
298 o.channel <- msg
299 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100300
William Kurkian9dadc5b2019-10-22 13:51:57 -0400301 go o.processOmciMessages()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100302
Matteo Scandolo4747d292019-08-05 11:50:18 -0700303 // send PON Port indications
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100304 for i, pon := range o.Pons {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700305 msg := Message{
306 Type: PonIndication,
307 Data: PonIndicationMessage{
308 OperState: UP,
309 PonPortID: pon.ID,
310 },
311 }
312 o.channel <- msg
313
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100314 for _, onu := range o.Pons[i].Onus {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700315 go onu.ProcessOnuMessages(stream, nil)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100316 if err := onu.InternalState.Event("discover"); err != nil {
317 log.Errorf("Error discover ONU: %v", err)
318 return err
Matteo Scandolo4747d292019-08-05 11:50:18 -0700319 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700320 }
321 }
322
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800323 oltLogger.Debug("Enable OLT Done")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700324 wg.Wait()
325 return nil
326}
327
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100328func (o *OltDevice) processOmciMessages() {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400329 ch := omcisim.GetChannel()
330
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100331 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400332
333 for message := range ch {
334 onuId := message.Data.OnuId
335 intfId := message.Data.IntfId
336 onu, err := o.FindOnuById(intfId, onuId)
337 if err != nil {
338 oltLogger.Errorf("Failed to find onu: %v", err)
339 }
340 go onu.processOmciMessage(message)
341 }
342}
343
Matteo Scandolo4747d292019-08-05 11:50:18 -0700344// Helpers method
345
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700346func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700347 for _, pon := range o.Pons {
348 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700349 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700350 }
351 }
352 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
353}
354
355func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
356 for _, nni := range o.Nnis {
357 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700358 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700359 }
360 }
361 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
362}
363
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100364func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700365 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
366 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700367 oltLogger.Errorf("Failed to send Indication_OltInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800368 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700369 }
370
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700371 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700372 "OperState": msg.OperState,
373 }).Debug("Sent Indication_OltInd")
374}
375
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100376func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700377 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700378 nni.OperState.Event("enable")
379 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700380 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700381 Type: nni.Type,
382 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700383 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700384 }}
385
386 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700387 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800388 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700389 }
390
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700391 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700392 "Type": nni.Type,
393 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700394 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700395 }).Debug("Sent Indication_IntfOperInd for NNI")
396}
397
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100398func (o *OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700399 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700400 pon.OperState.Event("enable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700401 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700402 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700403 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700404 }}
405
406 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700407 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800408 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700409 }
410
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700411 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700412 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700413 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700414 }).Debug("Sent Indication_IntfInd")
415
416 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700417 Type: pon.Type,
418 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700419 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700420 }}
421
422 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700423 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800424 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700425 }
426
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700427 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700428 "Type": pon.Type,
429 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700430 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431 }).Debug("Sent Indication_IntfOperInd for PON")
432}
433
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100434// processOltMessages handles messages received over the OpenOLT interface
435func (o *OltDevice) processOltMessages(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
436 oltLogger.Debug("Starting OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700437 for message := range o.channel {
438
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700439 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700440 "oltId": o.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700441 "messageType": message.Type,
442 }).Trace("Received message")
443
444 switch message.Type {
445 case OltIndication:
446 msg, _ := message.Data.(OltIndicationMessage)
447 if msg.OperState == UP {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700448 o.InternalState.Event("enable")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700449 o.OperState.Event("enable")
450 } else if msg.OperState == DOWN {
451 o.InternalState.Event("disable")
452 o.OperState.Event("disable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700453 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700454 o.sendOltIndication(msg, stream)
455 case NniIndication:
456 msg, _ := message.Data.(NniIndicationMessage)
457 o.sendNniIndication(msg, stream)
458 case PonIndication:
459 msg, _ := message.Data.(PonIndicationMessage)
460 o.sendPonIndication(msg, stream)
461 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700462 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700463 }
464
465 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100466 wg.Done()
467 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700468}
469
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100470// processNniPacketIns handles messages received over the NNI interface
471func (o *OltDevice) processNniPacketIns(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700472 oltLogger.WithFields(log.Fields{
473 "nniChannel": o.nniPktInChannel,
474 }).Debug("Started NNI Channel")
475 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
476 for message := range o.nniPktInChannel {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700477 oltLogger.Tracef("Received packets on NNI Channel")
478
479 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
480
481 if err != nil {
482 log.WithFields(log.Fields{
483 "IntfType": "nni",
484 "IntfId": nniId,
485 "Pkt": message.Pkt.Data(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700486 }).Error("Can't find Dst MacAddress in packet")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700487 return
488 }
489
490 onu, err := o.FindOnuByMacAddress(onuMac)
491 if err != nil {
492 log.WithFields(log.Fields{
493 "IntfType": "nni",
494 "IntfId": nniId,
495 "Pkt": message.Pkt.Data(),
496 "MacAddress": onuMac.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700497 }).Error("Can't find ONU with MacAddress")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700498 return
499 }
500
501 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
502 if err != nil {
503 log.Error("Fail to add double tag to packet")
504 }
505
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700506 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
507 IntfType: "nni",
508 IntfId: nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700509 Pkt: doubleTaggedPkt.Data()}}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700510 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
511 oltLogger.WithFields(log.Fields{
512 "IntfType": data.PktInd.IntfType,
513 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700514 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700515 }).Errorf("Fail to send PktInd indication: %v", err)
516 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700517 oltLogger.WithFields(log.Fields{
518 "IntfType": data.PktInd.IntfType,
519 "IntfId": nniId,
520 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700521 "OnuSn": onu.Sn(),
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700522 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700523 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100524 wg.Done()
525 oltLogger.WithFields(log.Fields{
526 "nniChannel": o.nniPktInChannel,
527 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700528}
529
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700530// returns an ONU with a given Serial Number
531func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200532 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700533 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700534 for _, pon := range o.Pons {
535 for _, onu := range pon.Onus {
536 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700537 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700538 }
539 }
540 }
541
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700542 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
543}
544
William Kurkian9dadc5b2019-10-22 13:51:57 -0400545// returns an ONU with a given interface/Onu Id
546func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200547 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400548 // memoizing it will remove the bottleneck
549 for _, pon := range o.Pons {
550 if pon.ID == intfId {
551 for _, onu := range pon.Onus {
552 if onu.ID == onuId {
553 return onu, nil
554 }
555 }
556 }
557 }
558 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
559}
560
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700561// returns an ONU with a given Mac Address
562func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200563 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700564 // memoizing it will remove the bottleneck
565 for _, pon := range o.Pons {
566 for _, onu := range pon.Onus {
567 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700568 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700569 }
570 }
571 }
572
573 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700574}
575
Matteo Scandolo4747d292019-08-05 11:50:18 -0700576// GRPC Endpoints
577
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700578func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700579 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700580 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700582
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700583 pon, _ := o.GetPonById(onu.IntfId)
584 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500585 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700586
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700587 if err := _onu.OperState.Event("enable"); err != nil {
588 oltLogger.WithFields(log.Fields{
589 "IntfId": _onu.PonPortID,
590 "OnuSn": _onu.Sn(),
591 "OnuId": _onu.ID,
592 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700593 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700594 if err := _onu.InternalState.Event("enable"); err != nil {
595 oltLogger.WithFields(log.Fields{
596 "IntfId": _onu.PonPortID,
597 "OnuSn": _onu.Sn(),
598 "OnuId": _onu.ID,
599 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
600 }
601
602 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
603
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) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700608 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700609 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700610}
611
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700612func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700613 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700614 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700615}
616
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700617func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700618 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800619 oltLogger.WithFields(log.Fields{
620 "oltId": o.ID,
621 }).Info("Disabling OLT")
622
623 for i, pon := range o.Pons {
624 // disable all onus
625 for _, onu := range o.Pons[i].Onus {
626 // NOTE order of these is important.
627 if err := onu.OperState.Event("disable"); err != nil {
628 log.Errorf("Error disabling ONU oper state: %v", err)
629 }
630 if err := onu.InternalState.Event("disable"); err != nil {
631 log.Errorf("Error disabling ONU: %v", err)
632 }
633 }
634
635 // disable PONs
636 msg := Message{
637 Type: PonIndication,
638 Data: PonIndicationMessage{
639 OperState: DOWN,
640 PonPortID: pon.ID,
641 },
642 }
643
644 o.channel <- msg
645 }
646
647 // disable NNI
648 for _, nni := range o.Nnis {
649 msg := Message{
650 Type: NniIndication,
651 Data: NniIndicationMessage{
652 OperState: DOWN,
653 NniPortID: nni.ID,
654 },
655 }
656 o.channel <- msg
657 }
658
659 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100660 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700661 Type: OltIndication,
662 Data: OltIndicationMessage{
663 OperState: DOWN,
664 },
665 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100666 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700667 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700668}
669
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700670func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700671 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700672 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700673}
674
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100675func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700676 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700677 o.Enable(stream)
678 return nil
679}
680
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700681func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700682 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700683 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700684}
685
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700686func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700687 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700688 "IntfId": flow.AccessIntfId,
689 "OnuId": flow.OnuId,
690 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700691 "InnerVlan": flow.Classifier.IVid,
692 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700693 "FlowType": flow.FlowType,
694 "FlowId": flow.FlowId,
695 "UniID": flow.UniId,
696 "PortNo": flow.PortNo,
697 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700698 // TODO optionally store flows somewhere
699
700 if flow.AccessIntfId == -1 {
701 oltLogger.WithFields(log.Fields{
702 "FlowId": flow.FlowId,
703 }).Debugf("This is an OLT flow")
704 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700705 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700706 if err != nil {
707 oltLogger.WithFields(log.Fields{
708 "OnuId": flow.OnuId,
709 "IntfId": flow.AccessIntfId,
710 "err": err,
711 }).Error("Can't find PonPort")
712 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700713 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700714 if err != nil {
715 oltLogger.WithFields(log.Fields{
716 "OnuId": flow.OnuId,
717 "IntfId": flow.AccessIntfId,
718 "err": err,
719 }).Error("Can't find Onu")
720 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700721
722 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700723 Type: FlowUpdate,
724 Data: OnuFlowUpdateMessage{
725 PonPortID: pon.ID,
726 OnuID: onu.ID,
727 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700728 },
729 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700730 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700731 }
732
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700733 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700734}
735
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700736func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
737 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700738 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700739 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700740}
741
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700742func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700743 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700744 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700745}
746
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700747func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700748
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700749 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700750 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700751 "PonPorts": o.NumPon,
752 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700753 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100754 devinfo.Vendor = common.Options.Olt.Vendor
755 devinfo.Model = common.Options.Olt.Model
756 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
757 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
758 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700759 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700760 devinfo.OnuIdStart = 1
761 devinfo.OnuIdEnd = 255
762 devinfo.AllocIdStart = 1024
763 devinfo.AllocIdEnd = 16383
764 devinfo.GemportIdStart = 1024
765 devinfo.GemportIdEnd = 65535
766 devinfo.FlowIdStart = 1
767 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700768 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100769 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -0700770
771 return devinfo, nil
772}
773
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700774func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700775 pon, _ := o.GetPonById(omci_msg.IntfId)
776 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700777 oltLogger.WithFields(log.Fields{
778 "IntfId": onu.PonPortID,
779 "OnuId": onu.ID,
780 "OnuSn": onu.Sn(),
781 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700782 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700783 Type: OMCI,
784 Data: OmciMessage{
785 OnuSN: onu.SerialNumber,
786 OnuID: onu.ID,
787 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700788 },
789 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700790 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700791 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700792}
793
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700794func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700795 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700796 if err != nil {
797 oltLogger.WithFields(log.Fields{
798 "OnuId": onuPkt.OnuId,
799 "IntfId": onuPkt.IntfId,
800 "err": err,
801 }).Error("Can't find PonPort")
802 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700803 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700804 if err != nil {
805 oltLogger.WithFields(log.Fields{
806 "OnuId": onuPkt.OnuId,
807 "IntfId": onuPkt.IntfId,
808 "err": err,
809 }).Error("Can't find Onu")
810 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700811
Matteo Scandolo075b1892019-10-07 12:11:07 -0700812 oltLogger.WithFields(log.Fields{
813 "IntfId": onu.PonPortID,
814 "OnuId": onu.ID,
815 "OnuSn": onu.Sn(),
816 }).Tracef("Received OnuPacketOut")
817
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700818 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700819 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700820
Matteo Scandolo075b1892019-10-07 12:11:07 -0700821 msg := Message{
822 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700823 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -0700824 IntfId: onuPkt.IntfId,
825 OnuId: onuPkt.OnuId,
826 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700827 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700828 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700829 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700830 onu.Channel <- msg
831
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700832 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700833}
834
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700835func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800836 oltLogger.WithFields(log.Fields{
837 "oltId": o.ID,
838 }).Info("Shutting down")
839 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700840 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700841}
842
843func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700844 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700845 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700846}
847
848func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700849 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
850
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100851 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700852 // NOTE should we return an error if sendNniPakcet fails?
853 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700854}
855
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700856func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700857 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700858 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700859}
860
Matteo Scandolo4747d292019-08-05 11:50:18 -0700861func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700862 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700863 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700864}
865
866func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700867 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700868 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700869}
870
871func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700872 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700873 return new(openolt.Empty), nil
874}
875
876func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700877 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700878 return new(openolt.Empty), nil
879}
880
881func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700882 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700883 return new(openolt.Empty), nil
884}
885
886func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700887 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700888 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700889}