blob: 57b3aa0a751156e34cb1ef57a5d45fcf2e0ea3b7 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
Joey Armstrong2c039362024-02-04 18:51:52 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Matteo Scandolo11006992019-08-28 11:29:46 -07003
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{
Baris Ertas53ab13c2023-05-25 16:31:48 +0300511 "IntfId": msg.IntfId,
512 "OnuId": msg.OnuId,
513 "pktType": msg.Type,
514 "OnuSn": o.Sn(),
515 "gemportid": msg.GemPortId,
David Bainbridge103cf022019-12-16 20:11:35 +0000516 }).Trace("Received OnuPacketOut Message")
517
Baris Ertas53ab13c2023-05-25 16:31:48 +0300518 if msg.GemPortId == multicastGemPortId {
519 unis := o.findUniWithIgmpMembership()
520 if len(unis) == 0 {
521 onuLogger.WithFields(log.Fields{
522 "IntfId": msg.IntfId,
523 "OnuId": msg.OnuId,
524 "pktType": msg.Type,
525 "portNo": msg.PortNo,
526 "MacAddress": msg.MacAddress,
527 "Pkt": hex.EncodeToString(msg.Packet.Data()),
528 "OnuSn": o.Sn(),
529 }).Trace("No uni to forward msg coming to multicast gemport")
530 }
531 for _, uni := range unis {
532 uni.PacketCh <- msg
533 }
534 } else {
535 uni, err := o.findUniByPortNo(msg.PortNo)
536 if err != nil {
537 onuLogger.WithFields(log.Fields{
538 "IntfId": msg.IntfId,
539 "OnuId": msg.OnuId,
540 "pktType": msg.Type,
541 "portNo": msg.PortNo,
542 "MacAddress": msg.MacAddress,
543 "Pkt": hex.EncodeToString(msg.Packet.Data()),
544 "OnuSn": o.Sn(),
545 }).Error("Cannot find Uni associated with packet")
546 continue
547 }
548 uni.PacketCh <- msg
David Bainbridge103cf022019-12-16 20:11:35 +0000549 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700550 // BBR specific messages
Matteo Scandolof9d43412021-01-12 11:11:34 -0800551 case bbsim.OnuPacketIn:
David Bainbridge103cf022019-12-16 20:11:35 +0000552 // NOTE we only receive BBR packets here.
553 // Eapol.HandleNextPacket can handle both BBSim and BBr cases so the call is the same
554 // 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 -0800555 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000556
Matteo Scandolo8a574812021-05-20 15:18:53 -0700557 onuLogger.WithFields(log.Fields{
558 "IntfId": msg.IntfId,
559 "OnuId": msg.OnuId,
560 "PortNo": msg.PortNo,
561 "GemPortId": msg.GemPortId,
562 "pktType": msg.Type,
David Bainbridge103cf022019-12-16 20:11:35 +0000563 }).Trace("Received OnuPacketIn Message")
564
Matteo Scandolo8a574812021-05-20 15:18:53 -0700565 uni, err := o.findUniByPortNo(msg.PortNo)
566 if err != nil {
567 onuLogger.WithFields(log.Fields{
568 "IntfId": msg.IntfId,
569 "OnuId": msg.OnuId,
570 "PortNo": msg.PortNo,
571 "GemPortId": msg.GemPortId,
572 "pktType": msg.Type,
573 }).Error(err.Error())
574 }
575
576 // BBR has one service and one UNI
577 serviceId := uint32(0)
578 oltId := 0
David Bainbridge103cf022019-12-16 20:11:35 +0000579 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700580 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 +0000581 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700582 _ = dhcp.HandleNextBbrPacket(o.ID, o.PonPortID, o.Sn(), o.DoneChannel, msg.Packet, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000583 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800584 case bbsim.OmciIndication:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800585 // these are OMCI messages received by BBR (VOLTHA emulator)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800586 msg, _ := message.Data.(bbsim.OmciIndicationMessage)
587 o.handleOmciResponse(msg, client)
588 case bbsim.SendEapolFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000589 o.sendEapolFlow(client)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800590 case bbsim.SendDhcpFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000591 o.sendDhcpFlow(client)
592 default:
593 onuLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700594 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700595 }
596 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700597}
598
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800599func NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700600 sn := new(openolt.SerialNumber)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700601 sn.VendorId = []byte("BBSM")
602 sn.VendorSpecific = []byte{0, byte(oltid % 256), byte(intfid), byte(onuid)}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700603 return sn
604}
605
Matteo Scandolof9d43412021-01-12 11:11:34 -0800606func (o *Onu) sendOnuDiscIndication(msg bbsim.OnuDiscIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700607 discoverData := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800608 IntfId: o.PonPortID,
609 SerialNumber: o.SerialNumber,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700610 }}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700611
Matteo Scandolo4747d292019-08-05 11:50:18 -0700612 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700613 log.Errorf("Failed to send Indication_OnuDiscInd: %v", err)
Matteo Scandolo99f18462019-10-28 14:14:28 -0700614 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700615 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700616
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700617 onuLogger.WithFields(log.Fields{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800618 "IntfId": o.PonPortID,
619 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700620 "OnuId": o.ID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700621 }).Debug("Sent Indication_OnuDiscInd")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800622 publishEvent("ONU-discovery-indication-sent", int32(o.PonPortID), int32(o.ID), o.Sn())
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800623
624 // after DiscoveryRetryDelay check if the state is the same and in case send a new OnuDiscIndication
625 go func(delay time.Duration) {
Matteo Scandolo569e7172019-12-20 11:51:51 -0800626 time.Sleep(delay)
Matteo Scandolocedde462021-03-09 17:37:16 -0800627 if o.InternalState.Current() == OnuStateDiscovered {
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800628 o.sendOnuDiscIndication(msg, stream)
629 }
630 }(o.DiscoveryRetryDelay)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700631}
632
Matteo Scandolof9d43412021-01-12 11:11:34 -0800633func (o *Onu) sendOnuIndication(msg bbsim.OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800634 // NOTE the ONU ID is set by VOLTHA in the ActivateOnu call (via openolt.proto)
635 // and stored in the Onu struct via onu.SetID
Matteo Scandolo4747d292019-08-05 11:50:18 -0700636
637 indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700638 IntfId: o.PonPortID,
639 OnuId: o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700640 OperState: msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700641 AdminState: o.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700642 SerialNumber: o.SerialNumber,
643 }}
644 if err := stream.Send(&openolt.Indication{Data: indData}); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800645 // NOTE do we need to transition to a broken state?
Matteo Scandolo11006992019-08-28 11:29:46 -0700646 log.Errorf("Failed to send Indication_OnuInd: %v", err)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700647 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700648 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700649 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800650 "IntfId": o.PonPortID,
651 "OnuId": o.ID,
652 "VolthaOnuId": msg.OnuID,
653 "OperState": msg.OperState.String(),
654 "AdminState": msg.OperState.String(),
655 "OnuSn": o.Sn(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700656 }).Debug("Sent Indication_OnuInd")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700657
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700658}
659
Matteo Scandolof9d43412021-01-12 11:11:34 -0800660func (o *Onu) HandleShutdownONU() error {
661
662 dyingGasp := pb.ONUAlarmRequest{
663 AlarmType: "DYING_GASP",
664 SerialNumber: o.Sn(),
665 Status: "on",
666 }
667
668 if err := alarmsim.SimulateOnuAlarm(&dyingGasp, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
669 onuLogger.WithFields(log.Fields{
670 "OnuId": o.ID,
671 "IntfId": o.PonPortID,
672 "OnuSn": o.Sn(),
673 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
674 return err
675 }
676
677 losReq := pb.ONUAlarmRequest{
678 AlarmType: "ONU_ALARM_LOS",
679 SerialNumber: o.Sn(),
680 Status: "on",
681 }
682
683 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
684 onuLogger.WithFields(log.Fields{
685 "OnuId": o.ID,
686 "IntfId": o.PonPortID,
687 "OnuSn": o.Sn(),
688 }).Errorf("Cannot send LOS: %s", err.Error())
689
690 return err
691 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530692 o.SendOMCIAlarmNotificationMsg(true, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800693 // TODO if it's the last ONU on the PON, then send a PON LOS
694
Matteo Scandolocedde462021-03-09 17:37:16 -0800695 if err := o.InternalState.Event(OnuTxDisable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800696 onuLogger.WithFields(log.Fields{
697 "OnuId": o.ID,
698 "IntfId": o.PonPortID,
699 "OnuSn": o.Sn(),
700 }).Errorf("Cannot shutdown ONU: %s", err.Error())
701 return err
702 }
703
704 return nil
705}
706
707func (o *Onu) HandlePowerOnONU() error {
708 intitalState := o.InternalState.Current()
709
710 // initialize the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800711 if intitalState == OnuStateCreated || intitalState == OnuStateDisabled {
712 if err := o.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800713 onuLogger.WithFields(log.Fields{
714 "OnuId": o.ID,
715 "IntfId": o.PonPortID,
716 "OnuSn": o.Sn(),
717 }).Errorf("Cannot poweron ONU: %s", err.Error())
718 return err
719 }
720 }
721
722 // turn off the LOS Alarm
723 losReq := pb.ONUAlarmRequest{
724 AlarmType: "ONU_ALARM_LOS",
725 SerialNumber: o.Sn(),
726 Status: "off",
727 }
728
729 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
730 onuLogger.WithFields(log.Fields{
731 "OnuId": o.ID,
732 "IntfId": o.PonPortID,
733 "OnuSn": o.Sn(),
734 }).Errorf("Cannot send LOS: %s", err.Error())
735 return err
736 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530737 o.SendOMCIAlarmNotificationMsg(false, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800738
739 // Send a ONU Discovery indication
Matteo Scandolocedde462021-03-09 17:37:16 -0800740 if err := o.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800741 onuLogger.WithFields(log.Fields{
742 "OnuId": o.ID,
743 "IntfId": o.PonPortID,
744 "OnuSn": o.Sn(),
745 }).Errorf("Cannot poweron ONU: %s", err.Error())
746 return err
747 }
748
749 // move o directly to enable state only when its a powercycle case
750 // in case of first time o poweron o will be moved to enable on
751 // receiving ActivateOnu request from openolt adapter
Matteo Scandolocedde462021-03-09 17:37:16 -0800752 if intitalState == OnuStateDisabled {
753 if err := o.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800754 onuLogger.WithFields(log.Fields{
755 "OnuId": o.ID,
756 "IntfId": o.PonPortID,
757 "OnuSn": o.Sn(),
758 }).Errorf("Cannot enable ONU: %s", err.Error())
759 return err
760 }
761 }
762
763 return nil
764}
765
766func (o *Onu) SetAlarm(alarmType string, status string) error {
767 alarmReq := pb.ONUAlarmRequest{
768 AlarmType: alarmType,
769 SerialNumber: o.Sn(),
770 Status: status,
771 }
772
773 err := alarmsim.SimulateOnuAlarm(&alarmReq, o.ID, o.PonPortID, o.PonPort.Olt.channel)
774 if err != nil {
775 return err
776 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530777 raiseAlarm := false
778 if alarmReq.Status == "on" {
779 raiseAlarm = true
780 }
781 o.SendOMCIAlarmNotificationMsg(raiseAlarm, alarmReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800782 return nil
783}
784
785func (o *Onu) publishOmciEvent(msg bbsim.OmciMessage) {
Pragya Arya324337e2020-02-20 14:35:08 +0530786 if olt.PublishEvents {
Matteo Scandolob5913142021-03-19 16:10:18 -0700787 _, omciMsg, err := omcilib.ParseOpenOltOmciPacket(msg.OmciPkt.Data())
Pragya Arya324337e2020-02-20 14:35:08 +0530788 if err != nil {
789 log.Errorf("error in getting msgType %v", err)
790 return
791 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800792 if omciMsg.MessageType == omci.MibUploadRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530793 o.seqNumber = 0
794 publishEvent("MIB-upload-received", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
Matteo Scandolof9d43412021-01-12 11:11:34 -0800795 } else if omciMsg.MessageType == omci.MibUploadNextRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530796 o.seqNumber++
797 if o.seqNumber > 290 {
798 publishEvent("MIB-upload-done", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
799 }
800 }
801 }
802}
803
Matteo Scandolof9d43412021-01-12 11:11:34 -0800804// handleOmciRequest is responsible to parse the OMCI packets received from the openolt adapter
805// and generate the appropriate response to it
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200806func (o *Onu) handleOmciRequest(msg bbsim.OmciMessage, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800807
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700808 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700809 "omciMsgType": msg.OmciMsg.MessageType,
810 "transCorrId": strconv.FormatInt(int64(msg.OmciMsg.TransactionID), 16),
811 "DeviceIdent": msg.OmciMsg.DeviceIdentifier,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700812 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -0700813 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -0800814 }).Trace("omci-message-decoded")
815
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000816 if o.OmciMsgCounter < maxOmciMsgCounter {
817 o.OmciMsgCounter++
818 } else {
819 o.OmciMsgCounter = 1
820 }
821 if o.OmciMsgCounter > o.OmciResponseRate {
822 onuLogger.WithFields(log.Fields{
823 "OmciMsgCounter": o.OmciMsgCounter,
824 "OmciResponseRate": o.OmciResponseRate,
825 "omciMsgType": msg.OmciMsg.MessageType,
Matteo Scandoloa96e2242021-09-28 10:13:17 -0700826 "txId": msg.OmciMsg.TransactionID,
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200827 }).Debug("skipping-omci-msg-response")
828 return fmt.Errorf("skipping-omci-msg-response-because-of-response-rate-%d", o.OmciResponseRate)
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000829 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800830 var responsePkt []byte
Girish Gowdrae2683102021-03-05 08:24:26 -0800831 var errResp error
Matteo Scandolob5913142021-03-19 16:10:18 -0700832 switch msg.OmciMsg.MessageType {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800833 case omci.MibResetRequestType:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800834 onuLogger.WithFields(log.Fields{
835 "IntfId": o.PonPortID,
836 "OnuId": o.ID,
837 "SerialNumber": o.Sn(),
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700838 }).Debug("received-mib-reset-request")
Matteo Scandolob5913142021-03-19 16:10:18 -0700839 if responsePkt, errResp = omcilib.CreateMibResetResponse(msg.OmciMsg.TransactionID); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800840 o.MibDataSync = 0
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700841
842 // if the MIB reset is successful then remove all the stored AllocIds and GemPorts
Girish Gowdra574834a2022-02-04 15:15:15 -0800843 o.PonPort.removeAllocIdsForOnuSn(o.SerialNumber)
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700844 o.PonPort.removeGemPortBySn(o.SerialNumber)
Girish Gowdrae2683102021-03-05 08:24:26 -0800845 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800846 case omci.MibUploadRequestType:
Holger Hildebrandt236e3742022-05-04 14:07:27 +0000847 responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg, o.MibDb)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800848 case omci.MibUploadNextRequestType:
Holger Hildebrandt236e3742022-05-04 14:07:27 +0000849 responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDb)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800850 case omci.GetRequestType:
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700851 onuDown := o.AdminLockState == 1
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700852 responsePkt, _ = omcilib.CreateGetResponse(msg.OmciPkt, msg.OmciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId,
853 o.CommittedImageEntityId, o.StandbyImageVersion, o.ActiveImageVersion, o.CommittedImageVersion, onuDown)
Himani Chawla908a1f52022-01-27 14:39:44 +0530854
Matteo Scandolof9d43412021-01-12 11:11:34 -0800855 case omci.SetRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800856 success := true
Matteo Scandolob5913142021-03-19 16:10:18 -0700857 msgObj, _ := omcilib.ParseSetRequest(msg.OmciPkt)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800858 switch msgObj.EntityClass {
859 case me.PhysicalPathTerminationPointEthernetUniClassID:
860 // if we're Setting a PPTP state
Matteo Scandolo8a574812021-05-20 15:18:53 -0700861 // we need to send the appropriate alarm (handled in the UNI struct)
862 uni, err := o.FindUniByEntityId(msgObj.EntityInstance)
863 if err != nil {
864 onuLogger.Error(err)
865 success = false
866 } else {
867 // 1 locks the UNI, 0 unlocks it
Elia Battiston9bfe1102022-02-03 10:38:03 +0100868 adminState := msgObj.Attributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState].(uint8)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700869 var err error
Himani Chawla13b1ee02021-03-15 01:43:53 +0530870 if adminState == 1 {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700871 err = uni.Disable()
Girish Gowdra996d81e2021-04-21 16:16:27 -0700872 } else {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700873 err = uni.Enable()
Himani Chawla13b1ee02021-03-15 01:43:53 +0530874 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700875 if err != nil {
876 onuLogger.WithFields(log.Fields{
877 "IntfId": o.PonPortID,
878 "OnuId": o.ID,
879 "UniMeId": uni.MeId,
880 "UniId": uni.ID,
881 "SerialNumber": o.Sn(),
882 "Err": err.Error(),
883 }).Warn("cannot-change-uni-status")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800884 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800885 }
Elia Battistonac63b112022-01-12 18:40:49 +0100886 case me.PhysicalPathTerminationPointPotsUniClassID:
887 // if we're Setting a PPTP state
888 // we need to send the appropriate alarm (handled in the POTS struct)
889 pots, err := o.FindPotsByEntityId(msgObj.EntityInstance)
890 if err != nil {
891 onuLogger.Error(err)
892 success = false
893 } else {
894 // 1 locks the UNI, 0 unlocks it
Elia Battiston9bfe1102022-02-03 10:38:03 +0100895 adminState := msgObj.Attributes[me.PhysicalPathTerminationPointPotsUni_AdministrativeState].(uint8)
Elia Battistonac63b112022-01-12 18:40:49 +0100896 var err error
897 if adminState == 1 {
898 err = pots.Disable()
899 } else {
900 err = pots.Enable()
901 }
902 if err != nil {
903 onuLogger.WithFields(log.Fields{
904 "IntfId": o.PonPortID,
905 "OnuId": o.ID,
906 "PotsMeId": pots.MeId,
907 "PotsId": pots.ID,
908 "SerialNumber": o.Sn(),
909 "Err": err.Error(),
910 }).Warn("cannot-change-pots-status")
911 }
912 }
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700913 case me.OnuGClassID:
Elia Battiston9bfe1102022-02-03 10:38:03 +0100914 o.AdminLockState = msgObj.Attributes[me.OnuG_AdministrativeState].(uint8)
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700915 onuLogger.WithFields(log.Fields{
916 "IntfId": o.PonPortID,
917 "OnuId": o.ID,
918 "SerialNumber": o.Sn(),
919 "AdminLockState": o.AdminLockState,
920 }).Debug("set-onu-admin-lock-state")
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800921 case me.TContClassID:
Elia Battiston9bfe1102022-02-03 10:38:03 +0100922 allocId := msgObj.Attributes[me.TCont_AllocId].(uint16)
Girish Gowdra574834a2022-02-04 15:15:15 -0800923 entityID := msgObj.Attributes["ManagedEntityId"].(uint16)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800924
925 // if the AllocId is 255 (0xFF) or 65535 (0xFFFF) it means we are removing it,
926 // otherwise we are adding it
927 if allocId == 255 || allocId == 65535 {
928 onuLogger.WithFields(log.Fields{
929 "IntfId": o.PonPortID,
930 "OnuId": o.ID,
931 "TContId": msgObj.EntityInstance,
932 "AllocId": allocId,
933 "SerialNumber": o.Sn(),
934 }).Trace("freeing-alloc-id-via-omci")
Girish Gowdra574834a2022-02-04 15:15:15 -0800935 o.PonPort.removeAllocId(o.PonPortID, o.ID, entityID)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800936 } else {
Girish Gowdra574834a2022-02-04 15:15:15 -0800937 if used, allocObj := o.PonPort.isAllocIdAllocated(o.PonPortID, o.ID, entityID); used {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800938 onuLogger.WithFields(log.Fields{
939 "IntfId": o.PonPortID,
940 "OnuId": o.ID,
941 "AllocId": allocId,
942 "SerialNumber": o.Sn(),
Girish Gowdra574834a2022-02-04 15:15:15 -0800943 }).Errorf("allocid-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(allocObj.OnuSn))
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800944 success = false
945 } else {
946 onuLogger.WithFields(log.Fields{
947 "IntfId": o.PonPortID,
948 "OnuId": o.ID,
949 "TContId": msgObj.EntityInstance,
950 "AllocId": allocId,
951 "SerialNumber": o.Sn(),
952 }).Trace("storing-alloc-id-via-omci")
Girish Gowdra574834a2022-02-04 15:15:15 -0800953 o.PonPort.storeAllocId(o.PonPortID, o.ID, entityID, allocId, o.SerialNumber)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800954 }
955 }
Himani Chawla908a1f52022-01-27 14:39:44 +0530956 case me.EthernetFrameExtendedPmClassID,
957 me.EthernetFrameExtendedPm64BitClassID:
958 onuLogger.WithFields(log.Fields{
959 "me-instance": msgObj.EntityInstance,
960 }).Debug("set-request-received")
961 // No need to reset counters as onu adapter will simply send the set control block request to actually reset
962 // the counters, and respond with 0's without sending the get request to device.
963 // Also, if we even reset the counters here in cache, then on get we need to restore the counters back which
964 // would be of no use as ultimately the counters need to be restored.
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800965 }
966
967 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -0700968 if responsePkt, errResp = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800969 o.MibDataSync++
970 }
971 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700972 responsePkt, _ = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.AttributeFailure)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800973 }
974 case omci.CreateRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800975 // check for GemPortNetworkCtp and make sure there are no duplicates on the same PON
976 var used bool
977 var sn *openolt.SerialNumber
Matteo Scandolob5913142021-03-19 16:10:18 -0700978 msgObj, err := omcilib.ParseCreateRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800979 if err == nil {
980 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
Matteo Scandolo973b0182021-04-08 11:24:42 -0700981 // GemPort 4069 is reserved for multicast and shared across ONUs
982 if msgObj.EntityInstance != 4069 {
983 if used, sn = o.PonPort.isGemPortAllocated(msgObj.EntityInstance); used {
984 onuLogger.WithFields(log.Fields{
985 "IntfId": o.PonPortID,
986 "OnuId": o.ID,
987 "GemPortId": msgObj.EntityInstance,
988 "SerialNumber": o.Sn(),
989 }).Errorf("gemport-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
990 } else {
991 onuLogger.WithFields(log.Fields{
992 "IntfId": o.PonPortID,
993 "OnuId": o.ID,
994 "GemPortId": msgObj.EntityInstance,
995 "SerialNumber": o.Sn(),
996 }).Trace("storing-gem-port-id-via-omci")
997 o.PonPort.storeGemPort(msgObj.EntityInstance, o.SerialNumber)
998 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800999 }
1000 }
1001 }
1002
1003 // if the gemPort is valid then increment the MDS and return a successful response
1004 // otherwise fail the request
1005 // for now the CreateRequeste for the gemPort is the only one that can fail, if we start supporting multiple
1006 // validation this check will need to be rewritten
1007 if !used {
Matteo Scandolob5913142021-03-19 16:10:18 -07001008 if responsePkt, errResp = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001009 o.MibDataSync++
1010 }
1011 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -07001012 responsePkt, _ = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError)
Girish Gowdrae2683102021-03-05 08:24:26 -08001013 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001014 case omci.DeleteRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001015 msgObj, err := omcilib.ParseDeleteRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001016 if err == nil {
1017 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
1018 onuLogger.WithFields(log.Fields{
1019 "IntfId": o.PonPortID,
1020 "OnuId": o.ID,
1021 "GemPortId": msgObj.EntityInstance,
1022 "SerialNumber": o.Sn(),
1023 }).Trace("freeing-gem-port-id-via-omci")
1024 o.PonPort.removeGemPort(msgObj.EntityInstance)
1025 }
1026 }
1027
Matteo Scandolob5913142021-03-19 16:10:18 -07001028 if responsePkt, errResp = omcilib.CreateDeleteResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -08001029 o.MibDataSync++
1030 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001031 case omci.RebootRequestType:
1032
Matteo Scandolob5913142021-03-19 16:10:18 -07001033 responsePkt, _ = omcilib.CreateRebootResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolof9d43412021-01-12 11:11:34 -08001034
1035 // powercycle the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -08001036 // we run this in a separate goroutine so that
1037 // the RebootRequestResponse is sent to VOLTHA
Matteo Scandolof9d43412021-01-12 11:11:34 -08001038 go func() {
Matteo Scandolocedde462021-03-09 17:37:16 -08001039 if err := o.Reboot(10 * time.Second); err != nil {
1040 log.WithFields(log.Fields{
1041 "IntfId": o.PonPortID,
1042 "OnuId": o.ID,
1043 "SerialNumber": o.Sn(),
1044 "err": err,
1045 }).Error("cannot-reboot-onu-after-omci-reboot-request")
1046 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001047 }()
1048 case omci.TestRequestType:
Girish Gowdra161d27a2021-05-05 12:01:44 -07001049 var classID me.ClassID
1050 var omciResult me.Results
1051 var instID uint16
1052 responsePkt, errResp, classID, instID, omciResult = omcilib.CreateTestResponse(msg.OmciPkt, msg.OmciMsg)
1053 // Send TestResult only in case the TestResponse omci result code is me.Success
1054 if responsePkt != nil && errResp == nil && omciResult == me.Success {
1055 if testResultPkt, err := omcilib.CreateTestResult(classID, instID, msg.OmciMsg.TransactionID); err == nil {
1056 // send test results asynchronously
1057 go func() {
1058 // Send test results after a second to emulate async behavior
1059 time.Sleep(1 * time.Second)
1060 if testResultPkt != nil {
1061 if err := o.sendOmciIndication(testResultPkt, msg.OmciMsg.TransactionID, stream); err != nil {
1062 onuLogger.WithFields(log.Fields{
1063 "IntfId": o.PonPortID,
1064 "SerialNumber": o.Sn(),
1065 "omciPacket": testResultPkt,
1066 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1067 "transCorrId": msg.OmciMsg.TransactionID,
1068 }).Errorf("failed-to-send-omci-message: %v", err)
1069 }
1070 }
1071 }()
Matteo Scandolof9d43412021-01-12 11:11:34 -08001072 }
1073 }
Girish Gowdraa539f522021-02-15 23:00:45 -08001074 case omci.SynchronizeTimeRequestType:
1075 // MDS counter increment is not required for this message type
Matteo Scandolob5913142021-03-19 16:10:18 -07001076 responsePkt, _ = omcilib.CreateSyncTimeResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolocedde462021-03-09 17:37:16 -08001077 case omci.StartSoftwareDownloadRequestType:
1078
1079 o.ImageSoftwareReceivedSections = 0
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301080 o.ImageSectionData = []byte{}
Matteo Scandolob5913142021-03-19 16:10:18 -07001081 o.ImageSoftwareExpectedSections = omcilib.ComputeDownloadSectionsCount(msg.OmciPkt)
Matteo Scandolocedde462021-03-09 17:37:16 -08001082
Matteo Scandolob5913142021-03-19 16:10:18 -07001083 if responsePkt, errResp = omcilib.CreateStartSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001084 o.MibDataSync++
1085 if err := o.InternalState.Event(OnuTxStartImageDownload); err != nil {
1086 onuLogger.WithFields(log.Fields{
1087 "OnuId": o.ID,
1088 "IntfId": o.PonPortID,
1089 "OnuSn": o.Sn(),
1090 "Err": err.Error(),
1091 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadStarted)
1092 }
1093 } else {
1094 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001095 "OmciMsgType": msg.OmciMsg.MessageType,
1096 "TransCorrId": msg.OmciMsg.TransactionID,
1097 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001098 "IntfId": o.PonPortID,
1099 "SerialNumber": o.Sn(),
1100 }).Error("error-while-processing-start-software-download-request")
1101 }
1102 case omci.DownloadSectionRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001103 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001104 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001105 "OmciMsgType": msg.OmciMsg.MessageType,
1106 "TransCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001107 "EntityInstance": msgObj.EntityInstance,
1108 "SectionNumber": msgObj.SectionNumber,
1109 "SectionData": msgObj.SectionData,
1110 }).Trace("received-download-section-request")
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001111 //Extracting the first 14 bytes to use as a version for this image.
1112 if o.ImageSoftwareReceivedSections == 0 {
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001113 o.InDownloadImageVersion = string(msgObj.SectionData[0:14])
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001114 }
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301115 o.ImageSectionData = append(o.ImageSectionData, msgObj.SectionData...)
Matteo Scandolocedde462021-03-09 17:37:16 -08001116 o.ImageSoftwareReceivedSections++
1117 if o.InternalState.Current() != OnuStateImageDownloadInProgress {
1118 if err := o.InternalState.Event(OnuTxProgressImageDownload); err != nil {
1119 onuLogger.WithFields(log.Fields{
1120 "OnuId": o.ID,
1121 "IntfId": o.PonPortID,
1122 "OnuSn": o.Sn(),
1123 "Err": err.Error(),
1124 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadInProgress)
1125 }
1126 }
1127 }
1128 case omci.DownloadSectionRequestWithResponseType:
1129 // NOTE we only need to respond if an ACK is requested
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301130 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001131 onuLogger.WithFields(log.Fields{
Himani Chawla4ff5fab2021-11-09 19:19:29 +05301132 "OmciMsgType": msg.OmciMsg.MessageType,
1133 "TransCorrId": msg.OmciMsg.TransactionID,
1134 "EntityInstance": msgObj.EntityInstance,
1135 "SectionNumber": msgObj.SectionNumber,
1136 "SectionData": msgObj.SectionData,
1137 }).Trace("received-download-section-request-with-response-type")
1138 o.ImageSectionData = append(o.ImageSectionData, msgObj.SectionData...)
1139 responsePkt, errResp = omcilib.CreateDownloadSectionResponse(msg.OmciPkt, msg.OmciMsg)
1140
1141 if errResp != nil {
1142 onuLogger.WithFields(log.Fields{
1143 "OmciMsgType": msg.OmciMsg.MessageType,
1144 "TransCorrId": msg.OmciMsg.TransactionID,
1145 "Err": errResp.Error(),
1146 "IntfId": o.PonPortID,
1147 "SerialNumber": o.Sn(),
1148 }).Error("error-while-processing-create-download-section-response")
1149 return fmt.Errorf("error-while-processing-create-download-section-response: %s", errResp.Error())
1150 }
1151 o.ImageSoftwareReceivedSections++
Matteo Scandolocedde462021-03-09 17:37:16 -08001152 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001153 case omci.EndSoftwareDownloadRequestType:
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001154 success := o.handleEndSoftwareDownloadRequest(msg)
Matteo Scandolocedde462021-03-09 17:37:16 -08001155
Matteo Scandolocedde462021-03-09 17:37:16 -08001156 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -07001157 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001158 o.MibDataSync++
1159 if err := o.InternalState.Event(OnuTxCompleteImageDownload); 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", OnuStateImageDownloadComplete)
1166 }
1167 } else {
1168 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001169 "OmciMsgType": msg.OmciMsg.MessageType,
1170 "TransCorrId": msg.OmciMsg.TransactionID,
1171 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001172 "IntfId": o.PonPortID,
1173 "SerialNumber": o.Sn(),
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001174 }).Error("error-while-responding-to-end-software-download-request")
Matteo Scandolocedde462021-03-09 17:37:16 -08001175 }
1176 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -07001177 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001178 if err := o.InternalState.Event(OnuTxFailImageDownload); err != nil {
1179 onuLogger.WithFields(log.Fields{
1180 "OnuId": o.ID,
1181 "IntfId": o.PonPortID,
1182 "OnuSn": o.Sn(),
1183 "Err": err.Error(),
1184 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadError)
1185 }
1186 }
1187 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001188 case omci.ActivateSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001189 if responsePkt, errResp = omcilib.CreateActivateSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001190 o.MibDataSync++
1191 if err := o.InternalState.Event(OnuTxActivateImage); err != nil {
1192 onuLogger.WithFields(log.Fields{
1193 "OnuId": o.ID,
1194 "IntfId": o.PonPortID,
1195 "OnuSn": o.Sn(),
1196 "Err": err.Error(),
1197 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageActivated)
1198 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001199 if msgObj, err := omcilib.ParseActivateSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001200 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001201 previousActiveImage := o.ActiveImageVersion
1202 o.ActiveImageVersion = o.StandbyImageVersion
1203 o.StandbyImageVersion = previousActiveImage
Matteo Scandolocedde462021-03-09 17:37:16 -08001204 } else {
1205 onuLogger.Errorf("something-went-wrong-while-activating: %s", err)
1206 }
1207 onuLogger.WithFields(log.Fields{
1208 "OnuId": o.ID,
1209 "IntfId": o.PonPortID,
1210 "OnuSn": o.Sn(),
1211 "ActiveImageEntityId": o.ActiveImageEntityId,
1212 "CommittedImageEntityId": o.CommittedImageEntityId,
1213 }).Info("onu-software-image-activated")
1214
1215 // powercycle the ONU
1216 // we run this in a separate goroutine so that
1217 // the ActivateSoftwareResponse is sent to VOLTHA
1218 // NOTE do we need to wait before rebooting?
1219 go func() {
1220 if err := o.Reboot(10 * time.Second); err != nil {
1221 log.WithFields(log.Fields{
1222 "IntfId": o.PonPortID,
1223 "OnuId": o.ID,
1224 "SerialNumber": o.Sn(),
1225 "err": err,
1226 }).Error("cannot-reboot-onu-after-omci-activate-software-request")
1227 }
1228 }()
1229 }
1230 case omci.CommitSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001231 if responsePkt, errResp = omcilib.CreateCommitSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001232 o.MibDataSync++
Matteo Scandolob5913142021-03-19 16:10:18 -07001233 if msgObj, err := omcilib.ParseCommitSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001234 // TODO validate that the image to commit is:
1235 // - active
1236 // - not already committed
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001237 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandolocedde462021-03-09 17:37:16 -08001238 o.CommittedImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001239 //committed becomes standby
1240 o.StandbyImageVersion = o.CommittedImageVersion
1241 o.CommittedImageVersion = o.ActiveImageVersion
Matteo Scandolocedde462021-03-09 17:37:16 -08001242 } else {
1243 onuLogger.Errorf("something-went-wrong-while-committing: %s", err)
1244 }
1245 if err := o.InternalState.Event(OnuTxCommitImage); err != nil {
1246 onuLogger.WithFields(log.Fields{
1247 "OnuId": o.ID,
1248 "IntfId": o.PonPortID,
1249 "OnuSn": o.Sn(),
1250 "Err": err.Error(),
1251 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageCommitted)
1252 }
1253 onuLogger.WithFields(log.Fields{
1254 "OnuId": o.ID,
1255 "IntfId": o.PonPortID,
1256 "OnuSn": o.Sn(),
1257 "ActiveImageEntityId": o.ActiveImageEntityId,
1258 "CommittedImageEntityId": o.CommittedImageEntityId,
1259 }).Info("onu-software-image-committed")
1260 }
Himani Chawla13b1ee02021-03-15 01:43:53 +05301261 case omci.GetAllAlarmsRequestType:
1262 // Reset the alarm sequence number on receiving get all alarms request.
1263 o.onuAlarmsInfoLock.Lock()
1264 for key, alarmInfo := range o.onuAlarmsInfo {
1265 // reset the alarm sequence no
1266 alarmInfo.SequenceNo = 0
1267 o.onuAlarmsInfo[key] = alarmInfo
1268 }
1269 o.onuAlarmsInfoLock.Unlock()
Holger Hildebrandt24d27422022-07-11 05:50:02 +00001270 responsePkt, _ = omcilib.CreateGetAllAlarmsResponse(msg.OmciMsg, o.onuAlarmsInfo)
Himani Chawla13b1ee02021-03-15 01:43:53 +05301271 case omci.GetAllAlarmsNextRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001272 if responsePkt, errResp = omcilib.CreateGetAllAlarmsNextResponse(msg.OmciPkt, msg.OmciMsg, o.onuAlarmsInfo); errResp != nil {
Himani Chawla13b1ee02021-03-15 01:43:53 +05301273 responsePkt = nil //Do not send any response for error case
1274 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001275 default:
Matteo Scandolocedde462021-03-09 17:37:16 -08001276 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001277 "omciBytes": hex.EncodeToString(msg.OmciPkt.Data()),
1278 "omciPkt": msg.OmciPkt,
1279 "omciMsgType": msg.OmciMsg.MessageType,
1280 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001281 "IntfId": o.PonPortID,
1282 "SerialNumber": o.Sn(),
1283 }).Warnf("OMCI-message-not-supported")
1284 }
1285
1286 if responsePkt != nil {
Matteo Scandolob5913142021-03-19 16:10:18 -07001287 if err := o.sendOmciIndication(responsePkt, msg.OmciMsg.TransactionID, stream); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001288 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001289 "IntfId": o.PonPortID,
1290 "SerialNumber": o.Sn(),
1291 "omciPacket": responsePkt,
1292 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1293 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001294 }).Errorf("failed-to-send-omci-message: %v", err)
1295 }
1296 }
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001297
Pragya Arya324337e2020-02-20 14:35:08 +05301298 o.publishOmciEvent(msg)
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +02001299 return nil
Matteo Scandolof9d43412021-01-12 11:11:34 -08001300}
Pragya Arya324337e2020-02-20 14:35:08 +05301301
Matteo Scandolof9d43412021-01-12 11:11:34 -08001302// sendOmciIndication takes an OMCI packet and sends it up to VOLTHA
1303func (o *Onu) sendOmciIndication(responsePkt []byte, txId uint16, stream bbsim.Stream) error {
1304 indication := &openolt.Indication_OmciInd{
1305 OmciInd: &openolt.OmciIndication{
1306 IntfId: o.PonPortID,
1307 OnuId: o.ID,
1308 Pkt: responsePkt,
1309 },
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001310 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001311 if err := stream.Send(&openolt.Indication{Data: indication}); err != nil {
1312 return fmt.Errorf("failed-to-send-omci-message: %v", err)
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001313 }
1314 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001315 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -07001316 "SerialNumber": o.Sn(),
Holger Hildebrandt02101a62022-04-06 13:00:51 +00001317 "omciPacket": hex.EncodeToString(indication.OmciInd.Pkt),
Matteo Scandolof9d43412021-01-12 11:11:34 -08001318 "transCorrId": txId,
1319 }).Trace("omci-message-sent")
1320 return nil
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001321}
1322
Matteo Scandolo8a574812021-05-20 15:18:53 -07001323// FindUniById retrieves a UNI by ID
1324func (o *Onu) FindUniById(uniID uint32) (*UniPort, error) {
1325 for _, u := range o.UniPorts {
1326 uni := u.(*UniPort)
1327 if uni.ID == uniID {
1328 return uni, nil
1329 }
Matteo Scandolo27428702019-10-11 16:21:16 -07001330 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001331 return nil, fmt.Errorf("cannot-find-uni-with-id-%d-on-onu-%s", uniID, o.Sn())
1332}
1333
Elia Battistonac63b112022-01-12 18:40:49 +01001334// FindPotsById retrieves a POTS port by ID
1335func (o *Onu) FindPotsById(uniID uint32) (*PotsPort, error) {
1336 for _, p := range o.PotsPorts {
1337 pots := p.(*PotsPort)
1338 if pots.ID == uniID {
1339 return pots, nil
1340 }
1341 }
1342 return nil, fmt.Errorf("cannot-find-pots-with-id-%d-on-onu-%s", uniID, o.Sn())
1343}
1344
Matteo Scandolo8a574812021-05-20 15:18:53 -07001345// FindUniByEntityId retrieves a uni by MeID (the OMCI entity ID)
1346func (o *Onu) FindUniByEntityId(meId uint16) (*UniPort, error) {
1347 entityId := omcilib.EntityID{}.FromUint16(meId)
1348 for _, u := range o.UniPorts {
1349 uni := u.(*UniPort)
1350 if uni.MeId.Equals(entityId) {
1351 return uni, nil
1352 }
1353 }
1354 return nil, fmt.Errorf("cannot-find-uni-with-meid-%s-on-onu-%s", entityId.ToString(), o.Sn())
Matteo Scandolo27428702019-10-11 16:21:16 -07001355}
1356
Elia Battistonac63b112022-01-12 18:40:49 +01001357// FindPotsByEntityId retrieves a POTS uni by MeID (the OMCI entity ID)
1358func (o *Onu) FindPotsByEntityId(meId uint16) (*PotsPort, error) {
1359 entityId := omcilib.EntityID{}.FromUint16(meId)
1360 for _, p := range o.PotsPorts {
1361 pots := p.(*PotsPort)
1362 if pots.MeId.Equals(entityId) {
1363 return pots, nil
1364 }
1365 }
1366 return nil, fmt.Errorf("cannot-find-pots-with-meid-%s-on-onu-%s", entityId.ToString(), o.Sn())
1367}
1368
William Kurkian0418bc82019-11-06 12:16:24 -05001369func (o *Onu) SetID(id uint32) {
Matteo Scandolo583f17d2020-02-13 10:35:17 -08001370 onuLogger.WithFields(log.Fields{
1371 "IntfId": o.PonPortID,
1372 "OnuId": id,
1373 "SerialNumber": o.Sn(),
1374 }).Debug("Storing OnuId ")
William Kurkian0418bc82019-11-06 12:16:24 -05001375 o.ID = id
1376}
1377
Matteo Scandolof9d43412021-01-12 11:11:34 -08001378func (o *Onu) handleFlowAdd(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001379 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001380 "AllocId": msg.Flow.AllocId,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001381 "Cookie": msg.Flow.Cookie,
1382 "DstPort": msg.Flow.Classifier.DstPort,
1383 "FlowId": msg.Flow.FlowId,
1384 "FlowType": msg.Flow.FlowType,
1385 "GemportId": msg.Flow.GemportId,
1386 "InnerVlan": msg.Flow.Classifier.IVid,
1387 "IntfId": msg.Flow.AccessIntfId,
1388 "IpProto": msg.Flow.Classifier.IpProto,
1389 "OnuId": msg.Flow.OnuId,
1390 "OnuSn": o.Sn(),
1391 "OuterVlan": msg.Flow.Classifier.OVid,
1392 "PortNo": msg.Flow.PortNo,
1393 "SrcPort": msg.Flow.Classifier.SrcPort,
1394 "UniID": msg.Flow.UniId,
1395 "ClassifierEthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
1396 "ClassifierOPbits": msg.Flow.Classifier.OPbits,
1397 "ClassifierIVid": msg.Flow.Classifier.IVid,
1398 "ClassifierOVid": msg.Flow.Classifier.OVid,
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001399 "ReplicateFlow": msg.Flow.ReplicateFlow,
1400 "PbitToGemport": msg.Flow.PbitToGemport,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001401 }).Debug("OLT receives FlowAdd for ONU")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001402
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001403 o.FlowIds = append(o.FlowIds, msg.Flow.FlowId)
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001404
1405 var gemPortId uint32
1406 if msg.Flow.ReplicateFlow {
1407 // This means that the OLT should replicate the flow for each PBIT, for BBSim it's enough to use the
1408 // first available gemport (we only need to send one packet)
1409 // NOTE different TP may create different mapping between PBits and GemPorts, this may require some changes
1410 gemPortId = msg.Flow.PbitToGemport[0]
1411 } else {
1412 // if replicateFlows is false, then the flow is carrying the correct GemPortId
1413 gemPortId = uint32(msg.Flow.GemportId)
1414 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001415
1416 uni, err := o.FindUniById(uint32(msg.Flow.UniId))
1417 if err != nil {
1418 onuLogger.WithFields(log.Fields{
1419 "IntfId": o.PonPortID,
1420 "OnuId": o.ID,
1421 "UniId": msg.Flow.UniId,
1422 "PortNo": msg.Flow.PortNo,
1423 "SerialNumber": o.Sn(),
1424 "FlowId": msg.Flow.FlowId,
1425 "FlowType": msg.Flow.FlowType,
1426 }).Error("cannot-find-uni-port-for-flow")
1427 }
1428
1429 uni.addGemPortToService(gemPortId, msg.Flow.Classifier.EthType, msg.Flow.Classifier.OVid, msg.Flow.Classifier.IVid)
1430 uni.StorePortNo(msg.Flow.PortNo)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001431
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001432 if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
Elia Battistonda45f6e2022-02-24 11:12:16 +01001433 onuLogger.WithFields(log.Fields{
1434 "IntfId": o.PonPortID,
1435 "OnuId": o.ID,
1436 "UniId": msg.Flow.UniId,
1437 "PortNo": msg.Flow.PortNo,
1438 "SerialNumber": o.Sn(),
1439 "FlowId": msg.Flow.FlowId,
1440 }).Debug("EAPOL flow detected")
Matteo Scandolo8a574812021-05-20 15:18:53 -07001441 uni.HandleAuth()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001442 } else if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeIPv4) &&
1443 msg.Flow.Classifier.SrcPort == uint32(68) &&
Matteo Scandolobd875b32020-09-18 17:46:31 -07001444 msg.Flow.Classifier.DstPort == uint32(67) {
Elia Battistonda45f6e2022-02-24 11:12:16 +01001445 onuLogger.WithFields(log.Fields{
1446 "IntfId": o.PonPortID,
1447 "OnuId": o.ID,
1448 "UniId": msg.Flow.UniId,
1449 "PortNo": msg.Flow.PortNo,
1450 "SerialNumber": o.Sn(),
1451 "FlowId": msg.Flow.FlowId,
1452 "FlowType": msg.Flow.FlowType,
1453 }).Debug("DHCP flow detected")
Matteo Scandolo8a574812021-05-20 15:18:53 -07001454 uni.HandleDhcp(uint8(msg.Flow.Classifier.OPbits), int(msg.Flow.Classifier.OVid))
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001455 }
1456}
1457
Matteo Scandolof9d43412021-01-12 11:11:34 -08001458func (o *Onu) handleFlowRemove(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001459 onuLogger.WithFields(log.Fields{
1460 "IntfId": o.PonPortID,
1461 "OnuId": o.ID,
1462 "SerialNumber": o.Sn(),
1463 "FlowId": msg.Flow.FlowId,
1464 "FlowType": msg.Flow.FlowType,
1465 }).Debug("ONU receives FlowRemove")
1466
1467 for idx, flow := range o.FlowIds {
1468 // If the gemport is found, delete it from local cache.
1469 if flow == msg.Flow.FlowId {
1470 o.FlowIds = append(o.FlowIds[:idx], o.FlowIds[idx+1:]...)
1471 break
1472 }
1473 }
1474
1475 if len(o.FlowIds) == 0 {
1476 onuLogger.WithFields(log.Fields{
1477 "IntfId": o.PonPortID,
1478 "OnuId": o.ID,
1479 "SerialNumber": o.Sn(),
1480 }).Info("Resetting GemPort")
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001481
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301482 // check if ONU delete is performed and
1483 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolocedde462021-03-09 17:37:16 -08001484 if o.InternalState.Current() == OnuStateDisabled {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301485 close(o.Channel)
1486 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001487 }
1488}
1489
Matteo Scandolocedde462021-03-09 17:37:16 -08001490func (o *Onu) Reboot(timeout time.Duration) error {
1491 onuLogger.WithFields(log.Fields{
1492 "IntfId": o.PonPortID,
1493 "OnuId": o.ID,
1494 "SerialNumber": o.Sn(),
1495 }).Debug("shutting-down-onu")
1496 if err := o.HandleShutdownONU(); err != nil {
1497 return err
1498 }
1499 time.Sleep(timeout)
1500 onuLogger.WithFields(log.Fields{
1501 "IntfId": o.PonPortID,
1502 "OnuId": o.ID,
1503 "SerialNumber": o.Sn(),
1504 }).Debug("power-on-onu")
1505 if err := o.HandlePowerOnONU(); err != nil {
1506 return err
1507 }
1508 return nil
1509}
1510
Matteo Scandolo76f6b892021-11-15 16:13:06 -08001511// returns true if the request is successful, false otherwise
1512func (o *Onu) handleEndSoftwareDownloadRequest(msg bbsim.OmciMessage) bool {
1513 msgObj, err := omcilib.ParseEndSoftwareDownloadRequest(msg.OmciPkt)
1514 if err != nil {
1515 onuLogger.WithFields(log.Fields{
1516 "OmciMsgType": msg.OmciMsg.MessageType,
1517 "TransCorrId": msg.OmciMsg.TransactionID,
1518 "Err": err.Error(),
1519 "IntfId": o.PonPortID,
1520 "SerialNumber": o.Sn(),
1521 }).Error("error-while-processing-end-software-download-request")
1522 return false
1523 }
1524
1525 onuLogger.WithFields(log.Fields{
1526 "OnuId": o.ID,
1527 "IntfId": o.PonPortID,
1528 "OnuSn": o.Sn(),
1529 "msgObj": msgObj,
1530 }).Trace("EndSoftwareDownloadRequest received message")
1531
1532 // if the image download is ongoing and we receive a message with
1533 // ImageSize = 0 and Crc = 4294967295 (0xFFFFFFFF) respond with success
1534 if o.ImageSoftwareReceivedSections > 0 &&
1535 msgObj.ImageSize == 0 &&
1536 msgObj.CRC32 == 4294967295 {
1537 o.ImageSoftwareReceivedSections = 0
1538 // NOTE potentially we may want to add a ONU state to reflect
1539 // the software download abort
1540 return true
1541 }
1542
1543 // In the startSoftwareDownload we get the image size and the window size.
1544 // We calculate how many DownloadSection we should receive and validate
1545 // that we got the correct amount when we receive this message
1546 // If the received sections are different from the expected sections
1547 // respond with failure
1548 if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
1549 onuLogger.WithFields(log.Fields{
1550 "OnuId": o.ID,
1551 "IntfId": o.PonPortID,
1552 "OnuSn": o.Sn(),
1553 "ExpectedSections": o.ImageSoftwareExpectedSections,
1554 "ReceivedSections": o.ImageSoftwareReceivedSections,
1555 }).Errorf("onu-did-not-receive-all-image-sections")
1556 return false
1557 }
1558
1559 // check the received CRC vs the computed CRC
1560 computedCRC := crc32a.Checksum(o.ImageSectionData[:int(msgObj.ImageSize)])
1561 //Convert the crc to network byte order
1562 var byteSlice = make([]byte, 4)
1563 binary.LittleEndian.PutUint32(byteSlice, computedCRC)
1564 computedCRC = binary.BigEndian.Uint32(byteSlice)
1565 if msgObj.CRC32 != computedCRC {
1566 onuLogger.WithFields(log.Fields{
1567 "OnuId": o.ID,
1568 "IntfId": o.PonPortID,
1569 "OnuSn": o.Sn(),
1570 "ReceivedCRC": msgObj.CRC32,
1571 "CalculatedCRC": computedCRC,
1572 }).Errorf("onu-image-crc-validation-failed")
1573 return false
1574 }
1575
1576 o.StandbyImageVersion = o.InDownloadImageVersion
1577 onuLogger.WithFields(log.Fields{
1578 "OnuId": o.ID,
1579 "IntfId": o.PonPortID,
1580 "OnuSn": o.Sn(),
1581 "StandbyVersion": o.StandbyImageVersion,
1582 }).Debug("onu-image-version-updated")
1583 return true
1584}
1585
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001586// BBR methods
1587
1588func sendOmciMsg(pktBytes []byte, intfId uint32, onuId uint32, sn *openolt.SerialNumber, msgType string, client openolt.OpenoltClient) {
1589 omciMsg := openolt.OmciMsg{
1590 IntfId: intfId,
1591 OnuId: onuId,
1592 Pkt: pktBytes,
1593 }
1594
1595 if _, err := client.OmciMsgOut(context.Background(), &omciMsg); err != nil {
1596 log.WithFields(log.Fields{
1597 "IntfId": intfId,
1598 "OnuId": onuId,
1599 "SerialNumber": common.OnuSnToString(sn),
1600 "Pkt": omciMsg.Pkt,
1601 }).Fatalf("Failed to send MIB Reset")
1602 }
1603 log.WithFields(log.Fields{
1604 "IntfId": intfId,
1605 "OnuId": onuId,
1606 "SerialNumber": common.OnuSnToString(sn),
1607 "Pkt": omciMsg.Pkt,
1608 }).Tracef("Sent OMCI message %s", msgType)
1609}
1610
1611func (onu *Onu) getNextTid(highPriority ...bool) uint16 {
1612 var next uint16
1613 if len(highPriority) > 0 && highPriority[0] {
1614 next = onu.hpTid
1615 onu.hpTid += 1
1616 if onu.hpTid < 0x8000 {
1617 onu.hpTid = 0x8000
1618 }
1619 } else {
1620 next = onu.tid
1621 onu.tid += 1
1622 if onu.tid >= 0x8000 {
1623 onu.tid = 1
1624 }
1625 }
1626 return next
1627}
1628
1629// TODO move this method in responders/omcisim
Matteo Scandolo8a574812021-05-20 15:18:53 -07001630// StartOmci is called in BBR to start the OMCI state machine
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001631func (o *Onu) StartOmci(client openolt.OpenoltClient) {
1632 mibReset, _ := omcilib.CreateMibResetRequest(o.getNextTid(false))
1633 sendOmciMsg(mibReset, o.PonPortID, o.ID, o.SerialNumber, "mibReset", client)
1634}
1635
Matteo Scandolof9d43412021-01-12 11:11:34 -08001636// handleOmciResponse is used in BBR to generate the OMCI packets the openolt-adapter would send to the device
1637func (o *Onu) handleOmciResponse(msg bbsim.OmciIndicationMessage, client openolt.OpenoltClient) {
1638
1639 // we need to encode the packet in HEX
1640 pkt := make([]byte, len(msg.OmciInd.Pkt)*2)
1641 hex.Encode(pkt, msg.OmciInd.Pkt)
1642 packet, omciMsg, err := omcilib.ParseOpenOltOmciPacket(pkt)
1643 if err != nil {
1644 log.WithFields(log.Fields{
1645 "IntfId": o.PonPortID,
1646 "SerialNumber": o.Sn(),
1647 "omciPacket": msg.OmciInd.Pkt,
1648 }).Error("BBR Cannot parse OMCI packet")
1649 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001650
1651 log.WithFields(log.Fields{
1652 "IntfId": msg.OmciInd.IntfId,
1653 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001654 "OnuSn": o.Sn(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001655 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001656 "msgType": omciMsg.MessageType,
Anand S Katti09541352020-01-29 15:54:01 +05301657 }).Trace("ONU Receives OMCI Msg")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001658 switch omciMsg.MessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001659 default:
Matteo Scandolo813402b2019-10-23 19:24:52 -07001660 log.WithFields(log.Fields{
1661 "IntfId": msg.OmciInd.IntfId,
1662 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001663 "OnuSn": o.Sn(),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001664 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001665 "msgType": omciMsg.MessageType,
Matteo Scandolo813402b2019-10-23 19:24:52 -07001666 }).Fatalf("unexpected frame: %v", packet)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001667 case omci.MibResetResponseType:
1668 mibUpload, _ := omcilib.CreateMibUploadRequest(o.getNextTid(false))
1669 sendOmciMsg(mibUpload, o.PonPortID, o.ID, o.SerialNumber, "mibUpload", client)
1670 case omci.MibUploadResponseType:
1671 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1672 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
1673 case omci.MibUploadNextResponseType:
1674 o.seqNumber++
Matteo Scandolo8a574812021-05-20 15:18:53 -07001675 // once the mibUpload is complete send a SetRequest for the PPTP to enable the UNI
1676 // NOTE that in BBR we only enable the first UNI
Holger Hildebrandt236e3742022-05-04 14:07:27 +00001677 if o.seqNumber == o.MibDb.NumberOfBaselineCommands {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001678 meId := omcilib.GenerateUniPortEntityId(1)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001679
Matteo Scandolo8a574812021-05-20 15:18:53 -07001680 meParams := me.ParamData{
1681 EntityID: meId.ToUint16(),
Elia Battiston9bfe1102022-02-03 10:38:03 +01001682 Attributes: me.AttributeValueMap{me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0},
Matteo Scandolo8a574812021-05-20 15:18:53 -07001683 }
1684 managedEntity, omciError := me.NewPhysicalPathTerminationPointEthernetUni(meParams)
1685 if omciError.GetError() != nil {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001686 onuLogger.WithFields(log.Fields{
1687 "OnuId": o.ID,
1688 "IntfId": o.PonPortID,
1689 "OnuSn": o.Sn(),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001690 }).Fatal(omciError.GetError())
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001691 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001692
1693 setPPtp, _ := omcilib.CreateSetRequest(managedEntity, 1)
1694 sendOmciMsg(setPPtp, o.PonPortID, o.ID, o.SerialNumber, "setRquest", client)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001695 } else {
1696 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1697 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001698 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001699 case omci.SetResponseType:
1700 // once we set the PPTP to active we can start sending flows
1701
1702 if err := o.InternalState.Event(BbrOnuTxSendEapolFlow); err != nil {
1703 onuLogger.WithFields(log.Fields{
1704 "OnuId": o.ID,
1705 "IntfId": o.PonPortID,
1706 "OnuSn": o.Sn(),
1707 }).Errorf("Error while transitioning ONU State %v", err)
1708 }
1709 case omci.AlarmNotificationType:
1710 log.Info("bbr-received-alarm")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001711 }
1712}
1713
1714func (o *Onu) sendEapolFlow(client openolt.OpenoltClient) {
1715
1716 classifierProto := openolt.Classifier{
1717 EthType: uint32(layers.EthernetTypeEAPOL),
1718 OVid: 4091,
1719 }
1720
1721 actionProto := openolt.Action{}
1722
1723 downstreamFlow := openolt.Flow{
1724 AccessIntfId: int32(o.PonPortID),
1725 OnuId: int32(o.ID),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001726 UniId: int32(0), // NOTE do not hardcode this, we need to support multiple UNIs
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001727 FlowId: uint64(o.ID),
Elia Battiston560e9552022-01-31 10:44:15 +01001728 FlowType: flowTypeDownstream,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001729 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001730 Classifier: &classifierProto,
1731 Action: &actionProto,
1732 Priority: int32(100),
1733 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001734 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1735 // AllocId and GemPorts need to be unique per PON
1736 // for now use the ONU-ID, will need to change once we support multiple UNIs
1737 AllocId: int32(o.ID),
1738 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001739 }
1740
1741 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1742 log.WithFields(log.Fields{
1743 "IntfId": o.PonPortID,
1744 "OnuId": o.ID,
1745 "FlowId": downstreamFlow.FlowId,
1746 "PortNo": downstreamFlow.PortNo,
1747 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001748 "Err": err,
Matteo Scandolob0e3e622020-04-23 17:00:29 -07001749 }).Fatalf("Failed to add EAPOL Flow")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001750 }
1751 log.WithFields(log.Fields{
1752 "IntfId": o.PonPortID,
1753 "OnuId": o.ID,
1754 "FlowId": downstreamFlow.FlowId,
1755 "PortNo": downstreamFlow.PortNo,
1756 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1757 }).Info("Sent EAPOL Flow")
1758}
1759
1760func (o *Onu) sendDhcpFlow(client openolt.OpenoltClient) {
Matteo Scandolo4a036262020-08-17 15:56:13 -07001761
Matteo Scandolo8a574812021-05-20 15:18:53 -07001762 // BBR only works with a single UNI and a single service (ATT HSIA)
1763 hsia := o.UniPorts[0].(*UniPort).Services[0].(*Service)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001764 classifierProto := openolt.Classifier{
1765 EthType: uint32(layers.EthernetTypeIPv4),
1766 SrcPort: uint32(68),
1767 DstPort: uint32(67),
Matteo Scandolo4a036262020-08-17 15:56:13 -07001768 OVid: uint32(hsia.CTag),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001769 OPbits: 255,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001770 }
1771
1772 actionProto := openolt.Action{}
1773
1774 downstreamFlow := openolt.Flow{
1775 AccessIntfId: int32(o.PonPortID),
1776 OnuId: int32(o.ID),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001777 UniId: int32(0), // BBR only supports a single UNI
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001778 FlowId: uint64(o.ID),
Elia Battiston560e9552022-01-31 10:44:15 +01001779 FlowType: flowTypeDownstream,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001780 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001781 Classifier: &classifierProto,
1782 Action: &actionProto,
1783 Priority: int32(100),
1784 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001785 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1786 // AllocId and GemPorts need to be unique per PON
1787 // for now use the ONU-ID, will need to change once we support multiple UNIs
1788 AllocId: int32(o.ID),
1789 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001790 }
1791
1792 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1793 log.WithFields(log.Fields{
1794 "IntfId": o.PonPortID,
1795 "OnuId": o.ID,
1796 "FlowId": downstreamFlow.FlowId,
1797 "PortNo": downstreamFlow.PortNo,
1798 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001799 "Err": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001800 }).Fatalf("Failed to send DHCP Flow")
1801 }
1802 log.WithFields(log.Fields{
1803 "IntfId": o.PonPortID,
1804 "OnuId": o.ID,
1805 "FlowId": downstreamFlow.FlowId,
1806 "PortNo": downstreamFlow.PortNo,
1807 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1808 }).Info("Sent DHCP Flow")
1809}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301810
Andrea Campanellacc9b1662022-01-26 17:47:48 +01001811// DeleteFlow method search and delete flowKey from the onu flows slice
1812func (onu *Onu) DeleteFlow(key FlowKey) {
1813 for pos, flowKey := range onu.Flows {
1814 if flowKey == key {
1815 // delete the flowKey by shifting all flowKeys by one
1816 onu.Flows = append(onu.Flows[:pos], onu.Flows[pos+1:]...)
1817 t := make([]FlowKey, len(onu.Flows))
1818 copy(t, onu.Flows)
1819 onu.Flows = t
Pragya Arya8bdb4532020-03-02 17:08:09 +05301820 break
1821 }
1822 }
1823}
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301824
Abhay Kumarc5723cc2023-06-08 12:09:30 +05301825/*
1826when ReDiscoverOnu is called during reboot, true is passed so that there is no delay in onu discoveries
1827
1828 It is assumed that all onu resources are cleared and no sleep is required
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301829*/
1830func (onu *Onu) ReDiscoverOnu(isReboot bool) {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301831 // Wait for few seconds to be sure of the cleanup
Abhilash Laxmeshwar84425a02022-06-15 17:25:14 +05301832 if !isReboot {
1833 time.Sleep(5 * time.Second)
1834 }
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301835
1836 onuLogger.WithFields(log.Fields{
1837 "IntfId": onu.PonPortID,
1838 "OnuId": onu.ID,
1839 "OnuSn": onu.Sn(),
1840 }).Debug("Send ONU Re-Discovery")
nikesh.krishnandd07b922023-07-05 23:55:42 +05301841 if onu.InternalState.Current() != OnuStateDiscovered {
1842 // ONU Re-Discovery
1843 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
1844 log.WithFields(log.Fields{
1845 "IntfId": onu.PonPortID,
1846 "OnuSn": onu.Sn(),
1847 "OnuId": onu.ID,
1848 }).Infof("Failed to transition ONU to %s state: %s", OnuStateInitialized, err.Error())
1849 }
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301850
nikesh.krishnandd07b922023-07-05 23:55:42 +05301851 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
1852 log.WithFields(log.Fields{
1853 "IntfId": onu.PonPortID,
1854 "OnuSn": onu.Sn(),
1855 "OnuId": onu.ID,
1856 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDiscovered, err.Error())
1857 }
1858 } else {
1859 //if onu is already discovered dont change the state ut rather fire the indication again (this case happens if voltha misses the indications)
1860 msg := bbsim.Message{
1861 Type: bbsim.OnuDiscIndication,
1862 Data: bbsim.OnuDiscIndicationMessage{
1863 OperState: bbsim.UP,
1864 },
1865 }
1866 onu.Channel <- msg
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301867 }
1868
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301869}
Matteo Scandolo4a036262020-08-17 15:56:13 -07001870
Matteo Scandolo8a574812021-05-20 15:18:53 -07001871// deprecated, delegate this to the uniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -07001872func (onu *Onu) findServiceByMacAddress(macAddress net.HardwareAddr) (*Service, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001873 // FIXME is there a better way to avoid this loop?
1874 for _, u := range onu.UniPorts {
1875 uni := u.(*UniPort)
1876 for _, s := range uni.Services {
1877 service := s.(*Service)
1878 if service.HwAddress.String() == macAddress.String() {
1879 return service, nil
1880 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001881 }
1882 }
1883 return nil, fmt.Errorf("cannot-find-service-with-mac-address-%s", macAddress.String())
1884}
Himani Chawla13b1ee02021-03-15 01:43:53 +05301885
Matteo Scandolo8a574812021-05-20 15:18:53 -07001886func (onu *Onu) findUniByPortNo(portNo uint32) (*UniPort, error) {
1887 for _, u := range onu.UniPorts {
1888 uni := u.(*UniPort)
1889 if uni.PortNo == portNo {
1890 return uni, nil
1891 }
1892 }
1893 return nil, fmt.Errorf("cannot-find-uni-with-port-no-%d", portNo)
1894}
1895
Baris Ertas53ab13c2023-05-25 16:31:48 +03001896// findUniWithIgmpMembership returns the list of UNIs which has sent any IGMP messages
1897// and has any active membershipments currently
1898func (onu *Onu) findUniWithIgmpMembership() []UniPort {
1899 var uniPorts []UniPort
1900 for _, u := range onu.UniPorts {
1901 uni := u.(*UniPort)
1902 if !uni.OperState.Is(UniStateUp) {
1903 // if the UNI is disabled, ignore it
1904 continue
1905 }
1906 for _, s := range uni.Services {
1907 service := s.(*Service)
1908 if service.NeedsIgmp {
1909 if !service.InternalState.Is(ServiceStateInitialized) {
1910 log.WithFields(log.Fields{
1911 "OnuId": onu.ID,
1912 "UniId": uni.ID,
1913 "IntfId": onu.PonPortID,
1914 "OnuSn": onu.Sn(),
1915 "Service": service.Name,
1916 }).Warn("service-not-initialized-skipping")
1917 continue
1918 }
1919 if len(service.groupAddresses) > 0 {
1920 uniPorts = append(uniPorts, *uni)
1921 }
1922 }
1923 }
1924 }
1925 return uniPorts
1926}
1927
Himani Chawla13b1ee02021-03-15 01:43:53 +05301928func (o *Onu) SendOMCIAlarmNotificationMsg(raiseOMCIAlarm bool, alarmType string) {
1929 switch alarmType {
1930 case "ONU_ALARM_LOS":
1931 msg := bbsim.Message{
1932 Type: bbsim.UniStatusAlarm,
1933 Data: bbsim.UniStatusAlarmMessage{
1934 OnuSN: o.SerialNumber,
1935 OnuID: o.ID,
1936 EntityID: 257,
1937 RaiseOMCIAlarm: raiseOMCIAlarm,
1938 },
1939 }
1940 o.Channel <- msg
1941 }
1942
1943}
1944
1945func (o *Onu) IncrementAlarmSequenceNumber(key omcilib.OnuAlarmInfoMapKey) uint8 {
1946 o.onuAlarmsInfoLock.Lock()
1947 defer o.onuAlarmsInfoLock.Unlock()
1948 if alarmInfo, ok := o.onuAlarmsInfo[key]; ok {
1949 if alarmInfo.SequenceNo == 255 {
1950 alarmInfo.SequenceNo = 1
1951 } else {
1952 alarmInfo.SequenceNo++
1953 }
1954 o.onuAlarmsInfo[key] = alarmInfo
1955 return alarmInfo.SequenceNo
1956 } else {
1957 // This is the first time alarm notification message is being sent
1958 o.onuAlarmsInfo[key] = omcilib.OnuAlarmInfo{
1959 SequenceNo: 1,
1960 }
1961 return 1
1962 }
1963}
Elia Battistonfe017662022-01-05 11:43:16 +01001964
1965func (o *Onu) InvalidateMibDataSync() {
1966 rand.Seed(time.Now().UnixNano())
1967 r := uint8(rand.Intn(10) + 1)
1968
1969 o.MibDataSync += r
1970
1971 // Since MibDataSync is a uint8, summing to it will never
1972 // result in a value higher than 255, but could be 0
1973 if o.MibDataSync == 0 {
1974 o.MibDataSync++
1975 }
1976}