blob: 4d913b6313b74251d5d6cd9f78c5b6081ae64936 [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
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301806/* when ReDiscoverOnu is called during reboot, true is passed so that there is no delay in onu discoveries
1807 It is assumed that all onu resources are cleared and no sleep is required
1808*/
1809func (onu *Onu) ReDiscoverOnu(isReboot bool) {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301810 // Wait for few seconds to be sure of the cleanup
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301811 if !isReboot {
1812 time.Sleep(5 * time.Second)
1813 }
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301814
1815 onuLogger.WithFields(log.Fields{
1816 "IntfId": onu.PonPortID,
1817 "OnuId": onu.ID,
1818 "OnuSn": onu.Sn(),
1819 }).Debug("Send ONU Re-Discovery")
1820
1821 // ONU Re-Discovery
Matteo Scandolocedde462021-03-09 17:37:16 -08001822 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301823 log.WithFields(log.Fields{
1824 "IntfId": onu.PonPortID,
1825 "OnuSn": onu.Sn(),
1826 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001827 }).Infof("Failed to transition ONU to %s state: %s", OnuStateInitialized, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301828 }
1829
Matteo Scandolocedde462021-03-09 17:37:16 -08001830 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301831 log.WithFields(log.Fields{
1832 "IntfId": onu.PonPortID,
1833 "OnuSn": onu.Sn(),
1834 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001835 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDiscovered, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301836 }
1837}
Matteo Scandolo4a036262020-08-17 15:56:13 -07001838
Matteo Scandolo8a574812021-05-20 15:18:53 -07001839// deprecated, delegate this to the uniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -07001840func (onu *Onu) findServiceByMacAddress(macAddress net.HardwareAddr) (*Service, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001841 // FIXME is there a better way to avoid this loop?
1842 for _, u := range onu.UniPorts {
1843 uni := u.(*UniPort)
1844 for _, s := range uni.Services {
1845 service := s.(*Service)
1846 if service.HwAddress.String() == macAddress.String() {
1847 return service, nil
1848 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001849 }
1850 }
1851 return nil, fmt.Errorf("cannot-find-service-with-mac-address-%s", macAddress.String())
1852}
Himani Chawla13b1ee02021-03-15 01:43:53 +05301853
Matteo Scandolo8a574812021-05-20 15:18:53 -07001854func (onu *Onu) findUniByPortNo(portNo uint32) (*UniPort, error) {
1855 for _, u := range onu.UniPorts {
1856 uni := u.(*UniPort)
1857 if uni.PortNo == portNo {
1858 return uni, nil
1859 }
1860 }
1861 return nil, fmt.Errorf("cannot-find-uni-with-port-no-%d", portNo)
1862}
1863
Himani Chawla13b1ee02021-03-15 01:43:53 +05301864func (o *Onu) SendOMCIAlarmNotificationMsg(raiseOMCIAlarm bool, alarmType string) {
1865 switch alarmType {
1866 case "ONU_ALARM_LOS":
1867 msg := bbsim.Message{
1868 Type: bbsim.UniStatusAlarm,
1869 Data: bbsim.UniStatusAlarmMessage{
1870 OnuSN: o.SerialNumber,
1871 OnuID: o.ID,
1872 EntityID: 257,
1873 RaiseOMCIAlarm: raiseOMCIAlarm,
1874 },
1875 }
1876 o.Channel <- msg
1877 }
1878
1879}
1880
1881func (o *Onu) IncrementAlarmSequenceNumber(key omcilib.OnuAlarmInfoMapKey) uint8 {
1882 o.onuAlarmsInfoLock.Lock()
1883 defer o.onuAlarmsInfoLock.Unlock()
1884 if alarmInfo, ok := o.onuAlarmsInfo[key]; ok {
1885 if alarmInfo.SequenceNo == 255 {
1886 alarmInfo.SequenceNo = 1
1887 } else {
1888 alarmInfo.SequenceNo++
1889 }
1890 o.onuAlarmsInfo[key] = alarmInfo
1891 return alarmInfo.SequenceNo
1892 } else {
1893 // This is the first time alarm notification message is being sent
1894 o.onuAlarmsInfo[key] = omcilib.OnuAlarmInfo{
1895 SequenceNo: 1,
1896 }
1897 return 1
1898 }
1899}
Elia Battistonfe017662022-01-05 11:43:16 +01001900
1901func (o *Onu) InvalidateMibDataSync() {
1902 rand.Seed(time.Now().UnixNano())
1903 r := uint8(rand.Intn(10) + 1)
1904
1905 o.MibDataSync += r
1906
1907 // Since MibDataSync is a uint8, summing to it will never
1908 // result in a value higher than 255, but could be 0
1909 if o.MibDataSync == 0 {
1910 o.MibDataSync++
1911 }
1912}