blob: bde98cbae62768ee74da3fe9ac72810b717c11a9 [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)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700248 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 Scandolo4747d292019-08-05 11:50:18 -0700368 }
369
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700370 oltLogger.WithFields(log.Fields{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700371 "OperState": msg.OperState,
372 }).Debug("Sent Indication_OltInd")
373}
374
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100375func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700376 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700377 nni.OperState.Event("enable")
378 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700379 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700380 Type: nni.Type,
381 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700382 OperState: nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700383 }}
384
385 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700386 oltLogger.Errorf("Failed to send Indication_IntfOperInd for NNI: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700387 }
388
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700389 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700390 "Type": nni.Type,
391 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700392 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700393 }).Debug("Sent Indication_IntfOperInd for NNI")
394}
395
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100396func (o *OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700397 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700398 pon.OperState.Event("enable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700399 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700400 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700401 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700402 }}
403
404 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700405 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700406 }
407
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700408 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700409 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700410 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700411 }).Debug("Sent Indication_IntfInd")
412
413 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700414 Type: pon.Type,
415 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700416 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700417 }}
418
419 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700420 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700421 }
422
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700423 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700424 "Type": pon.Type,
425 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700426 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700427 }).Debug("Sent Indication_IntfOperInd for PON")
428}
429
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100430// processOltMessages handles messages received over the OpenOLT interface
431func (o *OltDevice) processOltMessages(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
432 oltLogger.Debug("Starting OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700433 for message := range o.channel {
434
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700435 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700436 "oltId": o.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700437 "messageType": message.Type,
438 }).Trace("Received message")
439
440 switch message.Type {
441 case OltIndication:
442 msg, _ := message.Data.(OltIndicationMessage)
443 if msg.OperState == UP {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700444 o.InternalState.Event("enable")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700445 o.OperState.Event("enable")
446 } else if msg.OperState == DOWN {
447 o.InternalState.Event("disable")
448 o.OperState.Event("disable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700449 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700450 o.sendOltIndication(msg, stream)
451 case NniIndication:
452 msg, _ := message.Data.(NniIndicationMessage)
453 o.sendNniIndication(msg, stream)
454 case PonIndication:
455 msg, _ := message.Data.(PonIndicationMessage)
456 o.sendPonIndication(msg, stream)
457 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700458 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700459 }
460
461 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100462 wg.Done()
463 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700464}
465
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100466// processNniPacketIns handles messages received over the NNI interface
467func (o *OltDevice) processNniPacketIns(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700468 oltLogger.WithFields(log.Fields{
469 "nniChannel": o.nniPktInChannel,
470 }).Debug("Started NNI Channel")
471 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
472 for message := range o.nniPktInChannel {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700473 oltLogger.Tracef("Received packets on NNI Channel")
474
475 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
476
477 if err != nil {
478 log.WithFields(log.Fields{
479 "IntfType": "nni",
480 "IntfId": nniId,
481 "Pkt": message.Pkt.Data(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700482 }).Error("Can't find Dst MacAddress in packet")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700483 return
484 }
485
486 onu, err := o.FindOnuByMacAddress(onuMac)
487 if err != nil {
488 log.WithFields(log.Fields{
489 "IntfType": "nni",
490 "IntfId": nniId,
491 "Pkt": message.Pkt.Data(),
492 "MacAddress": onuMac.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700493 }).Error("Can't find ONU with MacAddress")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700494 return
495 }
496
497 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
498 if err != nil {
499 log.Error("Fail to add double tag to packet")
500 }
501
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700502 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
503 IntfType: "nni",
504 IntfId: nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700505 Pkt: doubleTaggedPkt.Data()}}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700506 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
507 oltLogger.WithFields(log.Fields{
508 "IntfType": data.PktInd.IntfType,
509 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700510 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700511 }).Errorf("Fail to send PktInd indication: %v", err)
512 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700513 oltLogger.WithFields(log.Fields{
514 "IntfType": data.PktInd.IntfType,
515 "IntfId": nniId,
516 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700517 "OnuSn": onu.Sn(),
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700518 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700519 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100520 wg.Done()
521 oltLogger.WithFields(log.Fields{
522 "nniChannel": o.nniPktInChannel,
523 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700524}
525
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700526// returns an ONU with a given Serial Number
527func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200528 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700529 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700530 for _, pon := range o.Pons {
531 for _, onu := range pon.Onus {
532 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700533 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700534 }
535 }
536 }
537
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700538 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
539}
540
William Kurkian9dadc5b2019-10-22 13:51:57 -0400541// returns an ONU with a given interface/Onu Id
542func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200543 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400544 // memoizing it will remove the bottleneck
545 for _, pon := range o.Pons {
546 if pon.ID == intfId {
547 for _, onu := range pon.Onus {
548 if onu.ID == onuId {
549 return onu, nil
550 }
551 }
552 }
553 }
554 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
555}
556
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700557// returns an ONU with a given Mac Address
558func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200559 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700560 // memoizing it will remove the bottleneck
561 for _, pon := range o.Pons {
562 for _, onu := range pon.Onus {
563 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700564 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700565 }
566 }
567 }
568
569 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700570}
571
Matteo Scandolo4747d292019-08-05 11:50:18 -0700572// GRPC Endpoints
573
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700574func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700575 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700576 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700577 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700578
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700579 pon, _ := o.GetPonById(onu.IntfId)
580 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500581 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700582
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700583 if err := _onu.OperState.Event("enable"); err != nil {
584 oltLogger.WithFields(log.Fields{
585 "IntfId": _onu.PonPortID,
586 "OnuSn": _onu.Sn(),
587 "OnuId": _onu.ID,
588 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700589 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700590 if err := _onu.InternalState.Event("enable"); err != nil {
591 oltLogger.WithFields(log.Fields{
592 "IntfId": _onu.PonPortID,
593 "OnuSn": _onu.Sn(),
594 "OnuId": _onu.ID,
595 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
596 }
597
598 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
599
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700600 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601}
602
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700603func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700604 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700605 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700606}
607
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700608func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700609 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700610 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700611}
612
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700613func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700614 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800615 oltLogger.WithFields(log.Fields{
616 "oltId": o.ID,
617 }).Info("Disabling OLT")
618
619 for i, pon := range o.Pons {
620 // disable all onus
621 for _, onu := range o.Pons[i].Onus {
622 // NOTE order of these is important.
623 if err := onu.OperState.Event("disable"); err != nil {
624 log.Errorf("Error disabling ONU oper state: %v", err)
625 }
626 if err := onu.InternalState.Event("disable"); err != nil {
627 log.Errorf("Error disabling ONU: %v", err)
628 }
629 }
630
631 // disable PONs
632 msg := Message{
633 Type: PonIndication,
634 Data: PonIndicationMessage{
635 OperState: DOWN,
636 PonPortID: pon.ID,
637 },
638 }
639
640 o.channel <- msg
641 }
642
643 // disable NNI
644 for _, nni := range o.Nnis {
645 msg := Message{
646 Type: NniIndication,
647 Data: NniIndicationMessage{
648 OperState: DOWN,
649 NniPortID: nni.ID,
650 },
651 }
652 o.channel <- msg
653 }
654
655 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100656 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700657 Type: OltIndication,
658 Data: OltIndicationMessage{
659 OperState: DOWN,
660 },
661 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100662 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700663 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700664}
665
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700666func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700667 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700668 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700669}
670
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100671func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700672 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700673 o.Enable(stream)
674 return nil
675}
676
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700677func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700678 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700679 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700680}
681
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700682func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700683 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700684 "IntfId": flow.AccessIntfId,
685 "OnuId": flow.OnuId,
686 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700687 "InnerVlan": flow.Classifier.IVid,
688 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700689 "FlowType": flow.FlowType,
690 "FlowId": flow.FlowId,
691 "UniID": flow.UniId,
692 "PortNo": flow.PortNo,
693 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700694 // TODO optionally store flows somewhere
695
696 if flow.AccessIntfId == -1 {
697 oltLogger.WithFields(log.Fields{
698 "FlowId": flow.FlowId,
699 }).Debugf("This is an OLT flow")
700 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700701 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700702 if err != nil {
703 oltLogger.WithFields(log.Fields{
704 "OnuId": flow.OnuId,
705 "IntfId": flow.AccessIntfId,
706 "err": err,
707 }).Error("Can't find PonPort")
708 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700709 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700710 if err != nil {
711 oltLogger.WithFields(log.Fields{
712 "OnuId": flow.OnuId,
713 "IntfId": flow.AccessIntfId,
714 "err": err,
715 }).Error("Can't find Onu")
716 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700717
718 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700719 Type: FlowUpdate,
720 Data: OnuFlowUpdateMessage{
721 PonPortID: pon.ID,
722 OnuID: onu.ID,
723 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700724 },
725 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700726 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700727 }
728
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700729 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700730}
731
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700732func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
733 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700734 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700735 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700736}
737
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700738func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700739 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700740 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700741}
742
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700743func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700744
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700745 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700746 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700747 "PonPorts": o.NumPon,
748 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700749 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100750 devinfo.Vendor = common.Options.Olt.Vendor
751 devinfo.Model = common.Options.Olt.Model
752 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
753 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
754 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700755 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700756 devinfo.OnuIdStart = 1
757 devinfo.OnuIdEnd = 255
758 devinfo.AllocIdStart = 1024
759 devinfo.AllocIdEnd = 16383
760 devinfo.GemportIdStart = 1024
761 devinfo.GemportIdEnd = 65535
762 devinfo.FlowIdStart = 1
763 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700764 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100765 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -0700766
767 return devinfo, nil
768}
769
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700770func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700771 pon, _ := o.GetPonById(omci_msg.IntfId)
772 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700773 oltLogger.WithFields(log.Fields{
774 "IntfId": onu.PonPortID,
775 "OnuId": onu.ID,
776 "OnuSn": onu.Sn(),
777 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700778 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700779 Type: OMCI,
780 Data: OmciMessage{
781 OnuSN: onu.SerialNumber,
782 OnuID: onu.ID,
783 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700784 },
785 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700786 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700787 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700788}
789
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700790func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700791 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700792 if err != nil {
793 oltLogger.WithFields(log.Fields{
794 "OnuId": onuPkt.OnuId,
795 "IntfId": onuPkt.IntfId,
796 "err": err,
797 }).Error("Can't find PonPort")
798 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700799 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700800 if err != nil {
801 oltLogger.WithFields(log.Fields{
802 "OnuId": onuPkt.OnuId,
803 "IntfId": onuPkt.IntfId,
804 "err": err,
805 }).Error("Can't find Onu")
806 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700807
Matteo Scandolo075b1892019-10-07 12:11:07 -0700808 oltLogger.WithFields(log.Fields{
809 "IntfId": onu.PonPortID,
810 "OnuId": onu.ID,
811 "OnuSn": onu.Sn(),
812 }).Tracef("Received OnuPacketOut")
813
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700814 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700815 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700816
Matteo Scandolo075b1892019-10-07 12:11:07 -0700817 msg := Message{
818 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700819 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -0700820 IntfId: onuPkt.IntfId,
821 OnuId: onuPkt.OnuId,
822 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700823 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700824 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700825 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700826 onu.Channel <- msg
827
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700828 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700829}
830
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700831func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800832 oltLogger.WithFields(log.Fields{
833 "oltId": o.ID,
834 }).Info("Shutting down")
835 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700836 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700837}
838
839func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700840 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700841 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700842}
843
844func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700845 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
846
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100847 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700848 // NOTE should we return an error if sendNniPakcet fails?
849 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700850}
851
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700852func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700853 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700854 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700855}
856
Matteo Scandolo4747d292019-08-05 11:50:18 -0700857func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700858 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700859 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700860}
861
862func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700863 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700864 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700865}
866
867func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700868 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700869 return new(openolt.Empty), nil
870}
871
872func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700873 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700874 return new(openolt.Empty), nil
875}
876
877func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700878 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700879 return new(openolt.Empty), nil
880}
881
882func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700883 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700884 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700885}