blob: 22257a4c31e79d38e5068bae20b6859c5e8dba99 [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 Scandolo401503a2019-12-11 14:48:14 -080023 "github.com/google/gopacket/pcap"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020024 "net"
25 "sync"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010026 "time"
Zdravko Bozakov2da76342019-10-21 09:47:35 +020027
Matteo Scandolo47e69bb2019-08-28 15:41:12 -070028 "github.com/google/gopacket"
29 "github.com/google/gopacket/layers"
Matteo Scandolo4747d292019-08-05 11:50:18 -070030 "github.com/looplab/fsm"
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -070031 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070032 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +010033 "github.com/opencord/bbsim/internal/common"
William Kurkian9dadc5b2019-10-22 13:51:57 -040034 omcisim "github.com/opencord/omci-sim"
Matteo Scandolo3de9de02019-11-14 13:40:03 -080035 "github.com/opencord/voltha-protos/v2/go/openolt"
36 "github.com/opencord/voltha-protos/v2/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070037 log "github.com/sirupsen/logrus"
38 "google.golang.org/grpc"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010039 "google.golang.org/grpc/reflection"
Matteo Scandolo4747d292019-08-05 11:50:18 -070040)
41
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070042var oltLogger = log.WithFields(log.Fields{
Matteo Scandolo84f7d482019-08-08 19:00:47 -070043 "module": "OLT",
44})
45
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070046type OltDevice struct {
47 // BBSIM Internals
48 ID int
49 SerialNumber string
50 NumNni int
51 NumPon int
52 NumOnuPerPon int
53 InternalState *fsm.FSM
54 channel chan Message
Zdravko Bozakov681364d2019-11-10 14:28:46 +010055 nniPktInChannel chan *bbsim.PacketMsg // packets coming in from the NNI and going to VOLTHA
Matteo Scandolo401503a2019-12-11 14:48:14 -080056 nniHandle *pcap.Handle // handle on the NNI interface, close it when shutting down the NNI channel
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070057
Matteo Scandoloe33447a2019-10-31 12:38:23 -070058 Delay int
59
Matteo Scandolo27428702019-10-11 16:21:16 -070060 Pons []*PonPort
61 Nnis []*NniPort
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070062
63 // OLT Attributes
64 OperState *fsm.FSM
Matteo Scandolo4747d292019-08-05 11:50:18 -070065}
66
Matteo Scandolo27428702019-10-11 16:21:16 -070067var olt OltDevice
Zdravko Bozakov681364d2019-11-10 14:28:46 +010068var oltServer *grpc.Server
Matteo Scandolo84f7d482019-08-08 19:00:47 -070069
Matteo Scandolo27428702019-10-11 16:21:16 -070070func GetOLT() *OltDevice {
71 return &olt
Matteo Scandolo84f7d482019-08-08 19:00:47 -070072}
73
Zdravko Bozakov681364d2019-11-10 14:28:46 +010074func 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 -070075 oltLogger.WithFields(log.Fields{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070076 "ID": oltId,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -070077 "NumNni": nni,
78 "NumPon": pon,
79 "NumOnuPerPon": onuPerPon,
Matteo Scandolo4747d292019-08-05 11:50:18 -070080 }).Debug("CreateOLT")
81
Matteo Scandolo84f7d482019-08-08 19:00:47 -070082 olt = OltDevice{
Matteo Scandolo40e067f2019-10-16 16:59:41 -070083 ID: oltId,
84 SerialNumber: fmt.Sprintf("BBSIM_OLT_%d", oltId),
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070085 OperState: getOperStateFSM(func(e *fsm.Event) {
86 oltLogger.Debugf("Changing OLT OperState from %s to %s", e.Src, e.Dst)
87 }),
Zdravko Bozakov681364d2019-11-10 14:28:46 +010088 NumNni: nni,
89 NumPon: pon,
90 NumOnuPerPon: onuPerPon,
91 Pons: []*PonPort{},
92 Nnis: []*NniPort{},
93 Delay: delay,
Matteo Scandolo4747d292019-08-05 11:50:18 -070094 }
95
96 // OLT State machine
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070097 // NOTE do we need 2 state machines for the OLT? (InternalState and OperState)
Matteo Scandolo4747d292019-08-05 11:50:18 -070098 olt.InternalState = fsm.NewFSM(
99 "created",
100 fsm.Events{
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800101 {Name: "initialize", Src: []string{"created", "deleted"}, Dst: "initialized"},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100102 {Name: "enable", Src: []string{"initialized", "disabled"}, Dst: "enabled"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700103 {Name: "disable", Src: []string{"enabled"}, Dst: "disabled"},
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800104 {Name: "delete", Src: []string{"disabled"}, Dst: "deleted"},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700105 },
106 fsm.Callbacks{
107 "enter_state": func(e *fsm.Event) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700108 oltLogger.Debugf("Changing OLT InternalState from %s to %s", e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700109 },
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100110 "enter_initialized": func(e *fsm.Event) { olt.InitOlt() },
Matteo Scandolo4747d292019-08-05 11:50:18 -0700111 },
112 )
113
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700114 if isMock != true {
115 // create NNI Port
116 nniPort, err := CreateNNI(&olt)
117 if err != nil {
118 oltLogger.Fatalf("Couldn't create NNI Port: %v", err)
119 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700120
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700121 olt.Nnis = append(olt.Nnis, &nniPort)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700122 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700123
Matteo Scandolo4747d292019-08-05 11:50:18 -0700124 // create PON ports
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700125 availableCTag := cTagInit
Matteo Scandolo4747d292019-08-05 11:50:18 -0700126 for i := 0; i < pon; i++ {
127 p := PonPort{
128 NumOnu: olt.NumOnuPerPon,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700129 ID: uint32(i),
130 Type: "pon",
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700131 Olt: olt,
Matteo Scandolo27428702019-10-11 16:21:16 -0700132 Onus: []*Onu{},
Matteo Scandolo4747d292019-08-05 11:50:18 -0700133 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700134 p.OperState = getOperStateFSM(func(e *fsm.Event) {
135 oltLogger.WithFields(log.Fields{
136 "ID": p.ID,
137 }).Debugf("Changing PON Port OperState from %s to %s", e.Src, e.Dst)
138 })
Matteo Scandolo4747d292019-08-05 11:50:18 -0700139
140 // create ONU devices
141 for j := 0; j < onuPerPon; j++ {
Matteo Scandoloc1147092019-10-29 09:38:33 -0700142 o := CreateONU(olt, p, uint32(j+1), sTag, availableCTag, auth, dhcp)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700143 p.Onus = append(p.Onus, o)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700144 availableCTag = availableCTag + 1
Matteo Scandolo4747d292019-08-05 11:50:18 -0700145 }
146
Matteo Scandolo27428702019-10-11 16:21:16 -0700147 olt.Pons = append(olt.Pons, &p)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700148 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100149
Matteo Scandolod32c3822019-11-26 15:57:46 -0700150 if isMock != true {
151 if err := olt.InternalState.Event("initialize"); err != nil {
152 log.Errorf("Error initializing OLT: %v", err)
153 return nil
154 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100155 }
156
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700157 return &olt
158}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700159
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100160func (o *OltDevice) InitOlt() error {
161
162 if oltServer == nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800163 oltServer, _ = o.newOltServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100164 } else {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800165 // FIXME there should never be a server running if we are initializing the OLT
166 oltLogger.Fatal("OLT server already running.")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100167 }
168
169 // create new channel for processOltMessages Go routine
170 o.channel = make(chan Message)
171
172 o.nniPktInChannel = make(chan *bbsim.PacketMsg, 1024)
173 // FIXME we are assuming we have only one NNI
174 if o.Nnis[0] != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800175 // NOTE we want to make sure the state is down when we initialize the OLT,
176 // the NNI may be in a bad state after a disable/reboot as we are not disabling it for
177 // in-band management
178 o.Nnis[0].OperState.SetState("down")
179 ch, handle, err := o.Nnis[0].NewVethChan()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100180 if err == nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800181 oltLogger.WithFields(log.Fields{
182 "Type": o.Nnis[0].Type,
183 "IntfId": o.Nnis[0].ID,
184 "OperState": o.Nnis[0].OperState.Current(),
185 }).Info("NNI Channel created")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100186 o.nniPktInChannel = ch
Matteo Scandolo401503a2019-12-11 14:48:14 -0800187 o.nniHandle = handle
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100188 } else {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800189 oltLogger.Errorf("Error getting NNI channel: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100190 }
191 }
192
193 for i := range olt.Pons {
194 for _, onu := range olt.Pons[i].Onus {
195 if err := onu.InternalState.Event("initialize"); err != nil {
Matteo Scandolo401503a2019-12-11 14:48:14 -0800196 oltLogger.Errorf("Error initializing ONU: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100197 return err
198 }
199 }
200 }
201
202 return nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700203}
204
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800205func (o *OltDevice) RestartOLT() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100206
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800207 rebootDelay := common.Options.Olt.OltRebootDelay
208
209 oltLogger.WithFields(log.Fields{
210 "oltId": o.ID,
211 }).Infof("Simulating OLT restart... (%ds)", rebootDelay)
212
213 // transition internal state to deleted
214 if err := o.InternalState.Event("delete"); err != nil {
215 oltLogger.WithFields(log.Fields{
216 "oltId": o.ID,
217 }).Errorf("Error deleting OLT: %v", err)
218 return err
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100219 }
220
221 // TODO handle hard poweroff (i.e. no indications sent to Voltha) vs soft poweroff
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800222 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
223 if err := o.StopOltServer(); err != nil {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100224 return err
225 }
226
227 // terminate the OLT's processOltMessages go routine
228 close(o.channel)
229 // terminate the OLT's processNniPacketIns go routine
Matteo Scandolo401503a2019-12-11 14:48:14 -0800230 o.nniHandle.Close()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100231 close(o.nniPktInChannel)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100232
Matteo Scandolo401503a2019-12-11 14:48:14 -0800233 for i := range olt.Pons {
234 for _, onu := range olt.Pons[i].Onus {
235 // NOTE while the olt is off, restore the ONU to the initial state
236 onu.InternalState.SetState("created")
237 }
238 }
239
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100240 time.Sleep(time.Duration(rebootDelay) * time.Second)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100241
242 if err := o.InternalState.Event("initialize"); err != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800243 oltLogger.WithFields(log.Fields{
244 "oltId": o.ID,
245 }).Errorf("Error initializing OLT: %v", err)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100246 return err
247 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800248 oltLogger.WithFields(log.Fields{
249 "oltId": o.ID,
250 }).Info("OLT restart completed")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100251 return nil
252}
253
254// newOltServer launches a new grpc server for OpenOLT
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800255func (o *OltDevice) newOltServer() (*grpc.Server, error) {
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100256 address := common.Options.BBSim.OpenOltAddress
Matteo Scandolo4747d292019-08-05 11:50:18 -0700257 lis, err := net.Listen("tcp", address)
258 if err != nil {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700259 oltLogger.Fatalf("OLT failed to listen: %v", err)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700260 }
261 grpcServer := grpc.NewServer()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100262
Matteo Scandolo4747d292019-08-05 11:50:18 -0700263 openolt.RegisterOpenoltServer(grpcServer, o)
264
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100265 reflection.Register(grpcServer)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700266
Matteo Scandolo4747d292019-08-05 11:50:18 -0700267 go grpcServer.Serve(lis)
Zdravko Bozakov958d81c2019-12-13 22:09:48 +0100268 oltLogger.Debugf("OLT listening on %v", address)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700269
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100270 return grpcServer, nil
271}
272
273// StopOltServer stops the OpenOLT grpc server
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800274func (o *OltDevice) StopOltServer() error {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100275 // TODO handle poweroff vs graceful shutdown
276 if oltServer != nil {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800277 oltLogger.WithFields(log.Fields{
278 "oltId": o.SerialNumber,
279 }).Warnf("Stopping OLT gRPC server")
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100280 oltServer.Stop()
281 oltServer = nil
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700282 }
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800283
Matteo Scandolo4747d292019-08-05 11:50:18 -0700284 return nil
285}
286
287// Device Methods
288
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289// Enable implements the OpenOLT EnableIndicationServer functionality
290func (o *OltDevice) Enable(stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700291 oltLogger.Debug("Enable OLT called")
Matteo Scandolo84f7d482019-08-08 19:00:47 -0700292
Matteo Scandolo4747d292019-08-05 11:50:18 -0700293 wg := sync.WaitGroup{}
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800294 wg.Add(3)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700295
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100296 // create Go routine to process all OLT events
297 go o.processOltMessages(stream, &wg)
298 go o.processNniPacketIns(stream, &wg)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700299
300 // enable the OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100301 oltMsg := Message{
Matteo Scandolo4747d292019-08-05 11:50:18 -0700302 Type: OltIndication,
303 Data: OltIndicationMessage{
304 OperState: UP,
305 },
306 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100307 o.channel <- oltMsg
Matteo Scandolo4747d292019-08-05 11:50:18 -0700308
309 // send NNI Port Indications
310 for _, nni := range o.Nnis {
311 msg := Message{
312 Type: NniIndication,
313 Data: NniIndicationMessage{
314 OperState: UP,
315 NniPortID: nni.ID,
316 },
317 }
318 o.channel <- msg
319 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100320
William Kurkian9dadc5b2019-10-22 13:51:57 -0400321 go o.processOmciMessages()
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100322
Matteo Scandolo4747d292019-08-05 11:50:18 -0700323 // send PON Port indications
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100324 for i, pon := range o.Pons {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700325 msg := Message{
326 Type: PonIndication,
327 Data: PonIndicationMessage{
328 OperState: UP,
329 PonPortID: pon.ID,
330 },
331 }
332 o.channel <- msg
333
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100334 for _, onu := range o.Pons[i].Onus {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700335 go onu.ProcessOnuMessages(stream, nil)
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100336 if err := onu.InternalState.Event("discover"); err != nil {
337 log.Errorf("Error discover ONU: %v", err)
338 return err
Matteo Scandolo4747d292019-08-05 11:50:18 -0700339 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700340 }
341 }
342
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800343 oltLogger.Debug("Enable OLT Done")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700344 wg.Wait()
345 return nil
346}
347
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100348func (o *OltDevice) processOmciMessages() {
William Kurkian9dadc5b2019-10-22 13:51:57 -0400349 ch := omcisim.GetChannel()
350
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100351 oltLogger.Debug("Starting OMCI Indication Channel")
William Kurkian9dadc5b2019-10-22 13:51:57 -0400352
353 for message := range ch {
354 onuId := message.Data.OnuId
355 intfId := message.Data.IntfId
356 onu, err := o.FindOnuById(intfId, onuId)
357 if err != nil {
358 oltLogger.Errorf("Failed to find onu: %v", err)
359 }
360 go onu.processOmciMessage(message)
361 }
362}
363
Matteo Scandolo4747d292019-08-05 11:50:18 -0700364// Helpers method
365
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700366func (o OltDevice) GetPonById(id uint32) (*PonPort, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700367 for _, pon := range o.Pons {
368 if pon.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700369 return pon, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700370 }
371 }
372 return nil, errors.New(fmt.Sprintf("Cannot find PonPort with id %d in OLT %d", id, o.ID))
373}
374
375func (o OltDevice) getNniById(id uint32) (*NniPort, error) {
376 for _, nni := range o.Nnis {
377 if nni.ID == id {
Matteo Scandolo27428702019-10-11 16:21:16 -0700378 return nni, nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700379 }
380 }
381 return nil, errors.New(fmt.Sprintf("Cannot find NniPort with id %d in OLT %d", id, o.ID))
382}
383
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100384func (o *OltDevice) sendOltIndication(msg OltIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700385 data := &openolt.Indication_OltInd{OltInd: &openolt.OltIndication{OperState: msg.OperState.String()}}
386 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700387 oltLogger.Errorf("Failed to send Indication_OltInd: %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 Scandolo4747d292019-08-05 11:50:18 -0700392 "OperState": msg.OperState,
393 }).Debug("Sent Indication_OltInd")
394}
395
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100396func (o *OltDevice) sendNniIndication(msg NniIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700397 nni, _ := o.getNniById(msg.NniPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800398 if msg.OperState == UP {
399 if err := nni.OperState.Event("enable"); err != nil {
400 log.WithFields(log.Fields{
401 "Type": nni.Type,
402 "IntfId": nni.ID,
403 "OperState": nni.OperState.Current(),
404 }).Errorf("Can't move NNI Port to enabled state: %v", err)
405 }
406 } else if msg.OperState == DOWN {
407 if err := nni.OperState.Event("disable"); err != nil {
408 log.WithFields(log.Fields{
409 "Type": nni.Type,
410 "IntfId": nni.ID,
411 "OperState": nni.OperState.Current(),
412 }).Errorf("Can't move NNI Port to disable state: %v", err)
413 }
414 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700415 // NOTE Operstate may need to be an integer
Matteo Scandolo4747d292019-08-05 11:50:18 -0700416 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700417 Type: nni.Type,
418 IntfId: nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700419 OperState: nni.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 NNI: %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": nni.Type,
429 "IntfId": nni.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700430 "OperState": nni.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700431 }).Debug("Sent Indication_IntfOperInd for NNI")
432}
433
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100434func (o *OltDevice) sendPonIndication(msg PonIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700435 pon, _ := o.GetPonById(msg.PonPortID)
Matteo Scandolo401503a2019-12-11 14:48:14 -0800436 if msg.OperState == UP {
437 if err := pon.OperState.Event("enable"); err != nil {
438 log.WithFields(log.Fields{
439 "Type": pon.Type,
440 "IntfId": pon.ID,
441 "OperState": pon.OperState.Current(),
442 }).Errorf("Can't move PON Port to enable state: %v", err)
443 }
444 } else if msg.OperState == DOWN {
445 if err := pon.OperState.Event("disable"); err != nil {
446 log.WithFields(log.Fields{
447 "Type": pon.Type,
448 "IntfId": pon.ID,
449 "OperState": pon.OperState.Current(),
450 }).Errorf("Can't move PON Port to disable state: %v", err)
451 }
452 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700453 discoverData := &openolt.Indication_IntfInd{IntfInd: &openolt.IntfIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700454 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700455 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700456 }}
457
458 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700459 oltLogger.Errorf("Failed to send Indication_IntfInd: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800460 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700461 }
462
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700463 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700464 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700465 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700466 }).Debug("Sent Indication_IntfInd")
467
468 operData := &openolt.Indication_IntfOperInd{IntfOperInd: &openolt.IntfOperIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700469 Type: pon.Type,
470 IntfId: pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700471 OperState: pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700472 }}
473
474 if err := stream.Send(&openolt.Indication{Data: operData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700475 oltLogger.Errorf("Failed to send Indication_IntfOperInd for PON: %v", err)
Matteo Scandolo08badf42019-12-12 11:21:50 -0800476 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700477 }
478
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700479 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700480 "Type": pon.Type,
481 "IntfId": pon.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700482 "OperState": pon.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700483 }).Debug("Sent Indication_IntfOperInd for PON")
484}
485
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100486// processOltMessages handles messages received over the OpenOLT interface
487func (o *OltDevice) processOltMessages(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
488 oltLogger.Debug("Starting OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700489 for message := range o.channel {
490
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700491 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700492 "oltId": o.ID,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700493 "messageType": message.Type,
494 }).Trace("Received message")
495
496 switch message.Type {
497 case OltIndication:
498 msg, _ := message.Data.(OltIndicationMessage)
499 if msg.OperState == UP {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700500 o.InternalState.Event("enable")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700501 o.OperState.Event("enable")
502 } else if msg.OperState == DOWN {
503 o.InternalState.Event("disable")
504 o.OperState.Event("disable")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700505 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700506 o.sendOltIndication(msg, stream)
507 case NniIndication:
508 msg, _ := message.Data.(NniIndicationMessage)
509 o.sendNniIndication(msg, stream)
510 case PonIndication:
511 msg, _ := message.Data.(PonIndicationMessage)
512 o.sendPonIndication(msg, stream)
513 default:
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700514 oltLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700515 }
516
517 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100518 wg.Done()
519 oltLogger.Warn("Stopped handling OLT Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700520}
521
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100522// processNniPacketIns handles messages received over the NNI interface
523func (o *OltDevice) processNniPacketIns(stream openolt.Openolt_EnableIndicationServer, wg *sync.WaitGroup) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700524 oltLogger.WithFields(log.Fields{
525 "nniChannel": o.nniPktInChannel,
Matteo Scandolo401503a2019-12-11 14:48:14 -0800526 }).Debug("Started Processing Packets arriving from the NNI")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700527 nniId := o.Nnis[0].ID // FIXME we are assuming we have only one NNI
528 for message := range o.nniPktInChannel {
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700529 oltLogger.Tracef("Received packets on NNI Channel")
530
531 onuMac, err := packetHandlers.GetDstMacAddressFromPacket(message.Pkt)
532
533 if err != nil {
534 log.WithFields(log.Fields{
535 "IntfType": "nni",
536 "IntfId": nniId,
537 "Pkt": message.Pkt.Data(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700538 }).Error("Can't find Dst MacAddress in packet")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700539 return
540 }
541
542 onu, err := o.FindOnuByMacAddress(onuMac)
543 if err != nil {
544 log.WithFields(log.Fields{
545 "IntfType": "nni",
546 "IntfId": nniId,
547 "Pkt": message.Pkt.Data(),
548 "MacAddress": onuMac.String(),
Matteo Scandolo27428702019-10-11 16:21:16 -0700549 }).Error("Can't find ONU with MacAddress")
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700550 return
551 }
552
553 doubleTaggedPkt, err := packetHandlers.PushDoubleTag(onu.STag, onu.CTag, message.Pkt)
554 if err != nil {
555 log.Error("Fail to add double tag to packet")
556 }
557
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700558 data := &openolt.Indication_PktInd{PktInd: &openolt.PacketIndication{
559 IntfType: "nni",
560 IntfId: nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700561 Pkt: doubleTaggedPkt.Data()}}
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700562 if err := stream.Send(&openolt.Indication{Data: data}); err != nil {
563 oltLogger.WithFields(log.Fields{
564 "IntfType": data.PktInd.IntfType,
565 "IntfId": nniId,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700566 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700567 }).Errorf("Fail to send PktInd indication: %v", err)
568 }
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700569 oltLogger.WithFields(log.Fields{
570 "IntfType": data.PktInd.IntfType,
571 "IntfId": nniId,
572 "Pkt": doubleTaggedPkt.Data(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700573 "OnuSn": onu.Sn(),
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700574 }).Tracef("Sent PktInd indication")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700575 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100576 wg.Done()
577 oltLogger.WithFields(log.Fields{
578 "nniChannel": o.nniPktInChannel,
579 }).Warn("Stopped handling NNI Channel")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700580}
581
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700582// returns an ONU with a given Serial Number
583func (o OltDevice) FindOnuBySn(serialNumber string) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200584 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700585 // memoizing it will remove the bottleneck
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700586 for _, pon := range o.Pons {
587 for _, onu := range pon.Onus {
588 if onu.Sn() == serialNumber {
Matteo Scandolo27428702019-10-11 16:21:16 -0700589 return onu, nil
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700590 }
591 }
592 }
593
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700594 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-serial-number-%s", serialNumber))
595}
596
William Kurkian9dadc5b2019-10-22 13:51:57 -0400597// returns an ONU with a given interface/Onu Id
598func (o OltDevice) FindOnuById(intfId uint32, onuId uint32) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200599 // TODO this function can be a performance bottleneck when we have many ONUs,
William Kurkian9dadc5b2019-10-22 13:51:57 -0400600 // memoizing it will remove the bottleneck
601 for _, pon := range o.Pons {
602 if pon.ID == intfId {
603 for _, onu := range pon.Onus {
604 if onu.ID == onuId {
605 return onu, nil
606 }
607 }
608 }
609 }
610 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-id-%v-%v", intfId, onuId))
611}
612
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700613// returns an ONU with a given Mac Address
614func (o OltDevice) FindOnuByMacAddress(mac net.HardwareAddr) (*Onu, error) {
Zdravko Bozakov2da76342019-10-21 09:47:35 +0200615 // TODO this function can be a performance bottleneck when we have many ONUs,
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700616 // memoizing it will remove the bottleneck
617 for _, pon := range o.Pons {
618 for _, onu := range pon.Onus {
619 if onu.HwAddress.String() == mac.String() {
Matteo Scandolo27428702019-10-11 16:21:16 -0700620 return onu, nil
Matteo Scandolof6f3a7f2019-10-11 11:19:29 -0700621 }
622 }
623 }
624
625 return &Onu{}, errors.New(fmt.Sprintf("cannot-find-onu-by-mac-address-%s", mac))
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700626}
627
Matteo Scandolo4747d292019-08-05 11:50:18 -0700628// GRPC Endpoints
629
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700630func (o OltDevice) ActivateOnu(context context.Context, onu *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700631 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700632 "OnuSn": onuSnToString(onu.SerialNumber),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700633 }).Info("Received ActivateOnu call from VOLTHA")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700634
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700635 pon, _ := o.GetPonById(onu.IntfId)
636 _onu, _ := pon.GetOnuBySn(onu.SerialNumber)
William Kurkian0418bc82019-11-06 12:16:24 -0500637 _onu.SetID(onu.OnuId)
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700638
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700639 if err := _onu.OperState.Event("enable"); err != nil {
640 oltLogger.WithFields(log.Fields{
641 "IntfId": _onu.PonPortID,
642 "OnuSn": _onu.Sn(),
643 "OnuId": _onu.ID,
644 }).Infof("Failed to transition ONU.OperState to enabled state: %s", err.Error())
Matteo Scandolo4747d292019-08-05 11:50:18 -0700645 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700646 if err := _onu.InternalState.Event("enable"); err != nil {
647 oltLogger.WithFields(log.Fields{
648 "IntfId": _onu.PonPortID,
649 "OnuSn": _onu.Sn(),
650 "OnuId": _onu.ID,
651 }).Infof("Failed to transition ONU to enabled state: %s", err.Error())
652 }
653
654 // NOTE we need to immediately activate the ONU or the OMCI state machine won't start
655
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700656 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700657}
658
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700659func (o OltDevice) DeactivateOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700660 oltLogger.Error("DeactivateOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700661 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700662}
663
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700664func (o OltDevice) DeleteOnu(context.Context, *openolt.Onu) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700665 oltLogger.Error("DeleteOnu not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700666 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700667}
668
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700669func (o OltDevice) DisableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700670 // NOTE when we disable the OLT should we disable NNI, PONs and ONUs altogether?
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800671 oltLogger.WithFields(log.Fields{
672 "oltId": o.ID,
673 }).Info("Disabling OLT")
674
Matteo Scandolo401503a2019-12-11 14:48:14 -0800675 for _, pon := range o.Pons {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800676 // disable PONs
677 msg := Message{
678 Type: PonIndication,
679 Data: PonIndicationMessage{
680 OperState: DOWN,
681 PonPortID: pon.ID,
682 },
683 }
684
685 o.channel <- msg
686 }
687
Matteo Scandolo401503a2019-12-11 14:48:14 -0800688 // Note that we are not disabling the NNI as the real OLT does not.
689 // The reason for that is in-band management
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800690
691 // disable OLT
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100692 oltMsg := Message{
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700693 Type: OltIndication,
694 Data: OltIndicationMessage{
695 OperState: DOWN,
696 },
697 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100698 o.channel <- oltMsg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700699 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700700}
701
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700702func (o OltDevice) DisablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700703 oltLogger.Error("DisablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700704 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700705}
706
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100707func (o *OltDevice) EnableIndication(_ *openolt.Empty, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700708 oltLogger.WithField("oltId", o.ID).Info("OLT receives EnableIndication call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700709 o.Enable(stream)
710 return nil
711}
712
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700713func (o OltDevice) EnablePonIf(context.Context, *openolt.Interface) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700714 oltLogger.Error("EnablePonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700715 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700716}
717
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700718func (o OltDevice) FlowAdd(ctx context.Context, flow *openolt.Flow) (*openolt.Empty, error) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700719 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700720 "IntfId": flow.AccessIntfId,
721 "OnuId": flow.OnuId,
722 "EthType": fmt.Sprintf("%x", flow.Classifier.EthType),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700723 "InnerVlan": flow.Classifier.IVid,
724 "OuterVlan": flow.Classifier.OVid,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700725 "FlowType": flow.FlowType,
726 "FlowId": flow.FlowId,
727 "UniID": flow.UniId,
728 "PortNo": flow.PortNo,
729 }).Tracef("OLT receives Flow")
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700730 // TODO optionally store flows somewhere
731
732 if flow.AccessIntfId == -1 {
733 oltLogger.WithFields(log.Fields{
734 "FlowId": flow.FlowId,
735 }).Debugf("This is an OLT flow")
736 } else {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700737 pon, err := o.GetPonById(uint32(flow.AccessIntfId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700738 if err != nil {
739 oltLogger.WithFields(log.Fields{
740 "OnuId": flow.OnuId,
741 "IntfId": flow.AccessIntfId,
742 "err": err,
743 }).Error("Can't find PonPort")
744 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700745 onu, err := pon.GetOnuById(uint32(flow.OnuId))
Matteo Scandolo27428702019-10-11 16:21:16 -0700746 if err != nil {
747 oltLogger.WithFields(log.Fields{
748 "OnuId": flow.OnuId,
749 "IntfId": flow.AccessIntfId,
750 "err": err,
751 }).Error("Can't find Onu")
752 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700753
754 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700755 Type: FlowUpdate,
756 Data: OnuFlowUpdateMessage{
757 PonPortID: pon.ID,
758 OnuID: onu.ID,
759 Flow: flow,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700760 },
761 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700762 onu.Channel <- msg
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700763 }
764
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700765 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700766}
767
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700768func (o OltDevice) FlowRemove(context.Context, *openolt.Flow) (*openolt.Empty, error) {
769 oltLogger.Tracef("received FlowRemove")
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700770 // TODO store flows somewhere
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700771 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700772}
773
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700774func (o OltDevice) HeartbeatCheck(context.Context, *openolt.Empty) (*openolt.Heartbeat, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700775 oltLogger.Error("HeartbeatCheck not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700776 return new(openolt.Heartbeat), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700777}
778
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700779func (o OltDevice) GetDeviceInfo(context.Context, *openolt.Empty) (*openolt.DeviceInfo, error) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700780
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700781 oltLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700782 "oltId": o.ID,
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700783 "PonPorts": o.NumPon,
784 }).Info("OLT receives GetDeviceInfo call from VOLTHA")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700785 devinfo := new(openolt.DeviceInfo)
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100786 devinfo.Vendor = common.Options.Olt.Vendor
787 devinfo.Model = common.Options.Olt.Model
788 devinfo.HardwareVersion = common.Options.Olt.HardwareVersion
789 devinfo.FirmwareVersion = common.Options.Olt.FirmwareVersion
790 devinfo.Technology = common.Options.Olt.Technology
Matteo Scandoloda9cbe22019-08-19 16:05:10 -0700791 devinfo.PonPorts = uint32(o.NumPon)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700792 devinfo.OnuIdStart = 1
793 devinfo.OnuIdEnd = 255
794 devinfo.AllocIdStart = 1024
795 devinfo.AllocIdEnd = 16383
796 devinfo.GemportIdStart = 1024
797 devinfo.GemportIdEnd = 65535
798 devinfo.FlowIdStart = 1
799 devinfo.FlowIdEnd = 16383
Matteo Scandolo8df63df2019-09-12 10:34:32 -0700800 devinfo.DeviceSerialNumber = o.SerialNumber
Zdravko Bozakov3ddb2452019-11-29 14:33:41 +0100801 devinfo.DeviceId = common.Options.Olt.DeviceId
Matteo Scandolo4747d292019-08-05 11:50:18 -0700802
803 return devinfo, nil
804}
805
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700806func (o OltDevice) OmciMsgOut(ctx context.Context, omci_msg *openolt.OmciMsg) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700807 pon, _ := o.GetPonById(omci_msg.IntfId)
808 onu, _ := pon.GetOnuById(omci_msg.OnuId)
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700809 oltLogger.WithFields(log.Fields{
810 "IntfId": onu.PonPortID,
811 "OnuId": onu.ID,
812 "OnuSn": onu.Sn(),
813 }).Tracef("Received OmciMsgOut")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700814 msg := Message{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700815 Type: OMCI,
816 Data: OmciMessage{
817 OnuSN: onu.SerialNumber,
818 OnuID: onu.ID,
819 omciMsg: omci_msg,
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700820 },
821 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700822 onu.Channel <- msg
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700823 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700824}
825
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700826func (o OltDevice) OnuPacketOut(ctx context.Context, onuPkt *openolt.OnuPacket) (*openolt.Empty, error) {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700827 pon, err := o.GetPonById(onuPkt.IntfId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700828 if err != nil {
829 oltLogger.WithFields(log.Fields{
830 "OnuId": onuPkt.OnuId,
831 "IntfId": onuPkt.IntfId,
832 "err": err,
833 }).Error("Can't find PonPort")
834 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700835 onu, err := pon.GetOnuById(onuPkt.OnuId)
Matteo Scandolo27428702019-10-11 16:21:16 -0700836 if err != nil {
837 oltLogger.WithFields(log.Fields{
838 "OnuId": onuPkt.OnuId,
839 "IntfId": onuPkt.IntfId,
840 "err": err,
841 }).Error("Can't find Onu")
842 }
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700843
Matteo Scandolo075b1892019-10-07 12:11:07 -0700844 oltLogger.WithFields(log.Fields{
845 "IntfId": onu.PonPortID,
846 "OnuId": onu.ID,
847 "OnuSn": onu.Sn(),
848 }).Tracef("Received OnuPacketOut")
849
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700850 rawpkt := gopacket.NewPacket(onuPkt.Pkt, layers.LayerTypeEthernet, gopacket.Default)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700851 pktType, err := packetHandlers.IsEapolOrDhcp(rawpkt)
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700852
Matteo Scandolo075b1892019-10-07 12:11:07 -0700853 msg := Message{
854 Type: OnuPacketOut,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700855 Data: OnuPacketMessage{
Matteo Scandolo075b1892019-10-07 12:11:07 -0700856 IntfId: onuPkt.IntfId,
857 OnuId: onuPkt.OnuId,
858 Packet: rawpkt,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700859 Type: pktType,
Matteo Scandolo075b1892019-10-07 12:11:07 -0700860 },
Matteo Scandolo47e69bb2019-08-28 15:41:12 -0700861 }
Matteo Scandolo075b1892019-10-07 12:11:07 -0700862 onu.Channel <- msg
863
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700864 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700865}
866
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700867func (o OltDevice) Reboot(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolod02b79b2019-12-05 16:42:13 -0800868 oltLogger.WithFields(log.Fields{
869 "oltId": o.ID,
870 }).Info("Shutting down")
871 go o.RestartOLT()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700872 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700873}
874
875func (o OltDevice) ReenableOlt(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700876 oltLogger.Error("ReenableOlt not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700877 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700878}
879
880func (o OltDevice) UplinkPacketOut(context context.Context, packet *openolt.UplinkPacket) (*openolt.Empty, error) {
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700881 pkt := gopacket.NewPacket(packet.Pkt, layers.LayerTypeEthernet, gopacket.Default)
882
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100883 o.Nnis[0].sendNniPacket(pkt) // FIXME we are assuming we have only one NNI
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700884 // NOTE should we return an error if sendNniPakcet fails?
885 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700886}
887
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700888func (o OltDevice) CollectStatistics(context.Context, *openolt.Empty) (*openolt.Empty, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700889 oltLogger.Error("CollectStatistics not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700890 return new(openolt.Empty), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700891}
892
Matteo Scandolo4747d292019-08-05 11:50:18 -0700893func (o OltDevice) GetOnuInfo(context context.Context, packet *openolt.Onu) (*openolt.OnuIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700894 oltLogger.Error("GetOnuInfo not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700895 return new(openolt.OnuIndication), nil
Matteo Scandolo4747d292019-08-05 11:50:18 -0700896}
897
898func (o OltDevice) GetPonIf(context context.Context, packet *openolt.Interface) (*openolt.IntfIndication, error) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700899 oltLogger.Error("GetPonIf not implemented")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700900 return new(openolt.IntfIndication), nil
Matteo Scandolod54283a2019-08-13 16:22:31 -0700901}
902
903func (s OltDevice) CreateTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700904 oltLogger.Info("received CreateTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700905 return new(openolt.Empty), nil
906}
907
908func (s OltDevice) RemoveTrafficQueues(context.Context, *tech_profile.TrafficQueues) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700909 oltLogger.Info("received RemoveTrafficQueues")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700910 return new(openolt.Empty), nil
911}
912
913func (s OltDevice) CreateTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700914 oltLogger.Info("received CreateTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700915 return new(openolt.Empty), nil
916}
917
918func (s OltDevice) RemoveTrafficSchedulers(context.Context, *tech_profile.TrafficSchedulers) (*openolt.Empty, error) {
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700919 oltLogger.Info("received RemoveTrafficSchedulers")
Matteo Scandolod54283a2019-08-13 16:22:31 -0700920 return new(openolt.Empty), nil
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700921}