blob: 6a7125ce948afed035faa18fedc1671d670a353f [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 (
Matteo Scandolo40e067f2019-10-16 16:59:41 -070020 "context"
Matteo Scandolo618a6582020-09-09 12:21:29 -070021 "encoding/hex"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070022 "fmt"
Matteo Scandolof9d43412021-01-12 11:11:34 -080023 pb "github.com/opencord/bbsim/api/bbsim"
24 "github.com/opencord/bbsim/internal/bbsim/alarmsim"
Himani Chawla13b1ee02021-03-15 01:43:53 +053025 "sync"
26
Matteo Scandolo4a036262020-08-17 15:56:13 -070027 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
28 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
29 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080030 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
31 me "github.com/opencord/omci-lib-go/generated"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010032 "net"
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080033 "strconv"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010034 "time"
35
Matteo Scandolo3bc73742019-08-20 14:04:04 -070036 "github.com/google/gopacket/layers"
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070037 "github.com/jpillora/backoff"
Matteo Scandolo4747d292019-08-05 11:50:18 -070038 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070039 "github.com/opencord/bbsim/internal/common"
40 omcilib "github.com/opencord/bbsim/internal/common/omci"
Matteo Scandolof9d43412021-01-12 11:11:34 -080041 "github.com/opencord/omci-lib-go"
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070042 "github.com/opencord/voltha-protos/v4/go/openolt"
43 "github.com/opencord/voltha-protos/v4/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070044 log "github.com/sirupsen/logrus"
45)
46
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070047var onuLogger = log.WithFields(log.Fields{
48 "module": "ONU",
49})
50
Matteo Scandolocedde462021-03-09 17:37:16 -080051const (
52 // ONU transitions
53 OnuTxInitialize = "initialize"
54 OnuTxDiscover = "discover"
55 OnuTxEnable = "enable"
56 OnuTxDisable = "disable"
57 OnuTxPonDisable = "pon_disable"
58 OnuTxStartImageDownload = "start_image_download"
59 OnuTxProgressImageDownload = "progress_image_download"
60 OnuTxCompleteImageDownload = "complete_image_download"
61 OnuTxFailImageDownload = "fail_image_download"
62 OnuTxActivateImage = "activate_image"
63 OnuTxCommitImage = "commit_image"
64
65 // ONU States
66 OnuStateCreated = "created"
67 OnuStateInitialized = "initialized"
68 OnuStateDiscovered = "discovered"
69 OnuStateEnabled = "enabled"
70 OnuStateDisabled = "disabled"
71 OnuStatePonDisabled = "pon_disabled"
72 OnuStateImageDownloadStarted = "image_download_started"
73 OnuStateImageDownloadInProgress = "image_download_in_progress"
74 OnuStateImageDownloadComplete = "image_download_completed"
75 OnuStateImageDownloadError = "image_download_error"
76 OnuStateImageActivated = "software_image_activated"
77 OnuStateImageCommitted = "software_image_committed"
78
79 // BBR ONU States and Transitions
80 BbrOnuTxSendEapolFlow = "send_eapol_flow"
81 BbrOnuStateEapolFlowSent = "eapol_flow_sent"
82 BbrOnuTxSendDhcpFlow = "send_dhcp_flow"
83 BbrOnuStateDhcpFlowSent = "dhcp_flow_sent"
84)
85
Pragya Arya8bdb4532020-03-02 17:08:09 +053086type FlowKey struct {
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070087 ID uint64
Pragya Arya8bdb4532020-03-02 17:08:09 +053088 Direction string
89}
90
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070091type Onu struct {
Matteo Scandoloe811ae92019-12-10 17:50:14 -080092 ID uint32
93 PonPortID uint32
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070094 PonPort *PonPort
Matteo Scandoloe811ae92019-12-10 17:50:14 -080095 InternalState *fsm.FSM
Pragya Arya2225f202020-01-29 18:05:01 +053096 DiscoveryRetryDelay time.Duration // this is the time between subsequent Discovery Indication
97 DiscoveryDelay time.Duration // this is the time to send the first Discovery Indication
Matteo Scandolo4a036262020-08-17 15:56:13 -070098
99 Services []ServiceIf
100
101 Backoff *backoff.Backoff
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800102 // ONU State
Matteo Scandolo27428702019-10-11 16:21:16 -0700103 // PortNo comes with flows and it's used when sending packetIndications,
104 // There is one PortNo per UNI Port, for now we're only storing the first one
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700105 // FIXME add support for multiple UNIs (each UNI has a different PortNo)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800106 PortNo uint32
107 Flows []FlowKey
108 FlowIds []uint64 // keep track of the flows we currently have in the ONU
Matteo Scandolo99f18462019-10-28 14:14:28 -0700109
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700110 OperState *fsm.FSM
111 SerialNumber *openolt.SerialNumber
112
Matteo Scandolof9d43412021-01-12 11:11:34 -0800113 Channel chan bbsim.Message // this Channel is to track state changes OMCI messages, EAPOL and DHCP packets
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700114
115 // OMCI params
Matteo Scandolocedde462021-03-09 17:37:16 -0800116 MibDataSync uint8
117 ImageSoftwareExpectedSections int
118 ImageSoftwareReceivedSections int
119 ActiveImageEntityId uint16
120 CommittedImageEntityId uint16
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800121
122 // OMCI params (Used in BBR)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700123 tid uint16
124 hpTid uint16
125 seqNumber uint16
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700126
Anand S Katti09541352020-01-29 15:54:01 +0530127 DoneChannel chan bool // this channel is used to signal once the onu is complete (when the struct is used by BBR)
128 TrafficSchedulers *tech_profile.TrafficSchedulers
Himani Chawla13b1ee02021-03-15 01:43:53 +0530129 onuAlarmsInfoLock sync.RWMutex
130 onuAlarmsInfo map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700131}
132
Matteo Scandolo99f18462019-10-28 14:14:28 -0700133func (o *Onu) Sn() string {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700134 return common.OnuSnToString(o.SerialNumber)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700135}
136
Matteo Scandolo4a036262020-08-17 15:56:13 -0700137func CreateONU(olt *OltDevice, pon *PonPort, id uint32, delay time.Duration, isMock bool) *Onu {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700138
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700139 o := Onu{
Matteo Scandolocedde462021-03-09 17:37:16 -0800140 ID: id,
141 PonPortID: pon.ID,
142 PonPort: pon,
143 PortNo: 0,
144 tid: 0x1,
145 hpTid: 0x8000,
146 seqNumber: 0,
147 DoneChannel: make(chan bool, 1),
148 DiscoveryRetryDelay: 60 * time.Second, // this is used to send OnuDiscoveryIndications until an activate call is received
149 Flows: []FlowKey{},
150 DiscoveryDelay: delay,
151 MibDataSync: 0,
152 ImageSoftwareExpectedSections: 0, // populated during OMCI StartSoftwareDownloadRequest
153 ImageSoftwareReceivedSections: 0,
154 ActiveImageEntityId: 0, // when we start the SoftwareImage with ID 0 is active and committed
155 CommittedImageEntityId: 0,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700156 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800157 o.SerialNumber = NewSN(olt.ID, pon.ID, id)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700158 // NOTE this state machine is used to track the operational
159 // state as requested by VOLTHA
160 o.OperState = getOperStateFSM(func(e *fsm.Event) {
161 onuLogger.WithFields(log.Fields{
162 "ID": o.ID,
163 }).Debugf("Changing ONU OperState from %s to %s", e.Src, e.Dst)
164 })
Himani Chawla13b1ee02021-03-15 01:43:53 +0530165 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700166 // NOTE this state machine is used to activate the OMCI, EAPOL and DHCP clients
167 o.InternalState = fsm.NewFSM(
Matteo Scandolocedde462021-03-09 17:37:16 -0800168 OnuStateCreated,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700169 fsm.Events{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700170 // DEVICE Lifecycle
Matteo Scandolocedde462021-03-09 17:37:16 -0800171 {Name: OnuTxInitialize, Src: []string{OnuStateCreated, OnuStateDisabled, OnuStatePonDisabled}, Dst: OnuStateInitialized},
172 {Name: OnuTxDiscover, Src: []string{OnuStateInitialized}, Dst: OnuStateDiscovered},
173 {Name: OnuTxEnable, Src: []string{OnuStateDiscovered, OnuStatePonDisabled}, Dst: OnuStateEnabled},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100174 // NOTE should disabled state be different for oper_disabled (emulating an error) and admin_disabled (received a disabled call via VOLTHA)?
Matteo Scandolocedde462021-03-09 17:37:16 -0800175 {Name: OnuTxDisable, Src: []string{OnuStateEnabled, OnuStatePonDisabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStateDisabled},
Pragya Arya6a708d62020-01-01 17:17:20 +0530176 // ONU state when PON port is disabled but ONU is power ON(more states should be added in src?)
Matteo Scandolocedde462021-03-09 17:37:16 -0800177 {Name: OnuTxPonDisable, Src: []string{OnuStateEnabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStatePonDisabled},
178 // Software Image Download related states
179 {Name: OnuTxStartImageDownload, Src: []string{OnuStateEnabled, OnuStateImageDownloadComplete, OnuStateImageDownloadError}, Dst: OnuStateImageDownloadStarted},
180 {Name: OnuTxProgressImageDownload, Src: []string{OnuStateImageDownloadStarted}, Dst: OnuStateImageDownloadInProgress},
181 {Name: OnuTxCompleteImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadComplete},
182 {Name: OnuTxFailImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadError},
183 {Name: OnuTxActivateImage, Src: []string{OnuStateImageDownloadComplete}, Dst: OnuStateImageActivated},
184 {Name: OnuTxCommitImage, Src: []string{OnuStateEnabled}, Dst: OnuStateImageCommitted}, // the image is committed after a ONU reboot
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700185 // BBR States
186 // TODO add start OMCI state
Matteo Scandolocedde462021-03-09 17:37:16 -0800187 {Name: BbrOnuTxSendEapolFlow, Src: []string{OnuStateInitialized}, Dst: BbrOnuStateEapolFlowSent},
188 {Name: BbrOnuTxSendDhcpFlow, Src: []string{BbrOnuStateEapolFlowSent}, Dst: BbrOnuStateDhcpFlowSent},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700189 },
190 fsm.Callbacks{
191 "enter_state": func(e *fsm.Event) {
192 o.logStateChange(e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700193 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700194 fmt.Sprintf("enter_%s", OnuStateInitialized): func(e *fsm.Event) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100195 // create new channel for ProcessOnuMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800196 o.Channel = make(chan bbsim.Message, 2048)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800197
Matteo Scandolocedde462021-03-09 17:37:16 -0800198 if err := o.OperState.Event(OnuTxEnable); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800199 onuLogger.WithFields(log.Fields{
200 "OnuId": o.ID,
201 "IntfId": o.PonPortID,
202 "OnuSn": o.Sn(),
203 }).Errorf("Cannot change ONU OperState to up: %s", err.Error())
204 }
205
Pragya Arya1cbefa42020-01-13 12:15:29 +0530206 if !isMock {
207 // start ProcessOnuMessages Go routine
Matteo Scandolo4a036262020-08-17 15:56:13 -0700208 go o.ProcessOnuMessages(olt.enableContext, olt.OpenoltStream, nil)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530209 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100210 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700211 fmt.Sprintf("enter_%s", OnuStateDiscovered): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800212 msg := bbsim.Message{
213 Type: bbsim.OnuDiscIndication,
214 Data: bbsim.OnuDiscIndicationMessage{
215 OperState: bbsim.UP,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100216 },
217 }
218 o.Channel <- msg
219 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700220 fmt.Sprintf("enter_%s", OnuStateEnabled): func(event *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800221
222 if used, sn := o.PonPort.isOnuIdAllocated(o.ID); used {
223 onuLogger.WithFields(log.Fields{
224 "IntfId": o.PonPortID,
225 "OnuId": o.ID,
226 "SerialNumber": o.Sn(),
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700227 }).Errorf("onu-id-duplicated-with-%s", common.OnuSnToString(sn))
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800228 return
229 } else {
230 o.PonPort.storeOnuId(o.ID, o.SerialNumber)
231 }
232
Matteo Scandolof9d43412021-01-12 11:11:34 -0800233 msg := bbsim.Message{
234 Type: bbsim.OnuIndication,
235 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700236 OnuSN: o.SerialNumber,
237 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800238 OperState: bbsim.UP,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700239 },
240 }
241 o.Channel <- msg
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700242
243 // Once the ONU is enabled start listening for packets
244 for _, s := range o.Services {
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700245 s.Initialize(o.PonPort.Olt.OpenoltStream)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700246 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700247 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700248 fmt.Sprintf("enter_%s", OnuStateDisabled): func(event *fsm.Event) {
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700249
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700250 o.cleanupOnuState()
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700251
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700252 // set the OperState to disabled
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800253 if err := o.OperState.Event("disable"); err != nil {
254 onuLogger.WithFields(log.Fields{
255 "OnuId": o.ID,
256 "IntfId": o.PonPortID,
257 "OnuSn": o.Sn(),
258 }).Errorf("Cannot change ONU OperState to down: %s", err.Error())
259 }
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700260 // send the OnuIndication DOWN event
Matteo Scandolof9d43412021-01-12 11:11:34 -0800261 msg := bbsim.Message{
262 Type: bbsim.OnuIndication,
263 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700264 OnuSN: o.SerialNumber,
265 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800266 OperState: bbsim.DOWN,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700267 },
268 }
269 o.Channel <- msg
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530270
271 // verify all the flows removes are handled and
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100272 // terminate the ONU's ProcessOnuMessages Go routine
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530273 if len(o.FlowIds) == 0 {
274 close(o.Channel)
275 }
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700276
277 for _, s := range o.Services {
278 s.Disable()
279 }
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700280
281 },
282 fmt.Sprintf("enter_%s", OnuStatePonDisabled): func(event *fsm.Event) {
283 o.cleanupOnuState()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700284 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700285 // BBR states
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700286 fmt.Sprintf("enter_%s", BbrOnuStateEapolFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800287 msg := bbsim.Message{
288 Type: bbsim.SendEapolFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700289 }
290 o.Channel <- msg
291 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700292 fmt.Sprintf("enter_%s", BbrOnuStateDhcpFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800293 msg := bbsim.Message{
294 Type: bbsim.SendDhcpFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700295 }
296 o.Channel <- msg
297 },
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700298 },
299 )
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100300
Matteo Scandolo27428702019-10-11 16:21:16 -0700301 return &o
Matteo Scandolo4747d292019-08-05 11:50:18 -0700302}
303
William Kurkian0418bc82019-11-06 12:16:24 -0500304func (o *Onu) logStateChange(src string, dst string) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700305 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700306 "OnuId": o.ID,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700307 "IntfId": o.PonPortID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700308 "OnuSn": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700309 }).Debugf("Changing ONU InternalState from %s to %s", src, dst)
310}
311
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700312// cleanupOnuState this method is to clean the local state when the ONU is disabled
313func (o *Onu) cleanupOnuState() {
314 // clean the ONU state
315 o.PortNo = 0
316 o.Flows = []FlowKey{}
317 o.PonPort.removeOnuId(o.ID)
318 o.PonPort.removeAllocId(o.SerialNumber)
319 o.PonPort.removeGemPortBySn(o.SerialNumber)
320
321 o.onuAlarmsInfoLock.Lock()
322 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo) //Basically reset everything on onu disable
323 o.onuAlarmsInfoLock.Unlock()
324}
325
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100326// ProcessOnuMessages starts indication channel for each ONU
David Bainbridge103cf022019-12-16 20:11:35 +0000327func (o *Onu) ProcessOnuMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, client openolt.OpenoltClient) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700328 onuLogger.WithFields(log.Fields{
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100329 "onuID": o.ID,
330 "onuSN": o.Sn(),
331 "ponPort": o.PonPortID,
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700332 "stream": stream,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100333 }).Debug("Starting ONU Indication Channel")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700334
David Bainbridge103cf022019-12-16 20:11:35 +0000335loop:
336 for {
337 select {
338 case <-ctx.Done():
339 onuLogger.WithFields(log.Fields{
340 "onuID": o.ID,
341 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700342 }).Debug("ONU message handling canceled via context")
343 break loop
344 case <-stream.Context().Done():
345 onuLogger.WithFields(log.Fields{
346 "onuID": o.ID,
347 "onuSN": o.Sn(),
348 }).Debug("ONU message handling canceled via stream context")
David Bainbridge103cf022019-12-16 20:11:35 +0000349 break loop
350 case message, ok := <-o.Channel:
351 if !ok || ctx.Err() != nil {
352 onuLogger.WithFields(log.Fields{
353 "onuID": o.ID,
354 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700355 }).Debug("ONU message handling canceled via channel close")
David Bainbridge103cf022019-12-16 20:11:35 +0000356 break loop
Matteo Scandolo075b1892019-10-07 12:11:07 -0700357 }
David Bainbridge103cf022019-12-16 20:11:35 +0000358 onuLogger.WithFields(log.Fields{
359 "onuID": o.ID,
360 "onuSN": o.Sn(),
361 "messageType": message.Type,
362 }).Tracef("Received message on ONU Channel")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700363
David Bainbridge103cf022019-12-16 20:11:35 +0000364 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800365 case bbsim.OnuDiscIndication:
366 msg, _ := message.Data.(bbsim.OnuDiscIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000367 // NOTE we need to slow down and send ONU Discovery Indication in batches to better emulate a real scenario
Pragya Arya2225f202020-01-29 18:05:01 +0530368 time.Sleep(o.DiscoveryDelay)
David Bainbridge103cf022019-12-16 20:11:35 +0000369 o.sendOnuDiscIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800370 case bbsim.OnuIndication:
371 msg, _ := message.Data.(bbsim.OnuIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000372 o.sendOnuIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800373 case bbsim.OMCI:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800374 // these are OMCI messages received by the ONU
Matteo Scandolof9d43412021-01-12 11:11:34 -0800375 msg, _ := message.Data.(bbsim.OmciMessage)
376 o.handleOmciRequest(msg, stream)
377 case bbsim.UniStatusAlarm:
378 msg, _ := message.Data.(bbsim.UniStatusAlarmMessage)
Himani Chawla13b1ee02021-03-15 01:43:53 +0530379 onuAlarmMapKey := omcilib.OnuAlarmInfoMapKey{
380 MeInstance: msg.EntityID,
381 MeClassID: me.PhysicalPathTerminationPointEthernetUniClassID,
382 }
383 seqNo := o.IncrementAlarmSequenceNumber(onuAlarmMapKey)
384 o.onuAlarmsInfoLock.Lock()
385 var alarmInfo = o.onuAlarmsInfo[onuAlarmMapKey]
386 pkt, alarmBitMap := omcilib.CreateUniStatusAlarm(msg.RaiseOMCIAlarm, msg.EntityID, seqNo)
387 if pkt != nil { //pkt will be nil if we are unable to create the alarm
388 if err := o.sendOmciIndication(pkt, 0, stream); err != nil {
389 onuLogger.WithFields(log.Fields{
390 "IntfId": o.PonPortID,
391 "SerialNumber": o.Sn(),
392 "omciPacket": pkt,
393 "adminState": msg.AdminState,
394 "entityID": msg.EntityID,
395 }).Errorf("failed-to-send-UNI-Link-Alarm: %v", err)
396 alarmInfo.SequenceNo--
397 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800398 onuLogger.WithFields(log.Fields{
399 "IntfId": o.PonPortID,
400 "SerialNumber": o.Sn(),
401 "omciPacket": pkt,
402 "adminState": msg.AdminState,
403 "entityID": msg.EntityID,
Himani Chawla13b1ee02021-03-15 01:43:53 +0530404 }).Trace("UNI-Link-alarm-sent")
405 if alarmBitMap == [28]byte{0} {
406 delete(o.onuAlarmsInfo, onuAlarmMapKey)
407 } else {
408 alarmInfo.AlarmBitMap = alarmBitMap
409 o.onuAlarmsInfo[onuAlarmMapKey] = alarmInfo
410 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800411 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530412 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800413 case bbsim.FlowAdd:
414 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700415 o.handleFlowAdd(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800416 case bbsim.FlowRemoved:
417 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700418 o.handleFlowRemove(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800419 case bbsim.OnuPacketOut:
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700420
Matteo Scandolof9d43412021-01-12 11:11:34 -0800421 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000422
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700423 onuLogger.WithFields(log.Fields{
David Bainbridge103cf022019-12-16 20:11:35 +0000424 "IntfId": msg.IntfId,
425 "OnuId": msg.OnuId,
426 "pktType": msg.Type,
427 }).Trace("Received OnuPacketOut Message")
428
Matteo Scandolo618a6582020-09-09 12:21:29 -0700429 if msg.Type == packetHandlers.EAPOL || msg.Type == packetHandlers.DHCP {
430
431 service, err := o.findServiceByMacAddress(msg.MacAddress)
432 if err != nil {
433 onuLogger.WithFields(log.Fields{
434 "IntfId": msg.IntfId,
435 "OnuId": msg.OnuId,
436 "pktType": msg.Type,
437 "MacAddress": msg.MacAddress,
438 "Pkt": hex.EncodeToString(msg.Packet.Data()),
439 "OnuSn": o.Sn(),
440 }).Error("Cannot find Service associated with packet")
441 return
442 }
443 service.PacketCh <- msg
444 } else if msg.Type == packetHandlers.IGMP {
445 // if it's an IGMP packet we assume we have a single IGMP service
446 for _, s := range o.Services {
447 service := s.(*Service)
448
449 if service.NeedsIgmp {
450 service.PacketCh <- msg
451 }
452 }
David Bainbridge103cf022019-12-16 20:11:35 +0000453 }
Matteo Scandolo4a036262020-08-17 15:56:13 -0700454
Matteo Scandolof9d43412021-01-12 11:11:34 -0800455 case bbsim.OnuPacketIn:
David Bainbridge103cf022019-12-16 20:11:35 +0000456 // NOTE we only receive BBR packets here.
457 // Eapol.HandleNextPacket can handle both BBSim and BBr cases so the call is the same
458 // in the DHCP case VOLTHA only act as a proxy, the behaviour is completely different thus we have a dhcp.HandleNextBbrPacket
Matteo Scandolof9d43412021-01-12 11:11:34 -0800459 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000460
461 log.WithFields(log.Fields{
462 "IntfId": msg.IntfId,
463 "OnuId": msg.OnuId,
464 "pktType": msg.Type,
465 }).Trace("Received OnuPacketIn Message")
466
467 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700468 eapol.HandleNextPacket(msg.OnuId, msg.IntfId, msg.GemPortId, o.Sn(), o.PortNo, o.InternalState, msg.Packet, stream, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000469 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700470 _ = dhcp.HandleNextBbrPacket(o.ID, o.PonPortID, o.Sn(), o.DoneChannel, msg.Packet, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000471 }
Matteo Scandolo7f656fb2020-09-08 15:18:15 -0700472 // BBR specific messages
Matteo Scandolof9d43412021-01-12 11:11:34 -0800473 case bbsim.OmciIndication:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800474 // these are OMCI messages received by BBR (VOLTHA emulator)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800475 msg, _ := message.Data.(bbsim.OmciIndicationMessage)
476 o.handleOmciResponse(msg, client)
477 case bbsim.SendEapolFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000478 o.sendEapolFlow(client)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800479 case bbsim.SendDhcpFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000480 o.sendDhcpFlow(client)
481 default:
482 onuLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700483 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700484 }
485 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100486 onuLogger.WithFields(log.Fields{
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700487 "onuID": o.ID,
488 "onuSN": o.Sn(),
489 "stream": stream,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100490 }).Debug("Stopped handling ONU Indication Channel")
Matteo Scandolo4747d292019-08-05 11:50:18 -0700491}
492
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800493func NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700494 sn := new(openolt.SerialNumber)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700495 sn.VendorId = []byte("BBSM")
496 sn.VendorSpecific = []byte{0, byte(oltid % 256), byte(intfid), byte(onuid)}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700497 return sn
498}
499
Matteo Scandolof9d43412021-01-12 11:11:34 -0800500func (o *Onu) sendOnuDiscIndication(msg bbsim.OnuDiscIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700501 discoverData := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800502 IntfId: o.PonPortID,
503 SerialNumber: o.SerialNumber,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700504 }}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700505
Matteo Scandolo4747d292019-08-05 11:50:18 -0700506 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700507 log.Errorf("Failed to send Indication_OnuDiscInd: %v", err)
Matteo Scandolo99f18462019-10-28 14:14:28 -0700508 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700509 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700510
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700511 onuLogger.WithFields(log.Fields{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800512 "IntfId": o.PonPortID,
513 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700514 "OnuId": o.ID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700515 }).Debug("Sent Indication_OnuDiscInd")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800516 publishEvent("ONU-discovery-indication-sent", int32(o.PonPortID), int32(o.ID), o.Sn())
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800517
518 // after DiscoveryRetryDelay check if the state is the same and in case send a new OnuDiscIndication
519 go func(delay time.Duration) {
Matteo Scandolo569e7172019-12-20 11:51:51 -0800520 time.Sleep(delay)
Matteo Scandolocedde462021-03-09 17:37:16 -0800521 if o.InternalState.Current() == OnuStateDiscovered {
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800522 o.sendOnuDiscIndication(msg, stream)
523 }
524 }(o.DiscoveryRetryDelay)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700525}
526
Matteo Scandolof9d43412021-01-12 11:11:34 -0800527func (o *Onu) sendOnuIndication(msg bbsim.OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800528 // NOTE the ONU ID is set by VOLTHA in the ActivateOnu call (via openolt.proto)
529 // and stored in the Onu struct via onu.SetID
Matteo Scandolo4747d292019-08-05 11:50:18 -0700530
531 indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700532 IntfId: o.PonPortID,
533 OnuId: o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700534 OperState: msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700535 AdminState: o.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700536 SerialNumber: o.SerialNumber,
537 }}
538 if err := stream.Send(&openolt.Indication{Data: indData}); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800539 // NOTE do we need to transition to a broken state?
Matteo Scandolo11006992019-08-28 11:29:46 -0700540 log.Errorf("Failed to send Indication_OnuInd: %v", err)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700541 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700542 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700543 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800544 "IntfId": o.PonPortID,
545 "OnuId": o.ID,
546 "VolthaOnuId": msg.OnuID,
547 "OperState": msg.OperState.String(),
548 "AdminState": msg.OperState.String(),
549 "OnuSn": o.Sn(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700550 }).Debug("Sent Indication_OnuInd")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700551
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700552}
553
Matteo Scandolof9d43412021-01-12 11:11:34 -0800554func (o *Onu) HandleShutdownONU() error {
555
556 dyingGasp := pb.ONUAlarmRequest{
557 AlarmType: "DYING_GASP",
558 SerialNumber: o.Sn(),
559 Status: "on",
560 }
561
562 if err := alarmsim.SimulateOnuAlarm(&dyingGasp, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
563 onuLogger.WithFields(log.Fields{
564 "OnuId": o.ID,
565 "IntfId": o.PonPortID,
566 "OnuSn": o.Sn(),
567 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
568 return err
569 }
570
571 losReq := pb.ONUAlarmRequest{
572 AlarmType: "ONU_ALARM_LOS",
573 SerialNumber: o.Sn(),
574 Status: "on",
575 }
576
577 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
578 onuLogger.WithFields(log.Fields{
579 "OnuId": o.ID,
580 "IntfId": o.PonPortID,
581 "OnuSn": o.Sn(),
582 }).Errorf("Cannot send LOS: %s", err.Error())
583
584 return err
585 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530586 o.SendOMCIAlarmNotificationMsg(true, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800587 // TODO if it's the last ONU on the PON, then send a PON LOS
588
Matteo Scandolocedde462021-03-09 17:37:16 -0800589 if err := o.InternalState.Event(OnuTxDisable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800590 onuLogger.WithFields(log.Fields{
591 "OnuId": o.ID,
592 "IntfId": o.PonPortID,
593 "OnuSn": o.Sn(),
594 }).Errorf("Cannot shutdown ONU: %s", err.Error())
595 return err
596 }
597
598 return nil
599}
600
601func (o *Onu) HandlePowerOnONU() error {
602 intitalState := o.InternalState.Current()
603
604 // initialize the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800605 if intitalState == OnuStateCreated || intitalState == OnuStateDisabled {
606 if err := o.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800607 onuLogger.WithFields(log.Fields{
608 "OnuId": o.ID,
609 "IntfId": o.PonPortID,
610 "OnuSn": o.Sn(),
611 }).Errorf("Cannot poweron ONU: %s", err.Error())
612 return err
613 }
614 }
615
616 // turn off the LOS Alarm
617 losReq := pb.ONUAlarmRequest{
618 AlarmType: "ONU_ALARM_LOS",
619 SerialNumber: o.Sn(),
620 Status: "off",
621 }
622
623 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
624 onuLogger.WithFields(log.Fields{
625 "OnuId": o.ID,
626 "IntfId": o.PonPortID,
627 "OnuSn": o.Sn(),
628 }).Errorf("Cannot send LOS: %s", err.Error())
629 return err
630 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530631 o.SendOMCIAlarmNotificationMsg(false, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800632
633 // Send a ONU Discovery indication
Matteo Scandolocedde462021-03-09 17:37:16 -0800634 if err := o.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800635 onuLogger.WithFields(log.Fields{
636 "OnuId": o.ID,
637 "IntfId": o.PonPortID,
638 "OnuSn": o.Sn(),
639 }).Errorf("Cannot poweron ONU: %s", err.Error())
640 return err
641 }
642
643 // move o directly to enable state only when its a powercycle case
644 // in case of first time o poweron o will be moved to enable on
645 // receiving ActivateOnu request from openolt adapter
Matteo Scandolocedde462021-03-09 17:37:16 -0800646 if intitalState == OnuStateDisabled {
647 if err := o.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800648 onuLogger.WithFields(log.Fields{
649 "OnuId": o.ID,
650 "IntfId": o.PonPortID,
651 "OnuSn": o.Sn(),
652 }).Errorf("Cannot enable ONU: %s", err.Error())
653 return err
654 }
655 }
656
657 return nil
658}
659
660func (o *Onu) SetAlarm(alarmType string, status string) error {
661 alarmReq := pb.ONUAlarmRequest{
662 AlarmType: alarmType,
663 SerialNumber: o.Sn(),
664 Status: status,
665 }
666
667 err := alarmsim.SimulateOnuAlarm(&alarmReq, o.ID, o.PonPortID, o.PonPort.Olt.channel)
668 if err != nil {
669 return err
670 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530671 raiseAlarm := false
672 if alarmReq.Status == "on" {
673 raiseAlarm = true
674 }
675 o.SendOMCIAlarmNotificationMsg(raiseAlarm, alarmReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800676 return nil
677}
678
679func (o *Onu) publishOmciEvent(msg bbsim.OmciMessage) {
Pragya Arya324337e2020-02-20 14:35:08 +0530680 if olt.PublishEvents {
Matteo Scandolob5913142021-03-19 16:10:18 -0700681 _, omciMsg, err := omcilib.ParseOpenOltOmciPacket(msg.OmciPkt.Data())
Pragya Arya324337e2020-02-20 14:35:08 +0530682 if err != nil {
683 log.Errorf("error in getting msgType %v", err)
684 return
685 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800686 if omciMsg.MessageType == omci.MibUploadRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530687 o.seqNumber = 0
688 publishEvent("MIB-upload-received", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
Matteo Scandolof9d43412021-01-12 11:11:34 -0800689 } else if omciMsg.MessageType == omci.MibUploadNextRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530690 o.seqNumber++
691 if o.seqNumber > 290 {
692 publishEvent("MIB-upload-done", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
693 }
694 }
695 }
696}
697
Scott Bakerb90c4312020-03-12 21:33:25 -0700698// Create a TestResponse packet and send it
Matteo Scandolof9d43412021-01-12 11:11:34 -0800699func (o *Onu) sendTestResult(msg bbsim.OmciMessage, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolob5913142021-03-19 16:10:18 -0700700 resp, err := omcilib.BuildTestResult(msg.OmciPkt.Data())
Scott Bakerb90c4312020-03-12 21:33:25 -0700701 if err != nil {
702 return err
703 }
704
705 var omciInd openolt.OmciIndication
706 omciInd.IntfId = o.PonPortID
707 omciInd.OnuId = o.ID
708 omciInd.Pkt = resp
709
710 omci := &openolt.Indication_OmciInd{OmciInd: &omciInd}
711 if err := stream.Send(&openolt.Indication{Data: omci}); err != nil {
Scott Bakerb90c4312020-03-12 21:33:25 -0700712 return err
713 }
714 onuLogger.WithFields(log.Fields{
715 "IntfId": o.PonPortID,
716 "SerialNumber": o.Sn(),
717 "omciPacket": omciInd.Pkt,
718 }).Tracef("Sent TestResult OMCI message")
719
720 return nil
721}
722
Matteo Scandolof9d43412021-01-12 11:11:34 -0800723// handleOmciRequest is responsible to parse the OMCI packets received from the openolt adapter
724// and generate the appropriate response to it
725func (o *Onu) handleOmciRequest(msg bbsim.OmciMessage, stream openolt.Openolt_EnableIndicationServer) {
726
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700727 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700728 "omciMsgType": msg.OmciMsg.MessageType,
729 "transCorrId": strconv.FormatInt(int64(msg.OmciMsg.TransactionID), 16),
730 "DeviceIdent": msg.OmciMsg.DeviceIdentifier,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700731 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -0700732 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -0800733 }).Trace("omci-message-decoded")
734
735 var responsePkt []byte
Girish Gowdrae2683102021-03-05 08:24:26 -0800736 var errResp error
Matteo Scandolob5913142021-03-19 16:10:18 -0700737 switch msg.OmciMsg.MessageType {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800738 case omci.MibResetRequestType:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800739 onuLogger.WithFields(log.Fields{
740 "IntfId": o.PonPortID,
741 "OnuId": o.ID,
742 "SerialNumber": o.Sn(),
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700743 }).Debug("received-mib-reset-request")
Matteo Scandolob5913142021-03-19 16:10:18 -0700744 if responsePkt, errResp = omcilib.CreateMibResetResponse(msg.OmciMsg.TransactionID); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800745 o.MibDataSync = 0
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700746
747 // if the MIB reset is successful then remove all the stored AllocIds and GemPorts
748 o.PonPort.removeAllocId(o.SerialNumber)
749 o.PonPort.removeGemPortBySn(o.SerialNumber)
Girish Gowdrae2683102021-03-05 08:24:26 -0800750 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800751 case omci.MibUploadRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700752 responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg.TransactionID)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800753 case omci.MibUploadNextRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700754 responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDataSync)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800755 case omci.GetRequestType:
Girish Gowdra996d81e2021-04-21 16:16:27 -0700756 onuDown := o.OperState.Current() == "down"
757 responsePkt, _ = omcilib.CreateGetResponse(msg.OmciPkt, msg.OmciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId, o.CommittedImageEntityId, onuDown)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800758 case omci.SetRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800759 success := true
Matteo Scandolob5913142021-03-19 16:10:18 -0700760 msgObj, _ := omcilib.ParseSetRequest(msg.OmciPkt)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800761 switch msgObj.EntityClass {
762 case me.PhysicalPathTerminationPointEthernetUniClassID:
763 // if we're Setting a PPTP state
764 // we need to send the appropriate alarm
765
766 if msgObj.EntityInstance == 257 {
767 // for now we're only caring about the first UNI
768 // NOTE that the EntityID for the UNI port is for now hardcoded in
769 // omci/mibpackets.go where the PhysicalPathTerminationPointEthernetUni
770 // are reported during the MIB Upload sequence
771 adminState := msgObj.Attributes["AdministrativeState"].(uint8)
Himani Chawla13b1ee02021-03-15 01:43:53 +0530772 raiseOMCIAlarm := false
773 if adminState == 1 {
774 raiseOMCIAlarm = true
Girish Gowdra996d81e2021-04-21 16:16:27 -0700775 // set the OperState to disabled
776 if err := o.OperState.Event(OnuTxDisable); err != nil {
777 onuLogger.WithFields(log.Fields{
778 "OnuId": o.ID,
779 "IntfId": o.PonPortID,
780 "OnuSn": o.Sn(),
781 }).Errorf("Cannot change ONU OperState to down: %s", err.Error())
782 }
783 } else {
784 // set the OperState to enabled
785 if err := o.OperState.Event(OnuTxEnable); err != nil {
786 onuLogger.WithFields(log.Fields{
787 "OnuId": o.ID,
788 "IntfId": o.PonPortID,
789 "OnuSn": o.Sn(),
790 }).Errorf("Cannot change ONU OperState to up: %s", err.Error())
791 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530792 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800793 msg := bbsim.Message{
794 Type: bbsim.UniStatusAlarm,
795 Data: bbsim.UniStatusAlarmMessage{
Himani Chawla13b1ee02021-03-15 01:43:53 +0530796 OnuSN: o.SerialNumber,
797 OnuID: o.ID,
798 AdminState: adminState,
799 EntityID: msgObj.EntityInstance,
800 RaiseOMCIAlarm: raiseOMCIAlarm,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800801 },
802 }
803 o.Channel <- msg
804 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800805 case me.TContClassID:
806 allocId := msgObj.Attributes["AllocId"].(uint16)
807
808 // if the AllocId is 255 (0xFF) or 65535 (0xFFFF) it means we are removing it,
809 // otherwise we are adding it
810 if allocId == 255 || allocId == 65535 {
811 onuLogger.WithFields(log.Fields{
812 "IntfId": o.PonPortID,
813 "OnuId": o.ID,
814 "TContId": msgObj.EntityInstance,
815 "AllocId": allocId,
816 "SerialNumber": o.Sn(),
817 }).Trace("freeing-alloc-id-via-omci")
818 o.PonPort.removeAllocId(o.SerialNumber)
819 } else {
820 if used, sn := o.PonPort.isAllocIdAllocated(allocId); used {
821 onuLogger.WithFields(log.Fields{
822 "IntfId": o.PonPortID,
823 "OnuId": o.ID,
824 "AllocId": allocId,
825 "SerialNumber": o.Sn(),
826 }).Errorf("allocid-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
827 success = false
828 } else {
829 onuLogger.WithFields(log.Fields{
830 "IntfId": o.PonPortID,
831 "OnuId": o.ID,
832 "TContId": msgObj.EntityInstance,
833 "AllocId": allocId,
834 "SerialNumber": o.Sn(),
835 }).Trace("storing-alloc-id-via-omci")
836 o.PonPort.storeAllocId(allocId, o.SerialNumber)
837 }
838 }
839
840 }
841
842 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -0700843 if responsePkt, errResp = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800844 o.MibDataSync++
845 }
846 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700847 responsePkt, _ = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.AttributeFailure)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800848 }
849 case omci.CreateRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800850 // check for GemPortNetworkCtp and make sure there are no duplicates on the same PON
851 var used bool
852 var sn *openolt.SerialNumber
Matteo Scandolob5913142021-03-19 16:10:18 -0700853 msgObj, err := omcilib.ParseCreateRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800854 if err == nil {
855 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
Matteo Scandolo973b0182021-04-08 11:24:42 -0700856 // GemPort 4069 is reserved for multicast and shared across ONUs
857 if msgObj.EntityInstance != 4069 {
858 if used, sn = o.PonPort.isGemPortAllocated(msgObj.EntityInstance); used {
859 onuLogger.WithFields(log.Fields{
860 "IntfId": o.PonPortID,
861 "OnuId": o.ID,
862 "GemPortId": msgObj.EntityInstance,
863 "SerialNumber": o.Sn(),
864 }).Errorf("gemport-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
865 } else {
866 onuLogger.WithFields(log.Fields{
867 "IntfId": o.PonPortID,
868 "OnuId": o.ID,
869 "GemPortId": msgObj.EntityInstance,
870 "SerialNumber": o.Sn(),
871 }).Trace("storing-gem-port-id-via-omci")
872 o.PonPort.storeGemPort(msgObj.EntityInstance, o.SerialNumber)
873 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800874 }
875 }
876 }
877
878 // if the gemPort is valid then increment the MDS and return a successful response
879 // otherwise fail the request
880 // for now the CreateRequeste for the gemPort is the only one that can fail, if we start supporting multiple
881 // validation this check will need to be rewritten
882 if !used {
Matteo Scandolob5913142021-03-19 16:10:18 -0700883 if responsePkt, errResp = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800884 o.MibDataSync++
885 }
886 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700887 responsePkt, _ = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError)
Girish Gowdrae2683102021-03-05 08:24:26 -0800888 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800889 case omci.DeleteRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700890 msgObj, err := omcilib.ParseDeleteRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800891 if err == nil {
892 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
893 onuLogger.WithFields(log.Fields{
894 "IntfId": o.PonPortID,
895 "OnuId": o.ID,
896 "GemPortId": msgObj.EntityInstance,
897 "SerialNumber": o.Sn(),
898 }).Trace("freeing-gem-port-id-via-omci")
899 o.PonPort.removeGemPort(msgObj.EntityInstance)
900 }
901 }
902
Matteo Scandolob5913142021-03-19 16:10:18 -0700903 if responsePkt, errResp = omcilib.CreateDeleteResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800904 o.MibDataSync++
905 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800906 case omci.RebootRequestType:
907
Matteo Scandolob5913142021-03-19 16:10:18 -0700908 responsePkt, _ = omcilib.CreateRebootResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800909
910 // powercycle the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800911 // we run this in a separate goroutine so that
912 // the RebootRequestResponse is sent to VOLTHA
Matteo Scandolof9d43412021-01-12 11:11:34 -0800913 go func() {
Matteo Scandolocedde462021-03-09 17:37:16 -0800914 if err := o.Reboot(10 * time.Second); err != nil {
915 log.WithFields(log.Fields{
916 "IntfId": o.PonPortID,
917 "OnuId": o.ID,
918 "SerialNumber": o.Sn(),
919 "err": err,
920 }).Error("cannot-reboot-onu-after-omci-reboot-request")
921 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800922 }()
923 case omci.TestRequestType:
924
925 // Test message is special, it requires sending two packets:
926 // first packet: TestResponse, says whether test was started successully, handled by omci-sim
927 // second packet, TestResult, reports the result of running the self-test
928 // TestResult can come some time after a TestResponse
929 // TODO: Implement some delay between the TestResponse and the TestResult
Matteo Scandolob5913142021-03-19 16:10:18 -0700930 isTest, err := omcilib.IsTestRequest(msg.OmciPkt.Data())
Matteo Scandolof9d43412021-01-12 11:11:34 -0800931 if (err == nil) && (isTest) {
932 if sendErr := o.sendTestResult(msg, stream); sendErr != nil {
933 onuLogger.WithFields(log.Fields{
934 "IntfId": o.PonPortID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800935 "OnuId": o.ID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800936 "SerialNumber": o.Sn(),
Matteo Scandolob5913142021-03-19 16:10:18 -0700937 "omciPacket": msg.OmciPkt.Data(),
Matteo Scandolof9d43412021-01-12 11:11:34 -0800938 "msg": msg,
939 "err": sendErr,
940 }).Error("send-TestResult-indication-failed")
941 }
942 }
Girish Gowdraa539f522021-02-15 23:00:45 -0800943 case omci.SynchronizeTimeRequestType:
944 // MDS counter increment is not required for this message type
Matteo Scandolob5913142021-03-19 16:10:18 -0700945 responsePkt, _ = omcilib.CreateSyncTimeResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolocedde462021-03-09 17:37:16 -0800946 case omci.StartSoftwareDownloadRequestType:
947
948 o.ImageSoftwareReceivedSections = 0
949
Matteo Scandolob5913142021-03-19 16:10:18 -0700950 o.ImageSoftwareExpectedSections = omcilib.ComputeDownloadSectionsCount(msg.OmciPkt)
Matteo Scandolocedde462021-03-09 17:37:16 -0800951
Matteo Scandolob5913142021-03-19 16:10:18 -0700952 if responsePkt, errResp = omcilib.CreateStartSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -0800953 o.MibDataSync++
954 if err := o.InternalState.Event(OnuTxStartImageDownload); err != nil {
955 onuLogger.WithFields(log.Fields{
956 "OnuId": o.ID,
957 "IntfId": o.PonPortID,
958 "OnuSn": o.Sn(),
959 "Err": err.Error(),
960 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadStarted)
961 }
962 } else {
963 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700964 "OmciMsgType": msg.OmciMsg.MessageType,
965 "TransCorrId": msg.OmciMsg.TransactionID,
966 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -0800967 "IntfId": o.PonPortID,
968 "SerialNumber": o.Sn(),
969 }).Error("error-while-processing-start-software-download-request")
970 }
971 case omci.DownloadSectionRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700972 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -0800973 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700974 "OmciMsgType": msg.OmciMsg.MessageType,
975 "TransCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolocedde462021-03-09 17:37:16 -0800976 "EntityInstance": msgObj.EntityInstance,
977 "SectionNumber": msgObj.SectionNumber,
978 "SectionData": msgObj.SectionData,
979 }).Trace("received-download-section-request")
980 o.ImageSoftwareReceivedSections++
981 if o.InternalState.Current() != OnuStateImageDownloadInProgress {
982 if err := o.InternalState.Event(OnuTxProgressImageDownload); err != nil {
983 onuLogger.WithFields(log.Fields{
984 "OnuId": o.ID,
985 "IntfId": o.PonPortID,
986 "OnuSn": o.Sn(),
987 "Err": err.Error(),
988 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadInProgress)
989 }
990 }
991 }
992 case omci.DownloadSectionRequestWithResponseType:
993 // NOTE we only need to respond if an ACK is requested
Matteo Scandolob5913142021-03-19 16:10:18 -0700994 responsePkt, errResp = omcilib.CreateDownloadSectionResponse(msg.OmciPkt, msg.OmciMsg)
995 if errResp != nil {
Matteo Scandolocedde462021-03-09 17:37:16 -0800996 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700997 "OmciMsgType": msg.OmciMsg.MessageType,
998 "TransCorrId": msg.OmciMsg.TransactionID,
999 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001000 "IntfId": o.PonPortID,
1001 "SerialNumber": o.Sn(),
1002 }).Error("error-while-processing-create-download-section-response")
1003 return
1004 }
1005 o.ImageSoftwareReceivedSections++
1006
1007 case omci.EndSoftwareDownloadRequestType:
1008
1009 // In the startSoftwareDownload we get the image size and the window size.
1010 // We calculate how many DownloadSection we should receive and validate
1011 // that we got the correct amount when we receive this message
1012 success := true
1013 if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
1014 onuLogger.WithFields(log.Fields{
1015 "OnuId": o.ID,
1016 "IntfId": o.PonPortID,
1017 "OnuSn": o.Sn(),
1018 "ExpectedSections": o.ImageSoftwareExpectedSections,
1019 "ReceivedSections": o.ImageSoftwareReceivedSections,
1020 }).Errorf("onu-did-not-receive-all-image-sections")
1021 success = false
1022 }
1023
1024 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -07001025 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001026 o.MibDataSync++
1027 if err := o.InternalState.Event(OnuTxCompleteImageDownload); err != nil {
1028 onuLogger.WithFields(log.Fields{
1029 "OnuId": o.ID,
1030 "IntfId": o.PonPortID,
1031 "OnuSn": o.Sn(),
1032 "Err": err.Error(),
1033 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadComplete)
1034 }
1035 } else {
1036 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001037 "OmciMsgType": msg.OmciMsg.MessageType,
1038 "TransCorrId": msg.OmciMsg.TransactionID,
1039 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001040 "IntfId": o.PonPortID,
1041 "SerialNumber": o.Sn(),
1042 }).Error("error-while-processing-end-software-download-request")
1043 }
1044 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -07001045 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001046 if err := o.InternalState.Event(OnuTxFailImageDownload); err != nil {
1047 onuLogger.WithFields(log.Fields{
1048 "OnuId": o.ID,
1049 "IntfId": o.PonPortID,
1050 "OnuSn": o.Sn(),
1051 "Err": err.Error(),
1052 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadError)
1053 }
1054 }
1055 }
1056
1057 case omci.ActivateSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001058 if responsePkt, errResp = omcilib.CreateActivateSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001059 o.MibDataSync++
1060 if err := o.InternalState.Event(OnuTxActivateImage); err != nil {
1061 onuLogger.WithFields(log.Fields{
1062 "OnuId": o.ID,
1063 "IntfId": o.PonPortID,
1064 "OnuSn": o.Sn(),
1065 "Err": err.Error(),
1066 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageActivated)
1067 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001068 if msgObj, err := omcilib.ParseActivateSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001069 o.ActiveImageEntityId = msgObj.EntityInstance
1070 } else {
1071 onuLogger.Errorf("something-went-wrong-while-activating: %s", err)
1072 }
1073 onuLogger.WithFields(log.Fields{
1074 "OnuId": o.ID,
1075 "IntfId": o.PonPortID,
1076 "OnuSn": o.Sn(),
1077 "ActiveImageEntityId": o.ActiveImageEntityId,
1078 "CommittedImageEntityId": o.CommittedImageEntityId,
1079 }).Info("onu-software-image-activated")
1080
1081 // powercycle the ONU
1082 // we run this in a separate goroutine so that
1083 // the ActivateSoftwareResponse is sent to VOLTHA
1084 // NOTE do we need to wait before rebooting?
1085 go func() {
1086 if err := o.Reboot(10 * time.Second); err != nil {
1087 log.WithFields(log.Fields{
1088 "IntfId": o.PonPortID,
1089 "OnuId": o.ID,
1090 "SerialNumber": o.Sn(),
1091 "err": err,
1092 }).Error("cannot-reboot-onu-after-omci-activate-software-request")
1093 }
1094 }()
1095 }
1096 case omci.CommitSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001097 if responsePkt, errResp = omcilib.CreateCommitSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001098 o.MibDataSync++
Matteo Scandolob5913142021-03-19 16:10:18 -07001099 if msgObj, err := omcilib.ParseCommitSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001100 // TODO validate that the image to commit is:
1101 // - active
1102 // - not already committed
1103 o.CommittedImageEntityId = msgObj.EntityInstance
1104 } else {
1105 onuLogger.Errorf("something-went-wrong-while-committing: %s", err)
1106 }
1107 if err := o.InternalState.Event(OnuTxCommitImage); err != nil {
1108 onuLogger.WithFields(log.Fields{
1109 "OnuId": o.ID,
1110 "IntfId": o.PonPortID,
1111 "OnuSn": o.Sn(),
1112 "Err": err.Error(),
1113 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageCommitted)
1114 }
1115 onuLogger.WithFields(log.Fields{
1116 "OnuId": o.ID,
1117 "IntfId": o.PonPortID,
1118 "OnuSn": o.Sn(),
1119 "ActiveImageEntityId": o.ActiveImageEntityId,
1120 "CommittedImageEntityId": o.CommittedImageEntityId,
1121 }).Info("onu-software-image-committed")
1122 }
Himani Chawla13b1ee02021-03-15 01:43:53 +05301123 case omci.GetAllAlarmsRequestType:
1124 // Reset the alarm sequence number on receiving get all alarms request.
1125 o.onuAlarmsInfoLock.Lock()
1126 for key, alarmInfo := range o.onuAlarmsInfo {
1127 // reset the alarm sequence no
1128 alarmInfo.SequenceNo = 0
1129 o.onuAlarmsInfo[key] = alarmInfo
1130 }
1131 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolob5913142021-03-19 16:10:18 -07001132 responsePkt, _ = omcilib.CreateGetAllAlarmsResponse(msg.OmciMsg.TransactionID, o.onuAlarmsInfo)
Himani Chawla13b1ee02021-03-15 01:43:53 +05301133 case omci.GetAllAlarmsNextRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001134 if responsePkt, errResp = omcilib.CreateGetAllAlarmsNextResponse(msg.OmciPkt, msg.OmciMsg, o.onuAlarmsInfo); errResp != nil {
Himani Chawla13b1ee02021-03-15 01:43:53 +05301135 responsePkt = nil //Do not send any response for error case
1136 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001137 default:
Matteo Scandolocedde462021-03-09 17:37:16 -08001138 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001139 "omciBytes": hex.EncodeToString(msg.OmciPkt.Data()),
1140 "omciPkt": msg.OmciPkt,
1141 "omciMsgType": msg.OmciMsg.MessageType,
1142 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001143 "IntfId": o.PonPortID,
1144 "SerialNumber": o.Sn(),
1145 }).Warnf("OMCI-message-not-supported")
1146 }
1147
1148 if responsePkt != nil {
Matteo Scandolob5913142021-03-19 16:10:18 -07001149 if err := o.sendOmciIndication(responsePkt, msg.OmciMsg.TransactionID, stream); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001150 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001151 "IntfId": o.PonPortID,
1152 "SerialNumber": o.Sn(),
1153 "omciPacket": responsePkt,
1154 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1155 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001156 }).Errorf("failed-to-send-omci-message: %v", err)
1157 }
1158 }
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001159
Pragya Arya324337e2020-02-20 14:35:08 +05301160 o.publishOmciEvent(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -08001161}
Pragya Arya324337e2020-02-20 14:35:08 +05301162
Matteo Scandolof9d43412021-01-12 11:11:34 -08001163// sendOmciIndication takes an OMCI packet and sends it up to VOLTHA
1164func (o *Onu) sendOmciIndication(responsePkt []byte, txId uint16, stream bbsim.Stream) error {
1165 indication := &openolt.Indication_OmciInd{
1166 OmciInd: &openolt.OmciIndication{
1167 IntfId: o.PonPortID,
1168 OnuId: o.ID,
1169 Pkt: responsePkt,
1170 },
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001171 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001172 if err := stream.Send(&openolt.Indication{Data: indication}); err != nil {
1173 return fmt.Errorf("failed-to-send-omci-message: %v", err)
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001174 }
1175 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001176 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -07001177 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -08001178 "omciPacket": indication.OmciInd.Pkt,
1179 "transCorrId": txId,
1180 }).Trace("omci-message-sent")
1181 return nil
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001182}
1183
Matteo Scandolo27428702019-10-11 16:21:16 -07001184func (o *Onu) storePortNumber(portNo uint32) {
Matteo Scandolo813402b2019-10-23 19:24:52 -07001185 // NOTE this needed only as long as we don't support multiple UNIs
Matteo Scandolo27428702019-10-11 16:21:16 -07001186 // we need to add support for multiple UNIs
1187 // the action plan is:
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001188 // - refactor the omcisim-sim library to use https://github.com/cboling/omci instead of canned messages
Matteo Scandolo27428702019-10-11 16:21:16 -07001189 // - change the library so that it reports a single UNI and remove this workaroung
1190 // - add support for multiple UNIs in BBSim
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001191 if o.PortNo == 0 || portNo < o.PortNo {
Matteo Scandolo813402b2019-10-23 19:24:52 -07001192 onuLogger.WithFields(log.Fields{
1193 "IntfId": o.PonPortID,
1194 "OnuId": o.ID,
1195 "SerialNumber": o.Sn(),
1196 "OnuPortNo": o.PortNo,
1197 "FlowPortNo": portNo,
1198 }).Debug("Storing ONU portNo")
Matteo Scandolo27428702019-10-11 16:21:16 -07001199 o.PortNo = portNo
1200 }
1201}
1202
William Kurkian0418bc82019-11-06 12:16:24 -05001203func (o *Onu) SetID(id uint32) {
Matteo Scandolo583f17d2020-02-13 10:35:17 -08001204 onuLogger.WithFields(log.Fields{
1205 "IntfId": o.PonPortID,
1206 "OnuId": id,
1207 "SerialNumber": o.Sn(),
1208 }).Debug("Storing OnuId ")
William Kurkian0418bc82019-11-06 12:16:24 -05001209 o.ID = id
1210}
1211
Matteo Scandolof9d43412021-01-12 11:11:34 -08001212func (o *Onu) handleFlowAdd(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001213 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001214 "AllocId": msg.Flow.AllocId,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001215 "Cookie": msg.Flow.Cookie,
1216 "DstPort": msg.Flow.Classifier.DstPort,
1217 "FlowId": msg.Flow.FlowId,
1218 "FlowType": msg.Flow.FlowType,
1219 "GemportId": msg.Flow.GemportId,
1220 "InnerVlan": msg.Flow.Classifier.IVid,
1221 "IntfId": msg.Flow.AccessIntfId,
1222 "IpProto": msg.Flow.Classifier.IpProto,
1223 "OnuId": msg.Flow.OnuId,
1224 "OnuSn": o.Sn(),
1225 "OuterVlan": msg.Flow.Classifier.OVid,
1226 "PortNo": msg.Flow.PortNo,
1227 "SrcPort": msg.Flow.Classifier.SrcPort,
1228 "UniID": msg.Flow.UniId,
1229 "ClassifierEthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
1230 "ClassifierOPbits": msg.Flow.Classifier.OPbits,
1231 "ClassifierIVid": msg.Flow.Classifier.IVid,
1232 "ClassifierOVid": msg.Flow.Classifier.OVid,
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001233 "ReplicateFlow": msg.Flow.ReplicateFlow,
1234 "PbitToGemport": msg.Flow.PbitToGemport,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001235 }).Debug("OLT receives FlowAdd for ONU")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001236
Matteo Scandolo813402b2019-10-23 19:24:52 -07001237 if msg.Flow.UniId != 0 {
1238 // as of now BBSim only support a single UNI, so ignore everything that is not targeted to it
1239 onuLogger.WithFields(log.Fields{
1240 "IntfId": o.PonPortID,
1241 "OnuId": o.ID,
1242 "SerialNumber": o.Sn(),
1243 }).Debug("Ignoring flow as it's not for the first UNI")
1244 return
1245 }
1246
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001247 o.FlowIds = append(o.FlowIds, msg.Flow.FlowId)
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001248
1249 var gemPortId uint32
1250 if msg.Flow.ReplicateFlow {
1251 // This means that the OLT should replicate the flow for each PBIT, for BBSim it's enough to use the
1252 // first available gemport (we only need to send one packet)
1253 // NOTE different TP may create different mapping between PBits and GemPorts, this may require some changes
1254 gemPortId = msg.Flow.PbitToGemport[0]
1255 } else {
1256 // if replicateFlows is false, then the flow is carrying the correct GemPortId
1257 gemPortId = uint32(msg.Flow.GemportId)
1258 }
1259 o.addGemPortToService(gemPortId, msg.Flow.Classifier.EthType, msg.Flow.Classifier.OVid, msg.Flow.Classifier.IVid)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001260
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001261 if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
Matteo Scandolo27428702019-10-11 16:21:16 -07001262 // NOTE storing the PortNO, it's needed when sending PacketIndications
Matteo Scandolo813402b2019-10-23 19:24:52 -07001263 o.storePortNumber(uint32(msg.Flow.PortNo))
Matteo Scandolo4a036262020-08-17 15:56:13 -07001264
1265 for _, s := range o.Services {
Matteo Scandoloadc72a82020-09-08 18:46:08 -07001266 s.HandleAuth()
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001267 }
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001268 } else if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeIPv4) &&
1269 msg.Flow.Classifier.SrcPort == uint32(68) &&
Matteo Scandolobd875b32020-09-18 17:46:31 -07001270 msg.Flow.Classifier.DstPort == uint32(67) {
Matteo Scandolo99f18462019-10-28 14:14:28 -07001271
Matteo Scandolo4a036262020-08-17 15:56:13 -07001272 for _, s := range o.Services {
Matteo Scandolobd875b32020-09-18 17:46:31 -07001273 s.HandleDhcp(uint8(msg.Flow.Classifier.OPbits), int(msg.Flow.Classifier.OVid))
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001274 }
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001275 }
1276}
1277
Matteo Scandolof9d43412021-01-12 11:11:34 -08001278func (o *Onu) handleFlowRemove(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001279 onuLogger.WithFields(log.Fields{
1280 "IntfId": o.PonPortID,
1281 "OnuId": o.ID,
1282 "SerialNumber": o.Sn(),
1283 "FlowId": msg.Flow.FlowId,
1284 "FlowType": msg.Flow.FlowType,
1285 }).Debug("ONU receives FlowRemove")
1286
1287 for idx, flow := range o.FlowIds {
1288 // If the gemport is found, delete it from local cache.
1289 if flow == msg.Flow.FlowId {
1290 o.FlowIds = append(o.FlowIds[:idx], o.FlowIds[idx+1:]...)
1291 break
1292 }
1293 }
1294
1295 if len(o.FlowIds) == 0 {
1296 onuLogger.WithFields(log.Fields{
1297 "IntfId": o.PonPortID,
1298 "OnuId": o.ID,
1299 "SerialNumber": o.Sn(),
1300 }).Info("Resetting GemPort")
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001301
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301302 // check if ONU delete is performed and
1303 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolocedde462021-03-09 17:37:16 -08001304 if o.InternalState.Current() == OnuStateDisabled {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301305 close(o.Channel)
1306 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001307 }
1308}
1309
Matteo Scandolocedde462021-03-09 17:37:16 -08001310func (o *Onu) Reboot(timeout time.Duration) error {
1311 onuLogger.WithFields(log.Fields{
1312 "IntfId": o.PonPortID,
1313 "OnuId": o.ID,
1314 "SerialNumber": o.Sn(),
1315 }).Debug("shutting-down-onu")
1316 if err := o.HandleShutdownONU(); err != nil {
1317 return err
1318 }
1319 time.Sleep(timeout)
1320 onuLogger.WithFields(log.Fields{
1321 "IntfId": o.PonPortID,
1322 "OnuId": o.ID,
1323 "SerialNumber": o.Sn(),
1324 }).Debug("power-on-onu")
1325 if err := o.HandlePowerOnONU(); err != nil {
1326 return err
1327 }
1328 return nil
1329}
1330
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001331// BBR methods
1332
1333func sendOmciMsg(pktBytes []byte, intfId uint32, onuId uint32, sn *openolt.SerialNumber, msgType string, client openolt.OpenoltClient) {
1334 omciMsg := openolt.OmciMsg{
1335 IntfId: intfId,
1336 OnuId: onuId,
1337 Pkt: pktBytes,
1338 }
1339
1340 if _, err := client.OmciMsgOut(context.Background(), &omciMsg); err != nil {
1341 log.WithFields(log.Fields{
1342 "IntfId": intfId,
1343 "OnuId": onuId,
1344 "SerialNumber": common.OnuSnToString(sn),
1345 "Pkt": omciMsg.Pkt,
1346 }).Fatalf("Failed to send MIB Reset")
1347 }
1348 log.WithFields(log.Fields{
1349 "IntfId": intfId,
1350 "OnuId": onuId,
1351 "SerialNumber": common.OnuSnToString(sn),
1352 "Pkt": omciMsg.Pkt,
1353 }).Tracef("Sent OMCI message %s", msgType)
1354}
1355
1356func (onu *Onu) getNextTid(highPriority ...bool) uint16 {
1357 var next uint16
1358 if len(highPriority) > 0 && highPriority[0] {
1359 next = onu.hpTid
1360 onu.hpTid += 1
1361 if onu.hpTid < 0x8000 {
1362 onu.hpTid = 0x8000
1363 }
1364 } else {
1365 next = onu.tid
1366 onu.tid += 1
1367 if onu.tid >= 0x8000 {
1368 onu.tid = 1
1369 }
1370 }
1371 return next
1372}
1373
1374// TODO move this method in responders/omcisim
1375func (o *Onu) StartOmci(client openolt.OpenoltClient) {
1376 mibReset, _ := omcilib.CreateMibResetRequest(o.getNextTid(false))
1377 sendOmciMsg(mibReset, o.PonPortID, o.ID, o.SerialNumber, "mibReset", client)
1378}
1379
Matteo Scandolof9d43412021-01-12 11:11:34 -08001380// handleOmciResponse is used in BBR to generate the OMCI packets the openolt-adapter would send to the device
1381func (o *Onu) handleOmciResponse(msg bbsim.OmciIndicationMessage, client openolt.OpenoltClient) {
1382
1383 // we need to encode the packet in HEX
1384 pkt := make([]byte, len(msg.OmciInd.Pkt)*2)
1385 hex.Encode(pkt, msg.OmciInd.Pkt)
1386 packet, omciMsg, err := omcilib.ParseOpenOltOmciPacket(pkt)
1387 if err != nil {
1388 log.WithFields(log.Fields{
1389 "IntfId": o.PonPortID,
1390 "SerialNumber": o.Sn(),
1391 "omciPacket": msg.OmciInd.Pkt,
1392 }).Error("BBR Cannot parse OMCI packet")
1393 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001394
1395 log.WithFields(log.Fields{
1396 "IntfId": msg.OmciInd.IntfId,
1397 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001398 "OnuSn": o.Sn(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001399 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001400 "msgType": omciMsg.MessageType,
Anand S Katti09541352020-01-29 15:54:01 +05301401 }).Trace("ONU Receives OMCI Msg")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001402 switch omciMsg.MessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001403 default:
Matteo Scandolo813402b2019-10-23 19:24:52 -07001404 log.WithFields(log.Fields{
1405 "IntfId": msg.OmciInd.IntfId,
1406 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001407 "OnuSn": o.Sn(),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001408 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001409 "msgType": omciMsg.MessageType,
Matteo Scandolo813402b2019-10-23 19:24:52 -07001410 }).Fatalf("unexpected frame: %v", packet)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001411 case omci.MibResetResponseType:
1412 mibUpload, _ := omcilib.CreateMibUploadRequest(o.getNextTid(false))
1413 sendOmciMsg(mibUpload, o.PonPortID, o.ID, o.SerialNumber, "mibUpload", client)
1414 case omci.MibUploadResponseType:
1415 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1416 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
1417 case omci.MibUploadNextResponseType:
1418 o.seqNumber++
1419
1420 if o.seqNumber > 290 {
1421 // NOTE we are done with the MIB Upload (290 is the number of messages the omci-sim library will respond to)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001422 // start sending the flows, we don't care about the OMCI setup in BBR, just that a lot of messages can go through
Matteo Scandolocedde462021-03-09 17:37:16 -08001423 if err := o.InternalState.Event(BbrOnuTxSendEapolFlow); err != nil {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001424 onuLogger.WithFields(log.Fields{
1425 "OnuId": o.ID,
1426 "IntfId": o.PonPortID,
1427 "OnuSn": o.Sn(),
1428 }).Errorf("Error while transitioning ONU State %v", err)
1429 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001430 } else {
1431 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1432 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001433 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001434 }
1435}
1436
1437func (o *Onu) sendEapolFlow(client openolt.OpenoltClient) {
1438
1439 classifierProto := openolt.Classifier{
1440 EthType: uint32(layers.EthernetTypeEAPOL),
1441 OVid: 4091,
1442 }
1443
1444 actionProto := openolt.Action{}
1445
1446 downstreamFlow := openolt.Flow{
1447 AccessIntfId: int32(o.PonPortID),
1448 OnuId: int32(o.ID),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001449 UniId: int32(0), // NOTE do not hardcode this, we need to support multiple UNIs
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001450 FlowId: uint64(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001451 FlowType: "downstream",
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001452 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001453 Classifier: &classifierProto,
1454 Action: &actionProto,
1455 Priority: int32(100),
1456 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001457 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1458 // AllocId and GemPorts need to be unique per PON
1459 // for now use the ONU-ID, will need to change once we support multiple UNIs
1460 AllocId: int32(o.ID),
1461 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001462 }
1463
1464 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1465 log.WithFields(log.Fields{
1466 "IntfId": o.PonPortID,
1467 "OnuId": o.ID,
1468 "FlowId": downstreamFlow.FlowId,
1469 "PortNo": downstreamFlow.PortNo,
1470 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001471 "Err": err,
Matteo Scandolob0e3e622020-04-23 17:00:29 -07001472 }).Fatalf("Failed to add EAPOL Flow")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001473 }
1474 log.WithFields(log.Fields{
1475 "IntfId": o.PonPortID,
1476 "OnuId": o.ID,
1477 "FlowId": downstreamFlow.FlowId,
1478 "PortNo": downstreamFlow.PortNo,
1479 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1480 }).Info("Sent EAPOL Flow")
1481}
1482
1483func (o *Onu) sendDhcpFlow(client openolt.OpenoltClient) {
Matteo Scandolo4a036262020-08-17 15:56:13 -07001484
1485 // BBR only works with a single service (ATT HSIA)
1486 hsia := o.Services[0].(*Service)
1487
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001488 classifierProto := openolt.Classifier{
1489 EthType: uint32(layers.EthernetTypeIPv4),
1490 SrcPort: uint32(68),
1491 DstPort: uint32(67),
Matteo Scandolo4a036262020-08-17 15:56:13 -07001492 OVid: uint32(hsia.CTag),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001493 }
1494
1495 actionProto := openolt.Action{}
1496
1497 downstreamFlow := openolt.Flow{
1498 AccessIntfId: int32(o.PonPortID),
1499 OnuId: int32(o.ID),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001500 UniId: int32(0), // FIXME do not hardcode this
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001501 FlowId: uint64(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001502 FlowType: "downstream",
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001503 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001504 Classifier: &classifierProto,
1505 Action: &actionProto,
1506 Priority: int32(100),
1507 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001508 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1509 // AllocId and GemPorts need to be unique per PON
1510 // for now use the ONU-ID, will need to change once we support multiple UNIs
1511 AllocId: int32(o.ID),
1512 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001513 }
1514
1515 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1516 log.WithFields(log.Fields{
1517 "IntfId": o.PonPortID,
1518 "OnuId": o.ID,
1519 "FlowId": downstreamFlow.FlowId,
1520 "PortNo": downstreamFlow.PortNo,
1521 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001522 "Err": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001523 }).Fatalf("Failed to send DHCP Flow")
1524 }
1525 log.WithFields(log.Fields{
1526 "IntfId": o.PonPortID,
1527 "OnuId": o.ID,
1528 "FlowId": downstreamFlow.FlowId,
1529 "PortNo": downstreamFlow.PortNo,
1530 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1531 }).Info("Sent DHCP Flow")
1532}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301533
1534// DeleteFlow method search and delete flowKey from the onu flows slice
1535func (onu *Onu) DeleteFlow(key FlowKey) {
1536 for pos, flowKey := range onu.Flows {
1537 if flowKey == key {
1538 // delete the flowKey by shifting all flowKeys by one
1539 onu.Flows = append(onu.Flows[:pos], onu.Flows[pos+1:]...)
1540 t := make([]FlowKey, len(onu.Flows))
1541 copy(t, onu.Flows)
1542 onu.Flows = t
1543 break
1544 }
1545 }
1546}
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301547
1548func (onu *Onu) ReDiscoverOnu() {
1549 // Wait for few seconds to be sure of the cleanup
1550 time.Sleep(5 * time.Second)
1551
1552 onuLogger.WithFields(log.Fields{
1553 "IntfId": onu.PonPortID,
1554 "OnuId": onu.ID,
1555 "OnuSn": onu.Sn(),
1556 }).Debug("Send ONU Re-Discovery")
1557
1558 // ONU Re-Discovery
Matteo Scandolocedde462021-03-09 17:37:16 -08001559 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301560 log.WithFields(log.Fields{
1561 "IntfId": onu.PonPortID,
1562 "OnuSn": onu.Sn(),
1563 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001564 }).Infof("Failed to transition ONU to %s state: %s", OnuStateInitialized, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301565 }
1566
Matteo Scandolocedde462021-03-09 17:37:16 -08001567 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301568 log.WithFields(log.Fields{
1569 "IntfId": onu.PonPortID,
1570 "OnuSn": onu.Sn(),
1571 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001572 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDiscovered, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301573 }
1574}
Matteo Scandolo4a036262020-08-17 15:56:13 -07001575
1576func (onu *Onu) addGemPortToService(gemport uint32, ethType uint32, oVlan uint32, iVlan uint32) {
1577 for _, s := range onu.Services {
1578 if service, ok := s.(*Service); ok {
1579 // EAPOL is a strange case, as packets are untagged
1580 // but we assume we will have a single service requiring EAPOL
1581 if ethType == uint32(layers.EthernetTypeEAPOL) && service.NeedsEapol {
1582 service.GemPort = gemport
1583 }
1584
1585 // For DHCP services we single tag the outgoing packets,
1586 // thus the flow only contains the CTag and we can use that to match the service
1587 if ethType == uint32(layers.EthernetTypeIPv4) && service.NeedsDhcp && service.CTag == int(oVlan) {
1588 service.GemPort = gemport
1589 }
1590
1591 // for dataplane services match both C and S tags
1592 if service.CTag == int(iVlan) && service.STag == int(oVlan) {
1593 service.GemPort = gemport
1594 }
1595 }
1596 }
1597}
1598
1599func (onu *Onu) findServiceByMacAddress(macAddress net.HardwareAddr) (*Service, error) {
1600 for _, s := range onu.Services {
1601 service := s.(*Service)
1602 if service.HwAddress.String() == macAddress.String() {
1603 return service, nil
1604 }
1605 }
1606 return nil, fmt.Errorf("cannot-find-service-with-mac-address-%s", macAddress.String())
1607}
Himani Chawla13b1ee02021-03-15 01:43:53 +05301608
1609func (o *Onu) SendOMCIAlarmNotificationMsg(raiseOMCIAlarm bool, alarmType string) {
1610 switch alarmType {
1611 case "ONU_ALARM_LOS":
1612 msg := bbsim.Message{
1613 Type: bbsim.UniStatusAlarm,
1614 Data: bbsim.UniStatusAlarmMessage{
1615 OnuSN: o.SerialNumber,
1616 OnuID: o.ID,
1617 EntityID: 257,
1618 RaiseOMCIAlarm: raiseOMCIAlarm,
1619 },
1620 }
1621 o.Channel <- msg
1622 }
1623
1624}
1625
1626func (o *Onu) IncrementAlarmSequenceNumber(key omcilib.OnuAlarmInfoMapKey) uint8 {
1627 o.onuAlarmsInfoLock.Lock()
1628 defer o.onuAlarmsInfoLock.Unlock()
1629 if alarmInfo, ok := o.onuAlarmsInfo[key]; ok {
1630 if alarmInfo.SequenceNo == 255 {
1631 alarmInfo.SequenceNo = 1
1632 } else {
1633 alarmInfo.SequenceNo++
1634 }
1635 o.onuAlarmsInfo[key] = alarmInfo
1636 return alarmInfo.SequenceNo
1637 } else {
1638 // This is the first time alarm notification message is being sent
1639 o.onuAlarmsInfo[key] = omcilib.OnuAlarmInfo{
1640 SequenceNo: 1,
1641 }
1642 return 1
1643 }
1644}