blob: 1e7169c681e1f65635df627af22e2fed259b3069 [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"
Himani Chawla4ff5fab2021-11-09 19:19:29 +053021 "encoding/binary"
Matteo Scandolo618a6582020-09-09 12:21:29 -070022 "encoding/hex"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070023 "fmt"
Elia Battistonfe017662022-01-05 11:43:16 +010024 "math/rand"
Mahir Gunyela1753ae2021-06-23 00:24:56 -070025 "sync"
26
Matteo Scandolo8a574812021-05-20 15:18:53 -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"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000030
Matteo Scandolof9d43412021-01-12 11:11:34 -080031 pb "github.com/opencord/bbsim/api/bbsim"
32 "github.com/opencord/bbsim/internal/bbsim/alarmsim"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000033
34 "net"
35 "strconv"
36 "time"
Himani Chawla13b1ee02021-03-15 01:43:53 +053037
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080038 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Andrea Campanella10426e22021-10-15 17:58:04 +020039 me "github.com/opencord/omci-lib-go/v2/generated"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010040
Himani Chawla4ff5fab2021-11-09 19:19:29 +053041 "github.com/boguslaw-wojcik/crc32a"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070042 "github.com/google/gopacket/layers"
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070043 "github.com/jpillora/backoff"
Matteo Scandolo4747d292019-08-05 11:50:18 -070044 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070045 "github.com/opencord/bbsim/internal/common"
46 omcilib "github.com/opencord/bbsim/internal/common/omci"
Andrea Campanella10426e22021-10-15 17:58:04 +020047 "github.com/opencord/omci-lib-go/v2"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000048 "github.com/opencord/voltha-protos/v5/go/openolt"
49 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070050 log "github.com/sirupsen/logrus"
51)
52
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070053var onuLogger = log.WithFields(log.Fields{
54 "module": "ONU",
55})
56
Matteo Scandolocedde462021-03-09 17:37:16 -080057const (
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000058 maxOmciMsgCounter = 10
59)
60
61const (
Matteo Scandolocedde462021-03-09 17:37:16 -080062 // ONU transitions
63 OnuTxInitialize = "initialize"
64 OnuTxDiscover = "discover"
65 OnuTxEnable = "enable"
66 OnuTxDisable = "disable"
67 OnuTxPonDisable = "pon_disable"
68 OnuTxStartImageDownload = "start_image_download"
69 OnuTxProgressImageDownload = "progress_image_download"
70 OnuTxCompleteImageDownload = "complete_image_download"
71 OnuTxFailImageDownload = "fail_image_download"
72 OnuTxActivateImage = "activate_image"
73 OnuTxCommitImage = "commit_image"
74
75 // ONU States
76 OnuStateCreated = "created"
77 OnuStateInitialized = "initialized"
78 OnuStateDiscovered = "discovered"
79 OnuStateEnabled = "enabled"
80 OnuStateDisabled = "disabled"
81 OnuStatePonDisabled = "pon_disabled"
82 OnuStateImageDownloadStarted = "image_download_started"
83 OnuStateImageDownloadInProgress = "image_download_in_progress"
84 OnuStateImageDownloadComplete = "image_download_completed"
85 OnuStateImageDownloadError = "image_download_error"
86 OnuStateImageActivated = "software_image_activated"
87 OnuStateImageCommitted = "software_image_committed"
88
89 // BBR ONU States and Transitions
90 BbrOnuTxSendEapolFlow = "send_eapol_flow"
91 BbrOnuStateEapolFlowSent = "eapol_flow_sent"
92 BbrOnuTxSendDhcpFlow = "send_dhcp_flow"
93 BbrOnuStateDhcpFlowSent = "dhcp_flow_sent"
94)
95
Andrea Campanellacc9b1662022-01-26 17:47:48 +010096type FlowKey struct {
yasin saplic07b9522022-01-27 11:23:54 +000097 ID uint64
Andrea Campanellacc9b1662022-01-26 17:47:48 +010098}
99
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700100type Onu struct {
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800101 ID uint32
102 PonPortID uint32
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700103 PonPort *PonPort
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800104 InternalState *fsm.FSM
Pragya Arya2225f202020-01-29 18:05:01 +0530105 DiscoveryRetryDelay time.Duration // this is the time between subsequent Discovery Indication
106 DiscoveryDelay time.Duration // this is the time to send the first Discovery Indication
Matteo Scandolo4a036262020-08-17 15:56:13 -0700107
Matteo Scandolo4a036262020-08-17 15:56:13 -0700108 Backoff *backoff.Backoff
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800109 // ONU State
Elia Battistonac63b112022-01-12 18:40:49 +0100110 UniPorts []UniPortIf
111 PotsPorts []PotsPortIf
Andrea Campanellacc9b1662022-01-26 17:47:48 +0100112 Flows []FlowKey
Elia Battistonac63b112022-01-12 18:40:49 +0100113 FlowIds []uint64 // keep track of the flows we currently have in the ONU
Matteo Scandolo99f18462019-10-28 14:14:28 -0700114
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700115 OperState *fsm.FSM
116 SerialNumber *openolt.SerialNumber
117
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700118 AdminLockState uint8 // 0 is enabled, 1 is disabled.
119
Matteo Scandolof9d43412021-01-12 11:11:34 -0800120 Channel chan bbsim.Message // this Channel is to track state changes OMCI messages, EAPOL and DHCP packets
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700121
122 // OMCI params
Matteo Scandolocedde462021-03-09 17:37:16 -0800123 MibDataSync uint8
Holger Hildebrandt96382572022-05-31 09:41:38 +0000124 ImageSoftwareExpectedSections uint32
125 ImageSoftwareReceivedSections uint32
Matteo Scandolocedde462021-03-09 17:37:16 -0800126 ActiveImageEntityId uint16
127 CommittedImageEntityId uint16
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700128 StandbyImageVersion string
129 ActiveImageVersion string
Matteo Scandolo76f6b892021-11-15 16:13:06 -0800130 InDownloadImageVersion string
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700131 CommittedImageVersion string
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000132 OmciResponseRate uint8
133 OmciMsgCounter uint8
Himani Chawla4ff5fab2021-11-09 19:19:29 +0530134 ImageSectionData []byte
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800135
136 // OMCI params (Used in BBR)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700137 tid uint16
138 hpTid uint16
139 seqNumber uint16
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700140 MibDb *omcilib.MibDb
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700141
Anand S Katti09541352020-01-29 15:54:01 +0530142 DoneChannel chan bool // this channel is used to signal once the onu is complete (when the struct is used by BBR)
143 TrafficSchedulers *tech_profile.TrafficSchedulers
Himani Chawla13b1ee02021-03-15 01:43:53 +0530144 onuAlarmsInfoLock sync.RWMutex
145 onuAlarmsInfo map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700146}
147
Matteo Scandolo99f18462019-10-28 14:14:28 -0700148func (o *Onu) Sn() string {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700149 return common.OnuSnToString(o.SerialNumber)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700150}
151
Matteo Scandolo8a574812021-05-20 15:18:53 -0700152func CreateONU(olt *OltDevice, pon *PonPort, id uint32, delay time.Duration, nextCtag map[string]int, nextStag map[string]int, isMock bool) *Onu {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700153
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700154 o := Onu{
Matteo Scandolocedde462021-03-09 17:37:16 -0800155 ID: id,
156 PonPortID: pon.ID,
157 PonPort: pon,
Matteo Scandolocedde462021-03-09 17:37:16 -0800158 tid: 0x1,
159 hpTid: 0x8000,
160 seqNumber: 0,
161 DoneChannel: make(chan bool, 1),
162 DiscoveryRetryDelay: 60 * time.Second, // this is used to send OnuDiscoveryIndications until an activate call is received
Andrea Campanellacc9b1662022-01-26 17:47:48 +0100163 Flows: []FlowKey{},
Matteo Scandolocedde462021-03-09 17:37:16 -0800164 DiscoveryDelay: delay,
165 MibDataSync: 0,
166 ImageSoftwareExpectedSections: 0, // populated during OMCI StartSoftwareDownloadRequest
167 ImageSoftwareReceivedSections: 0,
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700168 //TODO this needs reworking, it's always 0 or 1, possibly base all on the version
169 ActiveImageEntityId: 0, // when we start the SoftwareImage with ID 0 is active and committed
170 CommittedImageEntityId: 0,
171 StandbyImageVersion: "BBSM_IMG_00000",
172 ActiveImageVersion: "BBSM_IMG_00001",
173 CommittedImageVersion: "BBSM_IMG_00001",
174 OmciResponseRate: olt.OmciResponseRate,
175 OmciMsgCounter: 0,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700176 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800177 o.SerialNumber = NewSN(olt.ID, pon.ID, id)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700178 // NOTE this state machine is used to track the operational
179 // state as requested by VOLTHA
180 o.OperState = getOperStateFSM(func(e *fsm.Event) {
181 onuLogger.WithFields(log.Fields{
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700182 "OnuId": o.ID,
183 "IntfId": o.PonPortID,
184 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700185 }).Debugf("Changing ONU OperState from %s to %s", e.Src, e.Dst)
186 })
Himani Chawla13b1ee02021-03-15 01:43:53 +0530187 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo)
Himani Chawla908a1f52022-01-27 14:39:44 +0530188
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700189 // NOTE this state machine is used to activate the OMCI, EAPOL and DHCP clients
190 o.InternalState = fsm.NewFSM(
Matteo Scandolocedde462021-03-09 17:37:16 -0800191 OnuStateCreated,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700192 fsm.Events{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700193 // DEVICE Lifecycle
Matteo Scandolocedde462021-03-09 17:37:16 -0800194 {Name: OnuTxInitialize, Src: []string{OnuStateCreated, OnuStateDisabled, OnuStatePonDisabled}, Dst: OnuStateInitialized},
195 {Name: OnuTxDiscover, Src: []string{OnuStateInitialized}, Dst: OnuStateDiscovered},
196 {Name: OnuTxEnable, Src: []string{OnuStateDiscovered, OnuStatePonDisabled}, Dst: OnuStateEnabled},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100197 // 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 -0800198 {Name: OnuTxDisable, Src: []string{OnuStateEnabled, OnuStatePonDisabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStateDisabled},
Pragya Arya6a708d62020-01-01 17:17:20 +0530199 // ONU state when PON port is disabled but ONU is power ON(more states should be added in src?)
Matteo Scandolo9f4bf4f2021-06-22 09:41:02 +0200200 {Name: OnuTxPonDisable, Src: []string{OnuStateEnabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted, OnuStateImageDownloadComplete}, Dst: OnuStatePonDisabled},
Matteo Scandolocedde462021-03-09 17:37:16 -0800201 // Software Image Download related states
Matteo Scandolo9f4bf4f2021-06-22 09:41:02 +0200202 {Name: OnuTxStartImageDownload, Src: []string{OnuStateEnabled, OnuStateImageDownloadComplete, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStateImageDownloadStarted},
Matteo Scandolocedde462021-03-09 17:37:16 -0800203 {Name: OnuTxProgressImageDownload, Src: []string{OnuStateImageDownloadStarted}, Dst: OnuStateImageDownloadInProgress},
204 {Name: OnuTxCompleteImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadComplete},
205 {Name: OnuTxFailImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadError},
206 {Name: OnuTxActivateImage, Src: []string{OnuStateImageDownloadComplete}, Dst: OnuStateImageActivated},
207 {Name: OnuTxCommitImage, Src: []string{OnuStateEnabled}, Dst: OnuStateImageCommitted}, // the image is committed after a ONU reboot
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700208 // BBR States
209 // TODO add start OMCI state
Matteo Scandolocedde462021-03-09 17:37:16 -0800210 {Name: BbrOnuTxSendEapolFlow, Src: []string{OnuStateInitialized}, Dst: BbrOnuStateEapolFlowSent},
211 {Name: BbrOnuTxSendDhcpFlow, Src: []string{BbrOnuStateEapolFlowSent}, Dst: BbrOnuStateDhcpFlowSent},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700212 },
213 fsm.Callbacks{
214 "enter_state": func(e *fsm.Event) {
215 o.logStateChange(e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700216 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700217 fmt.Sprintf("enter_%s", OnuStateInitialized): func(e *fsm.Event) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100218 // create new channel for ProcessOnuMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800219 o.Channel = make(chan bbsim.Message, 2048)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800220
Matteo Scandolocedde462021-03-09 17:37:16 -0800221 if err := o.OperState.Event(OnuTxEnable); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800222 onuLogger.WithFields(log.Fields{
223 "OnuId": o.ID,
224 "IntfId": o.PonPortID,
225 "OnuSn": o.Sn(),
226 }).Errorf("Cannot change ONU OperState to up: %s", err.Error())
227 }
228
Pragya Arya1cbefa42020-01-13 12:15:29 +0530229 if !isMock {
230 // start ProcessOnuMessages Go routine
Matteo Scandolo4a036262020-08-17 15:56:13 -0700231 go o.ProcessOnuMessages(olt.enableContext, olt.OpenoltStream, nil)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530232 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100233 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700234 fmt.Sprintf("enter_%s", OnuStateDiscovered): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800235 msg := bbsim.Message{
236 Type: bbsim.OnuDiscIndication,
237 Data: bbsim.OnuDiscIndicationMessage{
238 OperState: bbsim.UP,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100239 },
240 }
241 o.Channel <- msg
242 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700243 fmt.Sprintf("enter_%s", OnuStateEnabled): func(event *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800244
245 if used, sn := o.PonPort.isOnuIdAllocated(o.ID); used {
246 onuLogger.WithFields(log.Fields{
247 "IntfId": o.PonPortID,
248 "OnuId": o.ID,
249 "SerialNumber": o.Sn(),
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700250 }).Errorf("onu-id-duplicated-with-%s", common.OnuSnToString(sn))
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800251 return
252 } else {
253 o.PonPort.storeOnuId(o.ID, o.SerialNumber)
254 }
255
Matteo Scandolof9d43412021-01-12 11:11:34 -0800256 msg := bbsim.Message{
257 Type: bbsim.OnuIndication,
258 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700259 OnuSN: o.SerialNumber,
260 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800261 OperState: bbsim.UP,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700262 },
263 }
264 o.Channel <- msg
265 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700266 fmt.Sprintf("enter_%s", OnuStateDisabled): func(event *fsm.Event) {
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700267
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700268 o.cleanupOnuState()
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700269
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700270 // set the OperState to disabled
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800271 if err := o.OperState.Event("disable"); err != nil {
272 onuLogger.WithFields(log.Fields{
273 "OnuId": o.ID,
274 "IntfId": o.PonPortID,
275 "OnuSn": o.Sn(),
276 }).Errorf("Cannot change ONU OperState to down: %s", err.Error())
277 }
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700278 // send the OnuIndication DOWN event
Matteo Scandolof9d43412021-01-12 11:11:34 -0800279 msg := bbsim.Message{
280 Type: bbsim.OnuIndication,
281 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700282 OnuSN: o.SerialNumber,
283 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800284 OperState: bbsim.DOWN,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700285 },
286 }
287 o.Channel <- msg
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530288
Matteo Scandolo8a574812021-05-20 15:18:53 -0700289 // disable the UNI ports
290 for _, uni := range o.UniPorts {
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700291 if err := uni.Disable(); err != nil {
292 onuLogger.WithFields(log.Fields{
293 "onuId": o.ID,
294 "OnuSn": o.Sn(),
295 "UniId": uni.GetID(),
296 "err": err,
297 }).Error("failed-to-disable-uni-port")
298 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700299 }
300
Elia Battistonac63b112022-01-12 18:40:49 +0100301 // disable the POTS UNI ports
302 for _, pots := range o.PotsPorts {
Matteo Scandolofbb94ae2022-04-14 14:17:47 -0700303 if err := pots.Disable(); err != nil {
304 onuLogger.WithFields(log.Fields{
305 "onuId": o.ID,
306 "OnuSn": o.Sn(),
307 "UniId": pots.GetID(),
308 "err": err,
309 }).Error("failed-to-disable-pots-port")
310 }
Elia Battistonac63b112022-01-12 18:40:49 +0100311 }
312
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530313 // verify all the flows removes are handled and
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100314 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolo8a574812021-05-20 15:18:53 -0700315 // NOTE may need to wait for the UNIs to be down too before shutting down the channel
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530316 if len(o.FlowIds) == 0 {
317 close(o.Channel)
318 }
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700319 },
320 fmt.Sprintf("enter_%s", OnuStatePonDisabled): func(event *fsm.Event) {
321 o.cleanupOnuState()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700322 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700323 // BBR states
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700324 fmt.Sprintf("enter_%s", BbrOnuStateEapolFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800325 msg := bbsim.Message{
326 Type: bbsim.SendEapolFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700327 }
328 o.Channel <- msg
329 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700330 fmt.Sprintf("enter_%s", BbrOnuStateDhcpFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800331 msg := bbsim.Message{
332 Type: bbsim.SendDhcpFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700333 }
334 o.Channel <- msg
335 },
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700336 },
337 )
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700338 onuLogger.WithFields(log.Fields{
Elia Battistonac63b112022-01-12 18:40:49 +0100339 "OnuId": o.ID,
340 "IntfId": o.PonPortID,
341 "OnuSn": o.Sn(),
342 "NumUni": olt.NumUni,
343 "NumPots": olt.NumPots,
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700344 }).Debug("creating-uni-ports")
Elia Battistonac63b112022-01-12 18:40:49 +0100345
346 // create Ethernet UNIs
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700347 for i := 0; i < olt.NumUni; i++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700348 uni, err := NewUniPort(uint32(i), &o, nextCtag, nextStag)
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700349 if err != nil {
350 onuLogger.WithFields(log.Fields{
351 "OnuId": o.ID,
352 "IntfId": o.PonPortID,
353 "OnuSn": o.Sn(),
354 "Err": err,
355 }).Fatal("cannot-create-uni-port")
356 }
357 o.UniPorts = append(o.UniPorts, uni)
358 }
Elia Battistonac63b112022-01-12 18:40:49 +0100359 // create POTS UNIs, with progressive IDs
360 for i := olt.NumUni; i < (olt.NumUni + olt.NumPots); i++ {
361 pots, err := NewPotsPort(uint32(i), &o)
362 if err != nil {
363 onuLogger.WithFields(log.Fields{
364 "OnuId": o.ID,
365 "IntfId": o.PonPortID,
366 "OnuSn": o.Sn(),
367 "Err": err,
368 }).Fatal("cannot-create-pots-port")
369 }
370 o.PotsPorts = append(o.PotsPorts, pots)
371 }
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700372
Elia Battistonb7bea222022-02-18 16:25:00 +0100373 mibDb, err := omcilib.GenerateMibDatabase(len(o.UniPorts), len(o.PotsPorts), o.PonPort.Technology)
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700374 if err != nil {
375 onuLogger.WithFields(log.Fields{
376 "OnuId": o.ID,
377 "IntfId": o.PonPortID,
378 "OnuSn": o.Sn(),
379 }).Fatal("cannot-generate-mibdb-for-onu")
380 }
381 o.MibDb = mibDb
382
Matteo Scandolo27428702019-10-11 16:21:16 -0700383 return &o
Matteo Scandolo4747d292019-08-05 11:50:18 -0700384}
385
William Kurkian0418bc82019-11-06 12:16:24 -0500386func (o *Onu) logStateChange(src string, dst string) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700387 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700388 "OnuId": o.ID,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700389 "IntfId": o.PonPortID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700390 "OnuSn": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700391 }).Debugf("Changing ONU InternalState from %s to %s", src, dst)
392}
393
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700394// cleanupOnuState this method is to clean the local state when the ONU is disabled
395func (o *Onu) cleanupOnuState() {
396 // clean the ONU state
Andrea Campanellacc9b1662022-01-26 17:47:48 +0100397 o.Flows = []FlowKey{}
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700398 o.PonPort.removeOnuId(o.ID)
Girish Gowdra574834a2022-02-04 15:15:15 -0800399 o.PonPort.removeAllocIdsForOnuSn(o.SerialNumber)
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700400 o.PonPort.removeGemPortBySn(o.SerialNumber)
401
402 o.onuAlarmsInfoLock.Lock()
403 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo) //Basically reset everything on onu disable
404 o.onuAlarmsInfoLock.Unlock()
405}
406
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100407// ProcessOnuMessages starts indication channel for each ONU
David Bainbridge103cf022019-12-16 20:11:35 +0000408func (o *Onu) ProcessOnuMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, client openolt.OpenoltClient) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700409 onuLogger.WithFields(log.Fields{
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100410 "onuID": o.ID,
411 "onuSN": o.Sn(),
412 "ponPort": o.PonPortID,
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700413 "stream": stream,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100414 }).Debug("Starting ONU Indication Channel")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700415
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700416 defer onuLogger.WithFields(log.Fields{
417 "onuID": o.ID,
418 "onuSN": o.Sn(),
419 "stream": stream,
420 }).Debug("Stopped handling ONU Indication Channel")
421
David Bainbridge103cf022019-12-16 20:11:35 +0000422loop:
423 for {
424 select {
425 case <-ctx.Done():
426 onuLogger.WithFields(log.Fields{
427 "onuID": o.ID,
428 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700429 }).Debug("ONU message handling canceled via context")
430 break loop
431 case <-stream.Context().Done():
432 onuLogger.WithFields(log.Fields{
433 "onuID": o.ID,
434 "onuSN": o.Sn(),
435 }).Debug("ONU message handling canceled via stream context")
David Bainbridge103cf022019-12-16 20:11:35 +0000436 break loop
437 case message, ok := <-o.Channel:
438 if !ok || ctx.Err() != nil {
439 onuLogger.WithFields(log.Fields{
440 "onuID": o.ID,
441 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700442 }).Debug("ONU message handling canceled via channel close")
David Bainbridge103cf022019-12-16 20:11:35 +0000443 break loop
Matteo Scandolo075b1892019-10-07 12:11:07 -0700444 }
David Bainbridge103cf022019-12-16 20:11:35 +0000445 onuLogger.WithFields(log.Fields{
446 "onuID": o.ID,
447 "onuSN": o.Sn(),
448 "messageType": message.Type,
449 }).Tracef("Received message on ONU Channel")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700450
David Bainbridge103cf022019-12-16 20:11:35 +0000451 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800452 case bbsim.OnuDiscIndication:
453 msg, _ := message.Data.(bbsim.OnuDiscIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000454 // 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 +0530455 time.Sleep(o.DiscoveryDelay)
David Bainbridge103cf022019-12-16 20:11:35 +0000456 o.sendOnuDiscIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800457 case bbsim.OnuIndication:
458 msg, _ := message.Data.(bbsim.OnuIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000459 o.sendOnuIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800460 case bbsim.OMCI:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800461 // these are OMCI messages received by the ONU
Matteo Scandolof9d43412021-01-12 11:11:34 -0800462 msg, _ := message.Data.(bbsim.OmciMessage)
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200463 _ = o.handleOmciRequest(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800464 case bbsim.UniStatusAlarm:
465 msg, _ := message.Data.(bbsim.UniStatusAlarmMessage)
Himani Chawla13b1ee02021-03-15 01:43:53 +0530466 onuAlarmMapKey := omcilib.OnuAlarmInfoMapKey{
467 MeInstance: msg.EntityID,
468 MeClassID: me.PhysicalPathTerminationPointEthernetUniClassID,
469 }
470 seqNo := o.IncrementAlarmSequenceNumber(onuAlarmMapKey)
471 o.onuAlarmsInfoLock.Lock()
472 var alarmInfo = o.onuAlarmsInfo[onuAlarmMapKey]
473 pkt, alarmBitMap := omcilib.CreateUniStatusAlarm(msg.RaiseOMCIAlarm, msg.EntityID, seqNo)
474 if pkt != nil { //pkt will be nil if we are unable to create the alarm
475 if err := o.sendOmciIndication(pkt, 0, stream); err != nil {
476 onuLogger.WithFields(log.Fields{
477 "IntfId": o.PonPortID,
478 "SerialNumber": o.Sn(),
479 "omciPacket": pkt,
480 "adminState": msg.AdminState,
481 "entityID": msg.EntityID,
482 }).Errorf("failed-to-send-UNI-Link-Alarm: %v", err)
483 alarmInfo.SequenceNo--
484 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800485 onuLogger.WithFields(log.Fields{
486 "IntfId": o.PonPortID,
487 "SerialNumber": o.Sn(),
488 "omciPacket": pkt,
489 "adminState": msg.AdminState,
490 "entityID": msg.EntityID,
Himani Chawla13b1ee02021-03-15 01:43:53 +0530491 }).Trace("UNI-Link-alarm-sent")
492 if alarmBitMap == [28]byte{0} {
493 delete(o.onuAlarmsInfo, onuAlarmMapKey)
494 } else {
495 alarmInfo.AlarmBitMap = alarmBitMap
496 o.onuAlarmsInfo[onuAlarmMapKey] = alarmInfo
497 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800498 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530499 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800500 case bbsim.FlowAdd:
501 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700502 o.handleFlowAdd(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800503 case bbsim.FlowRemoved:
504 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700505 o.handleFlowRemove(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800506 case bbsim.OnuPacketOut:
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700507
Matteo Scandolof9d43412021-01-12 11:11:34 -0800508 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000509
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700510 onuLogger.WithFields(log.Fields{
David Bainbridge103cf022019-12-16 20:11:35 +0000511 "IntfId": msg.IntfId,
512 "OnuId": msg.OnuId,
513 "pktType": msg.Type,
514 }).Trace("Received OnuPacketOut Message")
515
Matteo Scandolo8a574812021-05-20 15:18:53 -0700516 uni, err := o.findUniByPortNo(msg.PortNo)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700517
Matteo Scandolo8a574812021-05-20 15:18:53 -0700518 if err != nil {
519 onuLogger.WithFields(log.Fields{
520 "IntfId": msg.IntfId,
521 "OnuId": msg.OnuId,
522 "pktType": msg.Type,
523 "portNo": msg.PortNo,
524 "MacAddress": msg.MacAddress,
525 "Pkt": hex.EncodeToString(msg.Packet.Data()),
526 "OnuSn": o.Sn(),
527 }).Error("Cannot find Uni associated with packet")
528 return
David Bainbridge103cf022019-12-16 20:11:35 +0000529 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700530 uni.PacketCh <- msg
531 // BBR specific messages
Matteo Scandolof9d43412021-01-12 11:11:34 -0800532 case bbsim.OnuPacketIn:
David Bainbridge103cf022019-12-16 20:11:35 +0000533 // NOTE we only receive BBR packets here.
534 // Eapol.HandleNextPacket can handle both BBSim and BBr cases so the call is the same
535 // 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 -0800536 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000537
Matteo Scandolo8a574812021-05-20 15:18:53 -0700538 onuLogger.WithFields(log.Fields{
539 "IntfId": msg.IntfId,
540 "OnuId": msg.OnuId,
541 "PortNo": msg.PortNo,
542 "GemPortId": msg.GemPortId,
543 "pktType": msg.Type,
David Bainbridge103cf022019-12-16 20:11:35 +0000544 }).Trace("Received OnuPacketIn Message")
545
Matteo Scandolo8a574812021-05-20 15:18:53 -0700546 uni, err := o.findUniByPortNo(msg.PortNo)
547 if err != nil {
548 onuLogger.WithFields(log.Fields{
549 "IntfId": msg.IntfId,
550 "OnuId": msg.OnuId,
551 "PortNo": msg.PortNo,
552 "GemPortId": msg.GemPortId,
553 "pktType": msg.Type,
554 }).Error(err.Error())
555 }
556
557 // BBR has one service and one UNI
558 serviceId := uint32(0)
559 oltId := 0
David Bainbridge103cf022019-12-16 20:11:35 +0000560 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700561 eapol.HandleNextPacket(msg.OnuId, msg.IntfId, msg.GemPortId, o.Sn(), msg.PortNo, uni.ID, serviceId, oltId, o.InternalState, msg.Packet, stream, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000562 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700563 _ = dhcp.HandleNextBbrPacket(o.ID, o.PonPortID, o.Sn(), o.DoneChannel, msg.Packet, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000564 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800565 case bbsim.OmciIndication:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800566 // these are OMCI messages received by BBR (VOLTHA emulator)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800567 msg, _ := message.Data.(bbsim.OmciIndicationMessage)
568 o.handleOmciResponse(msg, client)
569 case bbsim.SendEapolFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000570 o.sendEapolFlow(client)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800571 case bbsim.SendDhcpFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000572 o.sendDhcpFlow(client)
573 default:
574 onuLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700575 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700576 }
577 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700578}
579
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800580func NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700581 sn := new(openolt.SerialNumber)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582 sn.VendorId = []byte("BBSM")
583 sn.VendorSpecific = []byte{0, byte(oltid % 256), byte(intfid), byte(onuid)}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700584 return sn
585}
586
Matteo Scandolof9d43412021-01-12 11:11:34 -0800587func (o *Onu) sendOnuDiscIndication(msg bbsim.OnuDiscIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700588 discoverData := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800589 IntfId: o.PonPortID,
590 SerialNumber: o.SerialNumber,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700591 }}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700592
Matteo Scandolo4747d292019-08-05 11:50:18 -0700593 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700594 log.Errorf("Failed to send Indication_OnuDiscInd: %v", err)
Matteo Scandolo99f18462019-10-28 14:14:28 -0700595 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700596 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700597
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700598 onuLogger.WithFields(log.Fields{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800599 "IntfId": o.PonPortID,
600 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700601 "OnuId": o.ID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700602 }).Debug("Sent Indication_OnuDiscInd")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800603 publishEvent("ONU-discovery-indication-sent", int32(o.PonPortID), int32(o.ID), o.Sn())
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800604
605 // after DiscoveryRetryDelay check if the state is the same and in case send a new OnuDiscIndication
606 go func(delay time.Duration) {
Matteo Scandolo569e7172019-12-20 11:51:51 -0800607 time.Sleep(delay)
Matteo Scandolocedde462021-03-09 17:37:16 -0800608 if o.InternalState.Current() == OnuStateDiscovered {
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800609 o.sendOnuDiscIndication(msg, stream)
610 }
611 }(o.DiscoveryRetryDelay)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612}
613
Matteo Scandolof9d43412021-01-12 11:11:34 -0800614func (o *Onu) sendOnuIndication(msg bbsim.OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800615 // NOTE the ONU ID is set by VOLTHA in the ActivateOnu call (via openolt.proto)
616 // and stored in the Onu struct via onu.SetID
Matteo Scandolo4747d292019-08-05 11:50:18 -0700617
618 indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700619 IntfId: o.PonPortID,
620 OnuId: o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700621 OperState: msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700622 AdminState: o.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700623 SerialNumber: o.SerialNumber,
624 }}
625 if err := stream.Send(&openolt.Indication{Data: indData}); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800626 // NOTE do we need to transition to a broken state?
Matteo Scandolo11006992019-08-28 11:29:46 -0700627 log.Errorf("Failed to send Indication_OnuInd: %v", err)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700628 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700629 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700630 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800631 "IntfId": o.PonPortID,
632 "OnuId": o.ID,
633 "VolthaOnuId": msg.OnuID,
634 "OperState": msg.OperState.String(),
635 "AdminState": msg.OperState.String(),
636 "OnuSn": o.Sn(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700637 }).Debug("Sent Indication_OnuInd")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700638
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700639}
640
Matteo Scandolof9d43412021-01-12 11:11:34 -0800641func (o *Onu) HandleShutdownONU() error {
642
643 dyingGasp := pb.ONUAlarmRequest{
644 AlarmType: "DYING_GASP",
645 SerialNumber: o.Sn(),
646 Status: "on",
647 }
648
649 if err := alarmsim.SimulateOnuAlarm(&dyingGasp, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
650 onuLogger.WithFields(log.Fields{
651 "OnuId": o.ID,
652 "IntfId": o.PonPortID,
653 "OnuSn": o.Sn(),
654 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
655 return err
656 }
657
658 losReq := pb.ONUAlarmRequest{
659 AlarmType: "ONU_ALARM_LOS",
660 SerialNumber: o.Sn(),
661 Status: "on",
662 }
663
664 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
665 onuLogger.WithFields(log.Fields{
666 "OnuId": o.ID,
667 "IntfId": o.PonPortID,
668 "OnuSn": o.Sn(),
669 }).Errorf("Cannot send LOS: %s", err.Error())
670
671 return err
672 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530673 o.SendOMCIAlarmNotificationMsg(true, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800674 // TODO if it's the last ONU on the PON, then send a PON LOS
675
Matteo Scandolocedde462021-03-09 17:37:16 -0800676 if err := o.InternalState.Event(OnuTxDisable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800677 onuLogger.WithFields(log.Fields{
678 "OnuId": o.ID,
679 "IntfId": o.PonPortID,
680 "OnuSn": o.Sn(),
681 }).Errorf("Cannot shutdown ONU: %s", err.Error())
682 return err
683 }
684
685 return nil
686}
687
688func (o *Onu) HandlePowerOnONU() error {
689 intitalState := o.InternalState.Current()
690
691 // initialize the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800692 if intitalState == OnuStateCreated || intitalState == OnuStateDisabled {
693 if err := o.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800694 onuLogger.WithFields(log.Fields{
695 "OnuId": o.ID,
696 "IntfId": o.PonPortID,
697 "OnuSn": o.Sn(),
698 }).Errorf("Cannot poweron ONU: %s", err.Error())
699 return err
700 }
701 }
702
703 // turn off the LOS Alarm
704 losReq := pb.ONUAlarmRequest{
705 AlarmType: "ONU_ALARM_LOS",
706 SerialNumber: o.Sn(),
707 Status: "off",
708 }
709
710 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
711 onuLogger.WithFields(log.Fields{
712 "OnuId": o.ID,
713 "IntfId": o.PonPortID,
714 "OnuSn": o.Sn(),
715 }).Errorf("Cannot send LOS: %s", err.Error())
716 return err
717 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530718 o.SendOMCIAlarmNotificationMsg(false, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800719
720 // Send a ONU Discovery indication
Matteo Scandolocedde462021-03-09 17:37:16 -0800721 if err := o.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800722 onuLogger.WithFields(log.Fields{
723 "OnuId": o.ID,
724 "IntfId": o.PonPortID,
725 "OnuSn": o.Sn(),
726 }).Errorf("Cannot poweron ONU: %s", err.Error())
727 return err
728 }
729
730 // move o directly to enable state only when its a powercycle case
731 // in case of first time o poweron o will be moved to enable on
732 // receiving ActivateOnu request from openolt adapter
Matteo Scandolocedde462021-03-09 17:37:16 -0800733 if intitalState == OnuStateDisabled {
734 if err := o.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800735 onuLogger.WithFields(log.Fields{
736 "OnuId": o.ID,
737 "IntfId": o.PonPortID,
738 "OnuSn": o.Sn(),
739 }).Errorf("Cannot enable ONU: %s", err.Error())
740 return err
741 }
742 }
743
744 return nil
745}
746
747func (o *Onu) SetAlarm(alarmType string, status string) error {
748 alarmReq := pb.ONUAlarmRequest{
749 AlarmType: alarmType,
750 SerialNumber: o.Sn(),
751 Status: status,
752 }
753
754 err := alarmsim.SimulateOnuAlarm(&alarmReq, o.ID, o.PonPortID, o.PonPort.Olt.channel)
755 if err != nil {
756 return err
757 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530758 raiseAlarm := false
759 if alarmReq.Status == "on" {
760 raiseAlarm = true
761 }
762 o.SendOMCIAlarmNotificationMsg(raiseAlarm, alarmReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800763 return nil
764}
765
766func (o *Onu) publishOmciEvent(msg bbsim.OmciMessage) {
Pragya Arya324337e2020-02-20 14:35:08 +0530767 if olt.PublishEvents {
Matteo Scandolob5913142021-03-19 16:10:18 -0700768 _, omciMsg, err := omcilib.ParseOpenOltOmciPacket(msg.OmciPkt.Data())
Pragya Arya324337e2020-02-20 14:35:08 +0530769 if err != nil {
770 log.Errorf("error in getting msgType %v", err)
771 return
772 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800773 if omciMsg.MessageType == omci.MibUploadRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530774 o.seqNumber = 0
775 publishEvent("MIB-upload-received", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
Matteo Scandolof9d43412021-01-12 11:11:34 -0800776 } else if omciMsg.MessageType == omci.MibUploadNextRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530777 o.seqNumber++
778 if o.seqNumber > 290 {
779 publishEvent("MIB-upload-done", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
780 }
781 }
782 }
783}
784
Matteo Scandolof9d43412021-01-12 11:11:34 -0800785// handleOmciRequest is responsible to parse the OMCI packets received from the openolt adapter
786// and generate the appropriate response to it
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200787func (o *Onu) handleOmciRequest(msg bbsim.OmciMessage, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800788
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700789 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700790 "omciMsgType": msg.OmciMsg.MessageType,
791 "transCorrId": strconv.FormatInt(int64(msg.OmciMsg.TransactionID), 16),
792 "DeviceIdent": msg.OmciMsg.DeviceIdentifier,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700793 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -0700794 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -0800795 }).Trace("omci-message-decoded")
796
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000797 if o.OmciMsgCounter < maxOmciMsgCounter {
798 o.OmciMsgCounter++
799 } else {
800 o.OmciMsgCounter = 1
801 }
802 if o.OmciMsgCounter > o.OmciResponseRate {
803 onuLogger.WithFields(log.Fields{
804 "OmciMsgCounter": o.OmciMsgCounter,
805 "OmciResponseRate": o.OmciResponseRate,
806 "omciMsgType": msg.OmciMsg.MessageType,
Matteo Scandoloa96e2242021-09-28 10:13:17 -0700807 "txId": msg.OmciMsg.TransactionID,
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200808 }).Debug("skipping-omci-msg-response")
809 return fmt.Errorf("skipping-omci-msg-response-because-of-response-rate-%d", o.OmciResponseRate)
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000810 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800811 var responsePkt []byte
Girish Gowdrae2683102021-03-05 08:24:26 -0800812 var errResp error
Matteo Scandolob5913142021-03-19 16:10:18 -0700813 switch msg.OmciMsg.MessageType {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800814 case omci.MibResetRequestType:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800815 onuLogger.WithFields(log.Fields{
816 "IntfId": o.PonPortID,
817 "OnuId": o.ID,
818 "SerialNumber": o.Sn(),
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700819 }).Debug("received-mib-reset-request")
Matteo Scandolob5913142021-03-19 16:10:18 -0700820 if responsePkt, errResp = omcilib.CreateMibResetResponse(msg.OmciMsg.TransactionID); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800821 o.MibDataSync = 0
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700822
823 // if the MIB reset is successful then remove all the stored AllocIds and GemPorts
Girish Gowdra574834a2022-02-04 15:15:15 -0800824 o.PonPort.removeAllocIdsForOnuSn(o.SerialNumber)
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700825 o.PonPort.removeGemPortBySn(o.SerialNumber)
Girish Gowdrae2683102021-03-05 08:24:26 -0800826 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800827 case omci.MibUploadRequestType:
Holger Hildebrandt236e3742022-05-04 14:07:27 +0000828 responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg, o.MibDb)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800829 case omci.MibUploadNextRequestType:
Holger Hildebrandt236e3742022-05-04 14:07:27 +0000830 responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDb)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800831 case omci.GetRequestType:
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700832 onuDown := o.AdminLockState == 1
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700833 responsePkt, _ = omcilib.CreateGetResponse(msg.OmciPkt, msg.OmciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId,
834 o.CommittedImageEntityId, o.StandbyImageVersion, o.ActiveImageVersion, o.CommittedImageVersion, onuDown)
Himani Chawla908a1f52022-01-27 14:39:44 +0530835
Matteo Scandolof9d43412021-01-12 11:11:34 -0800836 case omci.SetRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800837 success := true
Matteo Scandolob5913142021-03-19 16:10:18 -0700838 msgObj, _ := omcilib.ParseSetRequest(msg.OmciPkt)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800839 switch msgObj.EntityClass {
840 case me.PhysicalPathTerminationPointEthernetUniClassID:
841 // if we're Setting a PPTP state
Matteo Scandolo8a574812021-05-20 15:18:53 -0700842 // we need to send the appropriate alarm (handled in the UNI struct)
843 uni, err := o.FindUniByEntityId(msgObj.EntityInstance)
844 if err != nil {
845 onuLogger.Error(err)
846 success = false
847 } else {
848 // 1 locks the UNI, 0 unlocks it
Elia Battiston9bfe1102022-02-03 10:38:03 +0100849 adminState := msgObj.Attributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState].(uint8)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700850 var err error
Himani Chawla13b1ee02021-03-15 01:43:53 +0530851 if adminState == 1 {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700852 err = uni.Disable()
Girish Gowdra996d81e2021-04-21 16:16:27 -0700853 } else {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700854 err = uni.Enable()
Himani Chawla13b1ee02021-03-15 01:43:53 +0530855 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700856 if err != nil {
857 onuLogger.WithFields(log.Fields{
858 "IntfId": o.PonPortID,
859 "OnuId": o.ID,
860 "UniMeId": uni.MeId,
861 "UniId": uni.ID,
862 "SerialNumber": o.Sn(),
863 "Err": err.Error(),
864 }).Warn("cannot-change-uni-status")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800865 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800866 }
Elia Battistonac63b112022-01-12 18:40:49 +0100867 case me.PhysicalPathTerminationPointPotsUniClassID:
868 // if we're Setting a PPTP state
869 // we need to send the appropriate alarm (handled in the POTS struct)
870 pots, err := o.FindPotsByEntityId(msgObj.EntityInstance)
871 if err != nil {
872 onuLogger.Error(err)
873 success = false
874 } else {
875 // 1 locks the UNI, 0 unlocks it
Elia Battiston9bfe1102022-02-03 10:38:03 +0100876 adminState := msgObj.Attributes[me.PhysicalPathTerminationPointPotsUni_AdministrativeState].(uint8)
Elia Battistonac63b112022-01-12 18:40:49 +0100877 var err error
878 if adminState == 1 {
879 err = pots.Disable()
880 } else {
881 err = pots.Enable()
882 }
883 if err != nil {
884 onuLogger.WithFields(log.Fields{
885 "IntfId": o.PonPortID,
886 "OnuId": o.ID,
887 "PotsMeId": pots.MeId,
888 "PotsId": pots.ID,
889 "SerialNumber": o.Sn(),
890 "Err": err.Error(),
891 }).Warn("cannot-change-pots-status")
892 }
893 }
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700894 case me.OnuGClassID:
Elia Battiston9bfe1102022-02-03 10:38:03 +0100895 o.AdminLockState = msgObj.Attributes[me.OnuG_AdministrativeState].(uint8)
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700896 onuLogger.WithFields(log.Fields{
897 "IntfId": o.PonPortID,
898 "OnuId": o.ID,
899 "SerialNumber": o.Sn(),
900 "AdminLockState": o.AdminLockState,
901 }).Debug("set-onu-admin-lock-state")
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800902 case me.TContClassID:
Elia Battiston9bfe1102022-02-03 10:38:03 +0100903 allocId := msgObj.Attributes[me.TCont_AllocId].(uint16)
Girish Gowdra574834a2022-02-04 15:15:15 -0800904 entityID := msgObj.Attributes["ManagedEntityId"].(uint16)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800905
906 // if the AllocId is 255 (0xFF) or 65535 (0xFFFF) it means we are removing it,
907 // otherwise we are adding it
908 if allocId == 255 || allocId == 65535 {
909 onuLogger.WithFields(log.Fields{
910 "IntfId": o.PonPortID,
911 "OnuId": o.ID,
912 "TContId": msgObj.EntityInstance,
913 "AllocId": allocId,
914 "SerialNumber": o.Sn(),
915 }).Trace("freeing-alloc-id-via-omci")
Girish Gowdra574834a2022-02-04 15:15:15 -0800916 o.PonPort.removeAllocId(o.PonPortID, o.ID, entityID)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800917 } else {
Girish Gowdra574834a2022-02-04 15:15:15 -0800918 if used, allocObj := o.PonPort.isAllocIdAllocated(o.PonPortID, o.ID, entityID); used {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800919 onuLogger.WithFields(log.Fields{
920 "IntfId": o.PonPortID,
921 "OnuId": o.ID,
922 "AllocId": allocId,
923 "SerialNumber": o.Sn(),
Girish Gowdra574834a2022-02-04 15:15:15 -0800924 }).Errorf("allocid-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(allocObj.OnuSn))
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800925 success = false
926 } else {
927 onuLogger.WithFields(log.Fields{
928 "IntfId": o.PonPortID,
929 "OnuId": o.ID,
930 "TContId": msgObj.EntityInstance,
931 "AllocId": allocId,
932 "SerialNumber": o.Sn(),
933 }).Trace("storing-alloc-id-via-omci")
Girish Gowdra574834a2022-02-04 15:15:15 -0800934 o.PonPort.storeAllocId(o.PonPortID, o.ID, entityID, allocId, o.SerialNumber)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800935 }
936 }
Himani Chawla908a1f52022-01-27 14:39:44 +0530937 case me.EthernetFrameExtendedPmClassID,
938 me.EthernetFrameExtendedPm64BitClassID:
939 onuLogger.WithFields(log.Fields{
940 "me-instance": msgObj.EntityInstance,
941 }).Debug("set-request-received")
942 // No need to reset counters as onu adapter will simply send the set control block request to actually reset
943 // the counters, and respond with 0's without sending the get request to device.
944 // Also, if we even reset the counters here in cache, then on get we need to restore the counters back which
945 // would be of no use as ultimately the counters need to be restored.
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800946 }
947
948 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -0700949 if responsePkt, errResp = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800950 o.MibDataSync++
951 }
952 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700953 responsePkt, _ = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.AttributeFailure)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800954 }
955 case omci.CreateRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800956 // check for GemPortNetworkCtp and make sure there are no duplicates on the same PON
957 var used bool
958 var sn *openolt.SerialNumber
Matteo Scandolob5913142021-03-19 16:10:18 -0700959 msgObj, err := omcilib.ParseCreateRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800960 if err == nil {
961 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
Matteo Scandolo973b0182021-04-08 11:24:42 -0700962 // GemPort 4069 is reserved for multicast and shared across ONUs
963 if msgObj.EntityInstance != 4069 {
964 if used, sn = o.PonPort.isGemPortAllocated(msgObj.EntityInstance); used {
965 onuLogger.WithFields(log.Fields{
966 "IntfId": o.PonPortID,
967 "OnuId": o.ID,
968 "GemPortId": msgObj.EntityInstance,
969 "SerialNumber": o.Sn(),
970 }).Errorf("gemport-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
971 } else {
972 onuLogger.WithFields(log.Fields{
973 "IntfId": o.PonPortID,
974 "OnuId": o.ID,
975 "GemPortId": msgObj.EntityInstance,
976 "SerialNumber": o.Sn(),
977 }).Trace("storing-gem-port-id-via-omci")
978 o.PonPort.storeGemPort(msgObj.EntityInstance, o.SerialNumber)
979 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800980 }
981 }
982 }
983
984 // if the gemPort is valid then increment the MDS and return a successful response
985 // otherwise fail the request
986 // for now the CreateRequeste for the gemPort is the only one that can fail, if we start supporting multiple
987 // validation this check will need to be rewritten
988 if !used {
Matteo Scandolob5913142021-03-19 16:10:18 -0700989 if responsePkt, errResp = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800990 o.MibDataSync++
991 }
992 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700993 responsePkt, _ = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError)
Girish Gowdrae2683102021-03-05 08:24:26 -0800994 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800995 case omci.DeleteRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700996 msgObj, err := omcilib.ParseDeleteRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800997 if err == nil {
998 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
999 onuLogger.WithFields(log.Fields{
1000 "IntfId": o.PonPortID,
1001 "OnuId": o.ID,
1002 "GemPortId": msgObj.EntityInstance,
1003 "SerialNumber": o.Sn(),
1004 }).Trace("freeing-gem-port-id-via-omci")
1005 o.PonPort.removeGemPort(msgObj.EntityInstance)
1006 }
1007 }
1008
Matteo Scandolob5913142021-03-19 16:10:18 -07001009 if responsePkt, errResp = omcilib.CreateDeleteResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -08001010 o.MibDataSync++
1011 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001012 case omci.RebootRequestType:
1013
Matteo Scandolob5913142021-03-19 16:10:18 -07001014 responsePkt, _ = omcilib.CreateRebootResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolof9d43412021-01-12 11:11:34 -08001015
1016 // powercycle the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -08001017 // we run this in a separate goroutine so that
1018 // the RebootRequestResponse is sent to VOLTHA
Matteo Scandolof9d43412021-01-12 11:11:34 -08001019 go func() {
Matteo Scandolocedde462021-03-09 17:37:16 -08001020 if err := o.Reboot(10 * time.Second); err != nil {
1021 log.WithFields(log.Fields{
1022 "IntfId": o.PonPortID,
1023 "OnuId": o.ID,
1024 "SerialNumber": o.Sn(),
1025 "err": err,
1026 }).Error("cannot-reboot-onu-after-omci-reboot-request")
1027 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001028 }()
1029 case omci.TestRequestType:
Girish Gowdra161d27a2021-05-05 12:01:44 -07001030 var classID me.ClassID
1031 var omciResult me.Results
1032 var instID uint16
1033 responsePkt, errResp, classID, instID, omciResult = omcilib.CreateTestResponse(msg.OmciPkt, msg.OmciMsg)
1034 // Send TestResult only in case the TestResponse omci result code is me.Success
1035 if responsePkt != nil && errResp == nil && omciResult == me.Success {
1036 if testResultPkt, err := omcilib.CreateTestResult(classID, instID, msg.OmciMsg.TransactionID); err == nil {
1037 // send test results asynchronously
1038 go func() {
1039 // Send test results after a second to emulate async behavior
1040 time.Sleep(1 * time.Second)
1041 if testResultPkt != nil {
1042 if err := o.sendOmciIndication(testResultPkt, msg.OmciMsg.TransactionID, stream); err != nil {
1043 onuLogger.WithFields(log.Fields{
1044 "IntfId": o.PonPortID,
1045 "SerialNumber": o.Sn(),
1046 "omciPacket": testResultPkt,
1047 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1048 "transCorrId": msg.OmciMsg.TransactionID,
1049 }).Errorf("failed-to-send-omci-message: %v", err)
1050 }
1051 }
1052 }()
Matteo Scandolof9d43412021-01-12 11:11:34 -08001053 }
1054 }
Girish Gowdraa539f522021-02-15 23:00:45 -08001055 case omci.SynchronizeTimeRequestType:
1056 // MDS counter increment is not required for this message type
Matteo Scandolob5913142021-03-19 16:10:18 -07001057 responsePkt, _ = omcilib.CreateSyncTimeResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolocedde462021-03-09 17:37:16 -08001058 case omci.StartSoftwareDownloadRequestType:
1059
1060 o.ImageSoftwareReceivedSections = 0
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301061 o.ImageSectionData = []byte{}
Matteo Scandolob5913142021-03-19 16:10:18 -07001062 o.ImageSoftwareExpectedSections = omcilib.ComputeDownloadSectionsCount(msg.OmciPkt)
Matteo Scandolocedde462021-03-09 17:37:16 -08001063
Matteo Scandolob5913142021-03-19 16:10:18 -07001064 if responsePkt, errResp = omcilib.CreateStartSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001065 o.MibDataSync++
1066 if err := o.InternalState.Event(OnuTxStartImageDownload); err != nil {
1067 onuLogger.WithFields(log.Fields{
1068 "OnuId": o.ID,
1069 "IntfId": o.PonPortID,
1070 "OnuSn": o.Sn(),
1071 "Err": err.Error(),
1072 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadStarted)
1073 }
1074 } else {
1075 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001076 "OmciMsgType": msg.OmciMsg.MessageType,
1077 "TransCorrId": msg.OmciMsg.TransactionID,
1078 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001079 "IntfId": o.PonPortID,
1080 "SerialNumber": o.Sn(),
1081 }).Error("error-while-processing-start-software-download-request")
1082 }
1083 case omci.DownloadSectionRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001084 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001085 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001086 "OmciMsgType": msg.OmciMsg.MessageType,
1087 "TransCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001088 "EntityInstance": msgObj.EntityInstance,
1089 "SectionNumber": msgObj.SectionNumber,
1090 "SectionData": msgObj.SectionData,
1091 }).Trace("received-download-section-request")
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001092 //Extracting the first 14 bytes to use as a version for this image.
1093 if o.ImageSoftwareReceivedSections == 0 {
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001094 o.InDownloadImageVersion = string(msgObj.SectionData[0:14])
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001095 }
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301096 o.ImageSectionData = append(o.ImageSectionData, msgObj.SectionData...)
Matteo Scandolocedde462021-03-09 17:37:16 -08001097 o.ImageSoftwareReceivedSections++
1098 if o.InternalState.Current() != OnuStateImageDownloadInProgress {
1099 if err := o.InternalState.Event(OnuTxProgressImageDownload); err != nil {
1100 onuLogger.WithFields(log.Fields{
1101 "OnuId": o.ID,
1102 "IntfId": o.PonPortID,
1103 "OnuSn": o.Sn(),
1104 "Err": err.Error(),
1105 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadInProgress)
1106 }
1107 }
1108 }
1109 case omci.DownloadSectionRequestWithResponseType:
1110 // NOTE we only need to respond if an ACK is requested
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301111 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001112 onuLogger.WithFields(log.Fields{
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301113 "OmciMsgType": msg.OmciMsg.MessageType,
1114 "TransCorrId": msg.OmciMsg.TransactionID,
1115 "EntityInstance": msgObj.EntityInstance,
1116 "SectionNumber": msgObj.SectionNumber,
1117 "SectionData": msgObj.SectionData,
1118 }).Trace("received-download-section-request-with-response-type")
1119 o.ImageSectionData = append(o.ImageSectionData, msgObj.SectionData...)
1120 responsePkt, errResp = omcilib.CreateDownloadSectionResponse(msg.OmciPkt, msg.OmciMsg)
1121
1122 if errResp != nil {
1123 onuLogger.WithFields(log.Fields{
1124 "OmciMsgType": msg.OmciMsg.MessageType,
1125 "TransCorrId": msg.OmciMsg.TransactionID,
1126 "Err": errResp.Error(),
1127 "IntfId": o.PonPortID,
1128 "SerialNumber": o.Sn(),
1129 }).Error("error-while-processing-create-download-section-response")
1130 return fmt.Errorf("error-while-processing-create-download-section-response: %s", errResp.Error())
1131 }
1132 o.ImageSoftwareReceivedSections++
Matteo Scandolocedde462021-03-09 17:37:16 -08001133 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001134 case omci.EndSoftwareDownloadRequestType:
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001135 success := o.handleEndSoftwareDownloadRequest(msg)
Matteo Scandolocedde462021-03-09 17:37:16 -08001136
Matteo Scandolocedde462021-03-09 17:37:16 -08001137 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -07001138 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001139 o.MibDataSync++
1140 if err := o.InternalState.Event(OnuTxCompleteImageDownload); err != nil {
1141 onuLogger.WithFields(log.Fields{
1142 "OnuId": o.ID,
1143 "IntfId": o.PonPortID,
1144 "OnuSn": o.Sn(),
1145 "Err": err.Error(),
1146 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadComplete)
1147 }
1148 } else {
1149 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001150 "OmciMsgType": msg.OmciMsg.MessageType,
1151 "TransCorrId": msg.OmciMsg.TransactionID,
1152 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001153 "IntfId": o.PonPortID,
1154 "SerialNumber": o.Sn(),
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001155 }).Error("error-while-responding-to-end-software-download-request")
Matteo Scandolocedde462021-03-09 17:37:16 -08001156 }
1157 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -07001158 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001159 if err := o.InternalState.Event(OnuTxFailImageDownload); err != nil {
1160 onuLogger.WithFields(log.Fields{
1161 "OnuId": o.ID,
1162 "IntfId": o.PonPortID,
1163 "OnuSn": o.Sn(),
1164 "Err": err.Error(),
1165 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadError)
1166 }
1167 }
1168 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001169 case omci.ActivateSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001170 if responsePkt, errResp = omcilib.CreateActivateSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001171 o.MibDataSync++
1172 if err := o.InternalState.Event(OnuTxActivateImage); err != nil {
1173 onuLogger.WithFields(log.Fields{
1174 "OnuId": o.ID,
1175 "IntfId": o.PonPortID,
1176 "OnuSn": o.Sn(),
1177 "Err": err.Error(),
1178 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageActivated)
1179 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001180 if msgObj, err := omcilib.ParseActivateSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001181 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001182 previousActiveImage := o.ActiveImageVersion
1183 o.ActiveImageVersion = o.StandbyImageVersion
1184 o.StandbyImageVersion = previousActiveImage
Matteo Scandolocedde462021-03-09 17:37:16 -08001185 } else {
1186 onuLogger.Errorf("something-went-wrong-while-activating: %s", err)
1187 }
1188 onuLogger.WithFields(log.Fields{
1189 "OnuId": o.ID,
1190 "IntfId": o.PonPortID,
1191 "OnuSn": o.Sn(),
1192 "ActiveImageEntityId": o.ActiveImageEntityId,
1193 "CommittedImageEntityId": o.CommittedImageEntityId,
1194 }).Info("onu-software-image-activated")
1195
1196 // powercycle the ONU
1197 // we run this in a separate goroutine so that
1198 // the ActivateSoftwareResponse is sent to VOLTHA
1199 // NOTE do we need to wait before rebooting?
1200 go func() {
1201 if err := o.Reboot(10 * time.Second); err != nil {
1202 log.WithFields(log.Fields{
1203 "IntfId": o.PonPortID,
1204 "OnuId": o.ID,
1205 "SerialNumber": o.Sn(),
1206 "err": err,
1207 }).Error("cannot-reboot-onu-after-omci-activate-software-request")
1208 }
1209 }()
1210 }
1211 case omci.CommitSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001212 if responsePkt, errResp = omcilib.CreateCommitSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001213 o.MibDataSync++
Matteo Scandolob5913142021-03-19 16:10:18 -07001214 if msgObj, err := omcilib.ParseCommitSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001215 // TODO validate that the image to commit is:
1216 // - active
1217 // - not already committed
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001218 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandolocedde462021-03-09 17:37:16 -08001219 o.CommittedImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001220 //committed becomes standby
1221 o.StandbyImageVersion = o.CommittedImageVersion
1222 o.CommittedImageVersion = o.ActiveImageVersion
Matteo Scandolocedde462021-03-09 17:37:16 -08001223 } else {
1224 onuLogger.Errorf("something-went-wrong-while-committing: %s", err)
1225 }
1226 if err := o.InternalState.Event(OnuTxCommitImage); err != nil {
1227 onuLogger.WithFields(log.Fields{
1228 "OnuId": o.ID,
1229 "IntfId": o.PonPortID,
1230 "OnuSn": o.Sn(),
1231 "Err": err.Error(),
1232 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageCommitted)
1233 }
1234 onuLogger.WithFields(log.Fields{
1235 "OnuId": o.ID,
1236 "IntfId": o.PonPortID,
1237 "OnuSn": o.Sn(),
1238 "ActiveImageEntityId": o.ActiveImageEntityId,
1239 "CommittedImageEntityId": o.CommittedImageEntityId,
1240 }).Info("onu-software-image-committed")
1241 }
Himani Chawla13b1ee02021-03-15 01:43:53 +05301242 case omci.GetAllAlarmsRequestType:
1243 // Reset the alarm sequence number on receiving get all alarms request.
1244 o.onuAlarmsInfoLock.Lock()
1245 for key, alarmInfo := range o.onuAlarmsInfo {
1246 // reset the alarm sequence no
1247 alarmInfo.SequenceNo = 0
1248 o.onuAlarmsInfo[key] = alarmInfo
1249 }
1250 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolob5913142021-03-19 16:10:18 -07001251 responsePkt, _ = omcilib.CreateGetAllAlarmsResponse(msg.OmciMsg.TransactionID, o.onuAlarmsInfo)
Himani Chawla13b1ee02021-03-15 01:43:53 +05301252 case omci.GetAllAlarmsNextRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001253 if responsePkt, errResp = omcilib.CreateGetAllAlarmsNextResponse(msg.OmciPkt, msg.OmciMsg, o.onuAlarmsInfo); errResp != nil {
Himani Chawla13b1ee02021-03-15 01:43:53 +05301254 responsePkt = nil //Do not send any response for error case
1255 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001256 default:
Matteo Scandolocedde462021-03-09 17:37:16 -08001257 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001258 "omciBytes": hex.EncodeToString(msg.OmciPkt.Data()),
1259 "omciPkt": msg.OmciPkt,
1260 "omciMsgType": msg.OmciMsg.MessageType,
1261 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001262 "IntfId": o.PonPortID,
1263 "SerialNumber": o.Sn(),
1264 }).Warnf("OMCI-message-not-supported")
1265 }
1266
1267 if responsePkt != nil {
Matteo Scandolob5913142021-03-19 16:10:18 -07001268 if err := o.sendOmciIndication(responsePkt, msg.OmciMsg.TransactionID, stream); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001269 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001270 "IntfId": o.PonPortID,
1271 "SerialNumber": o.Sn(),
1272 "omciPacket": responsePkt,
1273 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1274 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001275 }).Errorf("failed-to-send-omci-message: %v", err)
1276 }
1277 }
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001278
Pragya Arya324337e2020-02-20 14:35:08 +05301279 o.publishOmciEvent(msg)
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +02001280 return nil
Matteo Scandolof9d43412021-01-12 11:11:34 -08001281}
Pragya Arya324337e2020-02-20 14:35:08 +05301282
Matteo Scandolof9d43412021-01-12 11:11:34 -08001283// sendOmciIndication takes an OMCI packet and sends it up to VOLTHA
1284func (o *Onu) sendOmciIndication(responsePkt []byte, txId uint16, stream bbsim.Stream) error {
1285 indication := &openolt.Indication_OmciInd{
1286 OmciInd: &openolt.OmciIndication{
1287 IntfId: o.PonPortID,
1288 OnuId: o.ID,
1289 Pkt: responsePkt,
1290 },
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001291 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001292 if err := stream.Send(&openolt.Indication{Data: indication}); err != nil {
1293 return fmt.Errorf("failed-to-send-omci-message: %v", err)
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001294 }
1295 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001296 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -07001297 "SerialNumber": o.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001298 "omciPacket": hex.EncodeToString(indication.OmciInd.Pkt),
Matteo Scandolof9d43412021-01-12 11:11:34 -08001299 "transCorrId": txId,
1300 }).Trace("omci-message-sent")
1301 return nil
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001302}
1303
Matteo Scandolo8a574812021-05-20 15:18:53 -07001304// FindUniById retrieves a UNI by ID
1305func (o *Onu) FindUniById(uniID uint32) (*UniPort, error) {
1306 for _, u := range o.UniPorts {
1307 uni := u.(*UniPort)
1308 if uni.ID == uniID {
1309 return uni, nil
1310 }
Matteo Scandolo27428702019-10-11 16:21:16 -07001311 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001312 return nil, fmt.Errorf("cannot-find-uni-with-id-%d-on-onu-%s", uniID, o.Sn())
1313}
1314
Elia Battistonac63b112022-01-12 18:40:49 +01001315// FindPotsById retrieves a POTS port by ID
1316func (o *Onu) FindPotsById(uniID uint32) (*PotsPort, error) {
1317 for _, p := range o.PotsPorts {
1318 pots := p.(*PotsPort)
1319 if pots.ID == uniID {
1320 return pots, nil
1321 }
1322 }
1323 return nil, fmt.Errorf("cannot-find-pots-with-id-%d-on-onu-%s", uniID, o.Sn())
1324}
1325
Matteo Scandolo8a574812021-05-20 15:18:53 -07001326// FindUniByEntityId retrieves a uni by MeID (the OMCI entity ID)
1327func (o *Onu) FindUniByEntityId(meId uint16) (*UniPort, error) {
1328 entityId := omcilib.EntityID{}.FromUint16(meId)
1329 for _, u := range o.UniPorts {
1330 uni := u.(*UniPort)
1331 if uni.MeId.Equals(entityId) {
1332 return uni, nil
1333 }
1334 }
1335 return nil, fmt.Errorf("cannot-find-uni-with-meid-%s-on-onu-%s", entityId.ToString(), o.Sn())
Matteo Scandolo27428702019-10-11 16:21:16 -07001336}
1337
Elia Battistonac63b112022-01-12 18:40:49 +01001338// FindPotsByEntityId retrieves a POTS uni by MeID (the OMCI entity ID)
1339func (o *Onu) FindPotsByEntityId(meId uint16) (*PotsPort, error) {
1340 entityId := omcilib.EntityID{}.FromUint16(meId)
1341 for _, p := range o.PotsPorts {
1342 pots := p.(*PotsPort)
1343 if pots.MeId.Equals(entityId) {
1344 return pots, nil
1345 }
1346 }
1347 return nil, fmt.Errorf("cannot-find-pots-with-meid-%s-on-onu-%s", entityId.ToString(), o.Sn())
1348}
1349
William Kurkian0418bc82019-11-06 12:16:24 -05001350func (o *Onu) SetID(id uint32) {
Matteo Scandolo583f17d2020-02-13 10:35:17 -08001351 onuLogger.WithFields(log.Fields{
1352 "IntfId": o.PonPortID,
1353 "OnuId": id,
1354 "SerialNumber": o.Sn(),
1355 }).Debug("Storing OnuId ")
William Kurkian0418bc82019-11-06 12:16:24 -05001356 o.ID = id
1357}
1358
Matteo Scandolof9d43412021-01-12 11:11:34 -08001359func (o *Onu) handleFlowAdd(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001360 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001361 "AllocId": msg.Flow.AllocId,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001362 "Cookie": msg.Flow.Cookie,
1363 "DstPort": msg.Flow.Classifier.DstPort,
1364 "FlowId": msg.Flow.FlowId,
1365 "FlowType": msg.Flow.FlowType,
1366 "GemportId": msg.Flow.GemportId,
1367 "InnerVlan": msg.Flow.Classifier.IVid,
1368 "IntfId": msg.Flow.AccessIntfId,
1369 "IpProto": msg.Flow.Classifier.IpProto,
1370 "OnuId": msg.Flow.OnuId,
1371 "OnuSn": o.Sn(),
1372 "OuterVlan": msg.Flow.Classifier.OVid,
1373 "PortNo": msg.Flow.PortNo,
1374 "SrcPort": msg.Flow.Classifier.SrcPort,
1375 "UniID": msg.Flow.UniId,
1376 "ClassifierEthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
1377 "ClassifierOPbits": msg.Flow.Classifier.OPbits,
1378 "ClassifierIVid": msg.Flow.Classifier.IVid,
1379 "ClassifierOVid": msg.Flow.Classifier.OVid,
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001380 "ReplicateFlow": msg.Flow.ReplicateFlow,
1381 "PbitToGemport": msg.Flow.PbitToGemport,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001382 }).Debug("OLT receives FlowAdd for ONU")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001383
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001384 o.FlowIds = append(o.FlowIds, msg.Flow.FlowId)
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001385
1386 var gemPortId uint32
1387 if msg.Flow.ReplicateFlow {
1388 // This means that the OLT should replicate the flow for each PBIT, for BBSim it's enough to use the
1389 // first available gemport (we only need to send one packet)
1390 // NOTE different TP may create different mapping between PBits and GemPorts, this may require some changes
1391 gemPortId = msg.Flow.PbitToGemport[0]
1392 } else {
1393 // if replicateFlows is false, then the flow is carrying the correct GemPortId
1394 gemPortId = uint32(msg.Flow.GemportId)
1395 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001396
1397 uni, err := o.FindUniById(uint32(msg.Flow.UniId))
1398 if err != nil {
1399 onuLogger.WithFields(log.Fields{
1400 "IntfId": o.PonPortID,
1401 "OnuId": o.ID,
1402 "UniId": msg.Flow.UniId,
1403 "PortNo": msg.Flow.PortNo,
1404 "SerialNumber": o.Sn(),
1405 "FlowId": msg.Flow.FlowId,
1406 "FlowType": msg.Flow.FlowType,
1407 }).Error("cannot-find-uni-port-for-flow")
1408 }
1409
1410 uni.addGemPortToService(gemPortId, msg.Flow.Classifier.EthType, msg.Flow.Classifier.OVid, msg.Flow.Classifier.IVid)
1411 uni.StorePortNo(msg.Flow.PortNo)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001412
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001413 if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
Elia Battistonda45f6e2022-02-24 11:12:16 +01001414 onuLogger.WithFields(log.Fields{
1415 "IntfId": o.PonPortID,
1416 "OnuId": o.ID,
1417 "UniId": msg.Flow.UniId,
1418 "PortNo": msg.Flow.PortNo,
1419 "SerialNumber": o.Sn(),
1420 "FlowId": msg.Flow.FlowId,
1421 }).Debug("EAPOL flow detected")
Matteo Scandolo8a574812021-05-20 15:18:53 -07001422 uni.HandleAuth()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001423 } else if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeIPv4) &&
1424 msg.Flow.Classifier.SrcPort == uint32(68) &&
Matteo Scandolobd875b32020-09-18 17:46:31 -07001425 msg.Flow.Classifier.DstPort == uint32(67) {
Elia Battistonda45f6e2022-02-24 11:12:16 +01001426 onuLogger.WithFields(log.Fields{
1427 "IntfId": o.PonPortID,
1428 "OnuId": o.ID,
1429 "UniId": msg.Flow.UniId,
1430 "PortNo": msg.Flow.PortNo,
1431 "SerialNumber": o.Sn(),
1432 "FlowId": msg.Flow.FlowId,
1433 "FlowType": msg.Flow.FlowType,
1434 }).Debug("DHCP flow detected")
Matteo Scandolo8a574812021-05-20 15:18:53 -07001435 uni.HandleDhcp(uint8(msg.Flow.Classifier.OPbits), int(msg.Flow.Classifier.OVid))
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001436 }
1437}
1438
Matteo Scandolof9d43412021-01-12 11:11:34 -08001439func (o *Onu) handleFlowRemove(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001440 onuLogger.WithFields(log.Fields{
1441 "IntfId": o.PonPortID,
1442 "OnuId": o.ID,
1443 "SerialNumber": o.Sn(),
1444 "FlowId": msg.Flow.FlowId,
1445 "FlowType": msg.Flow.FlowType,
1446 }).Debug("ONU receives FlowRemove")
1447
1448 for idx, flow := range o.FlowIds {
1449 // If the gemport is found, delete it from local cache.
1450 if flow == msg.Flow.FlowId {
1451 o.FlowIds = append(o.FlowIds[:idx], o.FlowIds[idx+1:]...)
1452 break
1453 }
1454 }
1455
1456 if len(o.FlowIds) == 0 {
1457 onuLogger.WithFields(log.Fields{
1458 "IntfId": o.PonPortID,
1459 "OnuId": o.ID,
1460 "SerialNumber": o.Sn(),
1461 }).Info("Resetting GemPort")
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001462
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301463 // check if ONU delete is performed and
1464 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolocedde462021-03-09 17:37:16 -08001465 if o.InternalState.Current() == OnuStateDisabled {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301466 close(o.Channel)
1467 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001468 }
1469}
1470
Matteo Scandolocedde462021-03-09 17:37:16 -08001471func (o *Onu) Reboot(timeout time.Duration) error {
1472 onuLogger.WithFields(log.Fields{
1473 "IntfId": o.PonPortID,
1474 "OnuId": o.ID,
1475 "SerialNumber": o.Sn(),
1476 }).Debug("shutting-down-onu")
1477 if err := o.HandleShutdownONU(); err != nil {
1478 return err
1479 }
1480 time.Sleep(timeout)
1481 onuLogger.WithFields(log.Fields{
1482 "IntfId": o.PonPortID,
1483 "OnuId": o.ID,
1484 "SerialNumber": o.Sn(),
1485 }).Debug("power-on-onu")
1486 if err := o.HandlePowerOnONU(); err != nil {
1487 return err
1488 }
1489 return nil
1490}
1491
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001492// returns true if the request is successful, false otherwise
1493func (o *Onu) handleEndSoftwareDownloadRequest(msg bbsim.OmciMessage) bool {
1494 msgObj, err := omcilib.ParseEndSoftwareDownloadRequest(msg.OmciPkt)
1495 if err != nil {
1496 onuLogger.WithFields(log.Fields{
1497 "OmciMsgType": msg.OmciMsg.MessageType,
1498 "TransCorrId": msg.OmciMsg.TransactionID,
1499 "Err": err.Error(),
1500 "IntfId": o.PonPortID,
1501 "SerialNumber": o.Sn(),
1502 }).Error("error-while-processing-end-software-download-request")
1503 return false
1504 }
1505
1506 onuLogger.WithFields(log.Fields{
1507 "OnuId": o.ID,
1508 "IntfId": o.PonPortID,
1509 "OnuSn": o.Sn(),
1510 "msgObj": msgObj,
1511 }).Trace("EndSoftwareDownloadRequest received message")
1512
1513 // if the image download is ongoing and we receive a message with
1514 // ImageSize = 0 and Crc = 4294967295 (0xFFFFFFFF) respond with success
1515 if o.ImageSoftwareReceivedSections > 0 &&
1516 msgObj.ImageSize == 0 &&
1517 msgObj.CRC32 == 4294967295 {
1518 o.ImageSoftwareReceivedSections = 0
1519 // NOTE potentially we may want to add a ONU state to reflect
1520 // the software download abort
1521 return true
1522 }
1523
1524 // In the startSoftwareDownload we get the image size and the window size.
1525 // We calculate how many DownloadSection we should receive and validate
1526 // that we got the correct amount when we receive this message
1527 // If the received sections are different from the expected sections
1528 // respond with failure
1529 if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
1530 onuLogger.WithFields(log.Fields{
1531 "OnuId": o.ID,
1532 "IntfId": o.PonPortID,
1533 "OnuSn": o.Sn(),
1534 "ExpectedSections": o.ImageSoftwareExpectedSections,
1535 "ReceivedSections": o.ImageSoftwareReceivedSections,
1536 }).Errorf("onu-did-not-receive-all-image-sections")
1537 return false
1538 }
1539
1540 // check the received CRC vs the computed CRC
1541 computedCRC := crc32a.Checksum(o.ImageSectionData[:int(msgObj.ImageSize)])
1542 //Convert the crc to network byte order
1543 var byteSlice = make([]byte, 4)
1544 binary.LittleEndian.PutUint32(byteSlice, computedCRC)
1545 computedCRC = binary.BigEndian.Uint32(byteSlice)
1546 if msgObj.CRC32 != computedCRC {
1547 onuLogger.WithFields(log.Fields{
1548 "OnuId": o.ID,
1549 "IntfId": o.PonPortID,
1550 "OnuSn": o.Sn(),
1551 "ReceivedCRC": msgObj.CRC32,
1552 "CalculatedCRC": computedCRC,
1553 }).Errorf("onu-image-crc-validation-failed")
1554 return false
1555 }
1556
1557 o.StandbyImageVersion = o.InDownloadImageVersion
1558 onuLogger.WithFields(log.Fields{
1559 "OnuId": o.ID,
1560 "IntfId": o.PonPortID,
1561 "OnuSn": o.Sn(),
1562 "StandbyVersion": o.StandbyImageVersion,
1563 }).Debug("onu-image-version-updated")
1564 return true
1565}
1566
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001567// BBR methods
1568
1569func sendOmciMsg(pktBytes []byte, intfId uint32, onuId uint32, sn *openolt.SerialNumber, msgType string, client openolt.OpenoltClient) {
1570 omciMsg := openolt.OmciMsg{
1571 IntfId: intfId,
1572 OnuId: onuId,
1573 Pkt: pktBytes,
1574 }
1575
1576 if _, err := client.OmciMsgOut(context.Background(), &omciMsg); err != nil {
1577 log.WithFields(log.Fields{
1578 "IntfId": intfId,
1579 "OnuId": onuId,
1580 "SerialNumber": common.OnuSnToString(sn),
1581 "Pkt": omciMsg.Pkt,
1582 }).Fatalf("Failed to send MIB Reset")
1583 }
1584 log.WithFields(log.Fields{
1585 "IntfId": intfId,
1586 "OnuId": onuId,
1587 "SerialNumber": common.OnuSnToString(sn),
1588 "Pkt": omciMsg.Pkt,
1589 }).Tracef("Sent OMCI message %s", msgType)
1590}
1591
1592func (onu *Onu) getNextTid(highPriority ...bool) uint16 {
1593 var next uint16
1594 if len(highPriority) > 0 && highPriority[0] {
1595 next = onu.hpTid
1596 onu.hpTid += 1
1597 if onu.hpTid < 0x8000 {
1598 onu.hpTid = 0x8000
1599 }
1600 } else {
1601 next = onu.tid
1602 onu.tid += 1
1603 if onu.tid >= 0x8000 {
1604 onu.tid = 1
1605 }
1606 }
1607 return next
1608}
1609
1610// TODO move this method in responders/omcisim
Matteo Scandolo8a574812021-05-20 15:18:53 -07001611// StartOmci is called in BBR to start the OMCI state machine
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001612func (o *Onu) StartOmci(client openolt.OpenoltClient) {
1613 mibReset, _ := omcilib.CreateMibResetRequest(o.getNextTid(false))
1614 sendOmciMsg(mibReset, o.PonPortID, o.ID, o.SerialNumber, "mibReset", client)
1615}
1616
Matteo Scandolof9d43412021-01-12 11:11:34 -08001617// handleOmciResponse is used in BBR to generate the OMCI packets the openolt-adapter would send to the device
1618func (o *Onu) handleOmciResponse(msg bbsim.OmciIndicationMessage, client openolt.OpenoltClient) {
1619
1620 // we need to encode the packet in HEX
1621 pkt := make([]byte, len(msg.OmciInd.Pkt)*2)
1622 hex.Encode(pkt, msg.OmciInd.Pkt)
1623 packet, omciMsg, err := omcilib.ParseOpenOltOmciPacket(pkt)
1624 if err != nil {
1625 log.WithFields(log.Fields{
1626 "IntfId": o.PonPortID,
1627 "SerialNumber": o.Sn(),
1628 "omciPacket": msg.OmciInd.Pkt,
1629 }).Error("BBR Cannot parse OMCI packet")
1630 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001631
1632 log.WithFields(log.Fields{
1633 "IntfId": msg.OmciInd.IntfId,
1634 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001635 "OnuSn": o.Sn(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001636 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001637 "msgType": omciMsg.MessageType,
Anand S Katti09541352020-01-29 15:54:01 +05301638 }).Trace("ONU Receives OMCI Msg")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001639 switch omciMsg.MessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001640 default:
Matteo Scandolo813402b2019-10-23 19:24:52 -07001641 log.WithFields(log.Fields{
1642 "IntfId": msg.OmciInd.IntfId,
1643 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001644 "OnuSn": o.Sn(),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001645 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001646 "msgType": omciMsg.MessageType,
Matteo Scandolo813402b2019-10-23 19:24:52 -07001647 }).Fatalf("unexpected frame: %v", packet)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001648 case omci.MibResetResponseType:
1649 mibUpload, _ := omcilib.CreateMibUploadRequest(o.getNextTid(false))
1650 sendOmciMsg(mibUpload, o.PonPortID, o.ID, o.SerialNumber, "mibUpload", client)
1651 case omci.MibUploadResponseType:
1652 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1653 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
1654 case omci.MibUploadNextResponseType:
1655 o.seqNumber++
Matteo Scandolo8a574812021-05-20 15:18:53 -07001656 // once the mibUpload is complete send a SetRequest for the PPTP to enable the UNI
1657 // NOTE that in BBR we only enable the first UNI
Holger Hildebrandt236e3742022-05-04 14:07:27 +00001658 if o.seqNumber == o.MibDb.NumberOfBaselineCommands {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001659 meId := omcilib.GenerateUniPortEntityId(1)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001660
Matteo Scandolo8a574812021-05-20 15:18:53 -07001661 meParams := me.ParamData{
1662 EntityID: meId.ToUint16(),
Elia Battiston9bfe1102022-02-03 10:38:03 +01001663 Attributes: me.AttributeValueMap{me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0},
Matteo Scandolo8a574812021-05-20 15:18:53 -07001664 }
1665 managedEntity, omciError := me.NewPhysicalPathTerminationPointEthernetUni(meParams)
1666 if omciError.GetError() != nil {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001667 onuLogger.WithFields(log.Fields{
1668 "OnuId": o.ID,
1669 "IntfId": o.PonPortID,
1670 "OnuSn": o.Sn(),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001671 }).Fatal(omciError.GetError())
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001672 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001673
1674 setPPtp, _ := omcilib.CreateSetRequest(managedEntity, 1)
1675 sendOmciMsg(setPPtp, o.PonPortID, o.ID, o.SerialNumber, "setRquest", client)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001676 } else {
1677 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1678 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001679 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001680 case omci.SetResponseType:
1681 // once we set the PPTP to active we can start sending flows
1682
1683 if err := o.InternalState.Event(BbrOnuTxSendEapolFlow); err != nil {
1684 onuLogger.WithFields(log.Fields{
1685 "OnuId": o.ID,
1686 "IntfId": o.PonPortID,
1687 "OnuSn": o.Sn(),
1688 }).Errorf("Error while transitioning ONU State %v", err)
1689 }
1690 case omci.AlarmNotificationType:
1691 log.Info("bbr-received-alarm")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001692 }
1693}
1694
1695func (o *Onu) sendEapolFlow(client openolt.OpenoltClient) {
1696
1697 classifierProto := openolt.Classifier{
1698 EthType: uint32(layers.EthernetTypeEAPOL),
1699 OVid: 4091,
1700 }
1701
1702 actionProto := openolt.Action{}
1703
1704 downstreamFlow := openolt.Flow{
1705 AccessIntfId: int32(o.PonPortID),
1706 OnuId: int32(o.ID),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001707 UniId: int32(0), // NOTE do not hardcode this, we need to support multiple UNIs
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001708 FlowId: uint64(o.ID),
Elia Battiston560e9552022-01-31 10:44:15 +01001709 FlowType: flowTypeDownstream,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001710 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001711 Classifier: &classifierProto,
1712 Action: &actionProto,
1713 Priority: int32(100),
1714 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001715 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1716 // AllocId and GemPorts need to be unique per PON
1717 // for now use the ONU-ID, will need to change once we support multiple UNIs
1718 AllocId: int32(o.ID),
1719 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001720 }
1721
1722 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1723 log.WithFields(log.Fields{
1724 "IntfId": o.PonPortID,
1725 "OnuId": o.ID,
1726 "FlowId": downstreamFlow.FlowId,
1727 "PortNo": downstreamFlow.PortNo,
1728 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001729 "Err": err,
Matteo Scandolob0e3e622020-04-23 17:00:29 -07001730 }).Fatalf("Failed to add EAPOL Flow")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001731 }
1732 log.WithFields(log.Fields{
1733 "IntfId": o.PonPortID,
1734 "OnuId": o.ID,
1735 "FlowId": downstreamFlow.FlowId,
1736 "PortNo": downstreamFlow.PortNo,
1737 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1738 }).Info("Sent EAPOL Flow")
1739}
1740
1741func (o *Onu) sendDhcpFlow(client openolt.OpenoltClient) {
Matteo Scandolo4a036262020-08-17 15:56:13 -07001742
Matteo Scandolo8a574812021-05-20 15:18:53 -07001743 // BBR only works with a single UNI and a single service (ATT HSIA)
1744 hsia := o.UniPorts[0].(*UniPort).Services[0].(*Service)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001745 classifierProto := openolt.Classifier{
1746 EthType: uint32(layers.EthernetTypeIPv4),
1747 SrcPort: uint32(68),
1748 DstPort: uint32(67),
Matteo Scandolo4a036262020-08-17 15:56:13 -07001749 OVid: uint32(hsia.CTag),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001750 OPbits: 255,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001751 }
1752
1753 actionProto := openolt.Action{}
1754
1755 downstreamFlow := openolt.Flow{
1756 AccessIntfId: int32(o.PonPortID),
1757 OnuId: int32(o.ID),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001758 UniId: int32(0), // BBR only supports a single UNI
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001759 FlowId: uint64(o.ID),
Elia Battiston560e9552022-01-31 10:44:15 +01001760 FlowType: flowTypeDownstream,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001761 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001762 Classifier: &classifierProto,
1763 Action: &actionProto,
1764 Priority: int32(100),
1765 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001766 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1767 // AllocId and GemPorts need to be unique per PON
1768 // for now use the ONU-ID, will need to change once we support multiple UNIs
1769 AllocId: int32(o.ID),
1770 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001771 }
1772
1773 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1774 log.WithFields(log.Fields{
1775 "IntfId": o.PonPortID,
1776 "OnuId": o.ID,
1777 "FlowId": downstreamFlow.FlowId,
1778 "PortNo": downstreamFlow.PortNo,
1779 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001780 "Err": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001781 }).Fatalf("Failed to send DHCP Flow")
1782 }
1783 log.WithFields(log.Fields{
1784 "IntfId": o.PonPortID,
1785 "OnuId": o.ID,
1786 "FlowId": downstreamFlow.FlowId,
1787 "PortNo": downstreamFlow.PortNo,
1788 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1789 }).Info("Sent DHCP Flow")
1790}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301791
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001792// DeleteFlow method search and delete flowKey from the onu flows slice
1793func (onu *Onu) DeleteFlow(key FlowKey) {
1794 for pos, flowKey := range onu.Flows {
1795 if flowKey == key {
1796 // delete the flowKey by shifting all flowKeys by one
1797 onu.Flows = append(onu.Flows[:pos], onu.Flows[pos+1:]...)
1798 t := make([]FlowKey, len(onu.Flows))
1799 copy(t, onu.Flows)
1800 onu.Flows = t
Pragya Arya8bdb4532020-03-02 17:08:09 +05301801 break
1802 }
1803 }
1804}
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301805
1806func (onu *Onu) ReDiscoverOnu() {
1807 // Wait for few seconds to be sure of the cleanup
1808 time.Sleep(5 * time.Second)
1809
1810 onuLogger.WithFields(log.Fields{
1811 "IntfId": onu.PonPortID,
1812 "OnuId": onu.ID,
1813 "OnuSn": onu.Sn(),
1814 }).Debug("Send ONU Re-Discovery")
1815
1816 // ONU Re-Discovery
Matteo Scandolocedde462021-03-09 17:37:16 -08001817 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301818 log.WithFields(log.Fields{
1819 "IntfId": onu.PonPortID,
1820 "OnuSn": onu.Sn(),
1821 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001822 }).Infof("Failed to transition ONU to %s state: %s", OnuStateInitialized, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301823 }
1824
Matteo Scandolocedde462021-03-09 17:37:16 -08001825 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301826 log.WithFields(log.Fields{
1827 "IntfId": onu.PonPortID,
1828 "OnuSn": onu.Sn(),
1829 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001830 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDiscovered, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301831 }
1832}
Matteo Scandolo4a036262020-08-17 15:56:13 -07001833
Matteo Scandolo8a574812021-05-20 15:18:53 -07001834// deprecated, delegate this to the uniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -07001835func (onu *Onu) findServiceByMacAddress(macAddress net.HardwareAddr) (*Service, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001836 // FIXME is there a better way to avoid this loop?
1837 for _, u := range onu.UniPorts {
1838 uni := u.(*UniPort)
1839 for _, s := range uni.Services {
1840 service := s.(*Service)
1841 if service.HwAddress.String() == macAddress.String() {
1842 return service, nil
1843 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001844 }
1845 }
1846 return nil, fmt.Errorf("cannot-find-service-with-mac-address-%s", macAddress.String())
1847}
Himani Chawla13b1ee02021-03-15 01:43:53 +05301848
Matteo Scandolo8a574812021-05-20 15:18:53 -07001849func (onu *Onu) findUniByPortNo(portNo uint32) (*UniPort, error) {
1850 for _, u := range onu.UniPorts {
1851 uni := u.(*UniPort)
1852 if uni.PortNo == portNo {
1853 return uni, nil
1854 }
1855 }
1856 return nil, fmt.Errorf("cannot-find-uni-with-port-no-%d", portNo)
1857}
1858
Himani Chawla13b1ee02021-03-15 01:43:53 +05301859func (o *Onu) SendOMCIAlarmNotificationMsg(raiseOMCIAlarm bool, alarmType string) {
1860 switch alarmType {
1861 case "ONU_ALARM_LOS":
1862 msg := bbsim.Message{
1863 Type: bbsim.UniStatusAlarm,
1864 Data: bbsim.UniStatusAlarmMessage{
1865 OnuSN: o.SerialNumber,
1866 OnuID: o.ID,
1867 EntityID: 257,
1868 RaiseOMCIAlarm: raiseOMCIAlarm,
1869 },
1870 }
1871 o.Channel <- msg
1872 }
1873
1874}
1875
1876func (o *Onu) IncrementAlarmSequenceNumber(key omcilib.OnuAlarmInfoMapKey) uint8 {
1877 o.onuAlarmsInfoLock.Lock()
1878 defer o.onuAlarmsInfoLock.Unlock()
1879 if alarmInfo, ok := o.onuAlarmsInfo[key]; ok {
1880 if alarmInfo.SequenceNo == 255 {
1881 alarmInfo.SequenceNo = 1
1882 } else {
1883 alarmInfo.SequenceNo++
1884 }
1885 o.onuAlarmsInfo[key] = alarmInfo
1886 return alarmInfo.SequenceNo
1887 } else {
1888 // This is the first time alarm notification message is being sent
1889 o.onuAlarmsInfo[key] = omcilib.OnuAlarmInfo{
1890 SequenceNo: 1,
1891 }
1892 return 1
1893 }
1894}
Elia Battistonfe017662022-01-05 11:43:16 +01001895
1896func (o *Onu) InvalidateMibDataSync() {
1897 rand.Seed(time.Now().UnixNano())
1898 r := uint8(rand.Intn(10) + 1)
1899
1900 o.MibDataSync += r
1901
1902 // Since MibDataSync is a uint8, summing to it will never
1903 // result in a value higher than 255, but could be 0
1904 if o.MibDataSync == 0 {
1905 o.MibDataSync++
1906 }
1907}