blob: b112d766ef24fb6c1d58c1d805b0b58ae5e10c06 [file] [log] [blame]
Matteo Scandolo11006992019-08-28 11:29:46 -07001/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Matteo Scandolo4747d292019-08-05 11:50:18 -070017package devices
18
19import (
Matteo Scandolo40e067f2019-10-16 16:59:41 -070020 "context"
Matteo Scandolo618a6582020-09-09 12:21:29 -070021 "encoding/hex"
Matteo Scandolo3bc73742019-08-20 14:04:04 -070022 "fmt"
Mahir Gunyela1753ae2021-06-23 00:24:56 -070023 "sync"
24
Matteo Scandolo8a574812021-05-20 15:18:53 -070025 "github.com/opencord/bbsim/internal/bbsim/packetHandlers"
26 "github.com/opencord/bbsim/internal/bbsim/responders/dhcp"
27 "github.com/opencord/bbsim/internal/bbsim/responders/eapol"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000028
Matteo Scandolof9d43412021-01-12 11:11:34 -080029 pb "github.com/opencord/bbsim/api/bbsim"
30 "github.com/opencord/bbsim/internal/bbsim/alarmsim"
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000031
32 "net"
33 "strconv"
34 "time"
Himani Chawla13b1ee02021-03-15 01:43:53 +053035
Matteo Scandolo4b077aa2021-02-16 17:33:37 -080036 bbsim "github.com/opencord/bbsim/internal/bbsim/types"
Andrea Campanella10426e22021-10-15 17:58:04 +020037 me "github.com/opencord/omci-lib-go/v2/generated"
Zdravko Bozakov681364d2019-11-10 14:28:46 +010038
Matteo Scandolo3bc73742019-08-20 14:04:04 -070039 "github.com/google/gopacket/layers"
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -070040 "github.com/jpillora/backoff"
Matteo Scandolo4747d292019-08-05 11:50:18 -070041 "github.com/looplab/fsm"
Matteo Scandolo40e067f2019-10-16 16:59:41 -070042 "github.com/opencord/bbsim/internal/common"
43 omcilib "github.com/opencord/bbsim/internal/common/omci"
Andrea Campanella10426e22021-10-15 17:58:04 +020044 "github.com/opencord/omci-lib-go/v2"
David K. Bainbridgec415efe2021-08-19 13:05:21 +000045 "github.com/opencord/voltha-protos/v5/go/openolt"
46 "github.com/opencord/voltha-protos/v5/go/tech_profile"
Matteo Scandolo4747d292019-08-05 11:50:18 -070047 log "github.com/sirupsen/logrus"
48)
49
Matteo Scandolo9a3518c2019-08-13 14:36:01 -070050var onuLogger = log.WithFields(log.Fields{
51 "module": "ONU",
52})
53
Matteo Scandolocedde462021-03-09 17:37:16 -080054const (
Holger Hildebrandtc10bab12021-04-27 09:23:48 +000055 maxOmciMsgCounter = 10
56)
57
58const (
Matteo Scandolocedde462021-03-09 17:37:16 -080059 // ONU transitions
60 OnuTxInitialize = "initialize"
61 OnuTxDiscover = "discover"
62 OnuTxEnable = "enable"
63 OnuTxDisable = "disable"
64 OnuTxPonDisable = "pon_disable"
65 OnuTxStartImageDownload = "start_image_download"
66 OnuTxProgressImageDownload = "progress_image_download"
67 OnuTxCompleteImageDownload = "complete_image_download"
68 OnuTxFailImageDownload = "fail_image_download"
69 OnuTxActivateImage = "activate_image"
70 OnuTxCommitImage = "commit_image"
71
72 // ONU States
73 OnuStateCreated = "created"
74 OnuStateInitialized = "initialized"
75 OnuStateDiscovered = "discovered"
76 OnuStateEnabled = "enabled"
77 OnuStateDisabled = "disabled"
78 OnuStatePonDisabled = "pon_disabled"
79 OnuStateImageDownloadStarted = "image_download_started"
80 OnuStateImageDownloadInProgress = "image_download_in_progress"
81 OnuStateImageDownloadComplete = "image_download_completed"
82 OnuStateImageDownloadError = "image_download_error"
83 OnuStateImageActivated = "software_image_activated"
84 OnuStateImageCommitted = "software_image_committed"
85
86 // BBR ONU States and Transitions
87 BbrOnuTxSendEapolFlow = "send_eapol_flow"
88 BbrOnuStateEapolFlowSent = "eapol_flow_sent"
89 BbrOnuTxSendDhcpFlow = "send_dhcp_flow"
90 BbrOnuStateDhcpFlowSent = "dhcp_flow_sent"
91)
92
Pragya Arya8bdb4532020-03-02 17:08:09 +053093type FlowKey struct {
Matteo Scandolo4f4ac792020-10-01 16:33:21 -070094 ID uint64
Pragya Arya8bdb4532020-03-02 17:08:09 +053095 Direction string
96}
97
Matteo Scandolo86e8ce62019-10-11 12:03:10 -070098type Onu struct {
Matteo Scandoloe811ae92019-12-10 17:50:14 -080099 ID uint32
100 PonPortID uint32
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700101 PonPort *PonPort
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800102 InternalState *fsm.FSM
Pragya Arya2225f202020-01-29 18:05:01 +0530103 DiscoveryRetryDelay time.Duration // this is the time between subsequent Discovery Indication
104 DiscoveryDelay time.Duration // this is the time to send the first Discovery Indication
Matteo Scandolo4a036262020-08-17 15:56:13 -0700105
Matteo Scandolo4a036262020-08-17 15:56:13 -0700106 Backoff *backoff.Backoff
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800107 // ONU State
Matteo Scandolo8a574812021-05-20 15:18:53 -0700108 UniPorts []UniPortIf
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700109 Flows []FlowKey
110 FlowIds []uint64 // keep track of the flows we currently have in the ONU
Matteo Scandolo99f18462019-10-28 14:14:28 -0700111
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700112 OperState *fsm.FSM
113 SerialNumber *openolt.SerialNumber
114
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700115 AdminLockState uint8 // 0 is enabled, 1 is disabled.
116
Matteo Scandolof9d43412021-01-12 11:11:34 -0800117 Channel chan bbsim.Message // this Channel is to track state changes OMCI messages, EAPOL and DHCP packets
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700118
119 // OMCI params
Matteo Scandolocedde462021-03-09 17:37:16 -0800120 MibDataSync uint8
121 ImageSoftwareExpectedSections int
122 ImageSoftwareReceivedSections int
123 ActiveImageEntityId uint16
124 CommittedImageEntityId uint16
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700125 StandbyImageVersion string
126 ActiveImageVersion string
127 CommittedImageVersion string
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000128 OmciResponseRate uint8
129 OmciMsgCounter uint8
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800130
131 // OMCI params (Used in BBR)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700132 tid uint16
133 hpTid uint16
134 seqNumber uint16
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700135 MibDb *omcilib.MibDb
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700136
Anand S Katti09541352020-01-29 15:54:01 +0530137 DoneChannel chan bool // this channel is used to signal once the onu is complete (when the struct is used by BBR)
138 TrafficSchedulers *tech_profile.TrafficSchedulers
Himani Chawla13b1ee02021-03-15 01:43:53 +0530139 onuAlarmsInfoLock sync.RWMutex
140 onuAlarmsInfo map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700141}
142
Matteo Scandolo99f18462019-10-28 14:14:28 -0700143func (o *Onu) Sn() string {
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700144 return common.OnuSnToString(o.SerialNumber)
Matteo Scandolo86e8ce62019-10-11 12:03:10 -0700145}
146
Matteo Scandolo8a574812021-05-20 15:18:53 -0700147func 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 -0700148
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700149 o := Onu{
Matteo Scandolocedde462021-03-09 17:37:16 -0800150 ID: id,
151 PonPortID: pon.ID,
152 PonPort: pon,
Matteo Scandolocedde462021-03-09 17:37:16 -0800153 tid: 0x1,
154 hpTid: 0x8000,
155 seqNumber: 0,
156 DoneChannel: make(chan bool, 1),
157 DiscoveryRetryDelay: 60 * time.Second, // this is used to send OnuDiscoveryIndications until an activate call is received
158 Flows: []FlowKey{},
159 DiscoveryDelay: delay,
160 MibDataSync: 0,
161 ImageSoftwareExpectedSections: 0, // populated during OMCI StartSoftwareDownloadRequest
162 ImageSoftwareReceivedSections: 0,
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700163 //TODO this needs reworking, it's always 0 or 1, possibly base all on the version
164 ActiveImageEntityId: 0, // when we start the SoftwareImage with ID 0 is active and committed
165 CommittedImageEntityId: 0,
166 StandbyImageVersion: "BBSM_IMG_00000",
167 ActiveImageVersion: "BBSM_IMG_00001",
168 CommittedImageVersion: "BBSM_IMG_00001",
169 OmciResponseRate: olt.OmciResponseRate,
170 OmciMsgCounter: 0,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700171 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800172 o.SerialNumber = NewSN(olt.ID, pon.ID, id)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700173 // NOTE this state machine is used to track the operational
174 // state as requested by VOLTHA
175 o.OperState = getOperStateFSM(func(e *fsm.Event) {
176 onuLogger.WithFields(log.Fields{
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700177 "OnuId": o.ID,
178 "IntfId": o.PonPortID,
179 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700180 }).Debugf("Changing ONU OperState from %s to %s", e.Src, e.Dst)
181 })
Himani Chawla13b1ee02021-03-15 01:43:53 +0530182 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo)
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700183 // NOTE this state machine is used to activate the OMCI, EAPOL and DHCP clients
184 o.InternalState = fsm.NewFSM(
Matteo Scandolocedde462021-03-09 17:37:16 -0800185 OnuStateCreated,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700186 fsm.Events{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700187 // DEVICE Lifecycle
Matteo Scandolocedde462021-03-09 17:37:16 -0800188 {Name: OnuTxInitialize, Src: []string{OnuStateCreated, OnuStateDisabled, OnuStatePonDisabled}, Dst: OnuStateInitialized},
189 {Name: OnuTxDiscover, Src: []string{OnuStateInitialized}, Dst: OnuStateDiscovered},
190 {Name: OnuTxEnable, Src: []string{OnuStateDiscovered, OnuStatePonDisabled}, Dst: OnuStateEnabled},
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100191 // 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 -0800192 {Name: OnuTxDisable, Src: []string{OnuStateEnabled, OnuStatePonDisabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStateDisabled},
Pragya Arya6a708d62020-01-01 17:17:20 +0530193 // 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 +0200194 {Name: OnuTxPonDisable, Src: []string{OnuStateEnabled, OnuStateImageActivated, OnuStateImageDownloadError, OnuStateImageCommitted, OnuStateImageDownloadComplete}, Dst: OnuStatePonDisabled},
Matteo Scandolocedde462021-03-09 17:37:16 -0800195 // Software Image Download related states
Matteo Scandolo9f4bf4f2021-06-22 09:41:02 +0200196 {Name: OnuTxStartImageDownload, Src: []string{OnuStateEnabled, OnuStateImageDownloadComplete, OnuStateImageDownloadError, OnuStateImageCommitted}, Dst: OnuStateImageDownloadStarted},
Matteo Scandolocedde462021-03-09 17:37:16 -0800197 {Name: OnuTxProgressImageDownload, Src: []string{OnuStateImageDownloadStarted}, Dst: OnuStateImageDownloadInProgress},
198 {Name: OnuTxCompleteImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadComplete},
199 {Name: OnuTxFailImageDownload, Src: []string{OnuStateImageDownloadInProgress}, Dst: OnuStateImageDownloadError},
200 {Name: OnuTxActivateImage, Src: []string{OnuStateImageDownloadComplete}, Dst: OnuStateImageActivated},
201 {Name: OnuTxCommitImage, Src: []string{OnuStateEnabled}, Dst: OnuStateImageCommitted}, // the image is committed after a ONU reboot
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700202 // BBR States
203 // TODO add start OMCI state
Matteo Scandolocedde462021-03-09 17:37:16 -0800204 {Name: BbrOnuTxSendEapolFlow, Src: []string{OnuStateInitialized}, Dst: BbrOnuStateEapolFlowSent},
205 {Name: BbrOnuTxSendDhcpFlow, Src: []string{BbrOnuStateEapolFlowSent}, Dst: BbrOnuStateDhcpFlowSent},
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700206 },
207 fsm.Callbacks{
208 "enter_state": func(e *fsm.Event) {
209 o.logStateChange(e.Src, e.Dst)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700210 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700211 fmt.Sprintf("enter_%s", OnuStateInitialized): func(e *fsm.Event) {
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100212 // create new channel for ProcessOnuMessages Go routine
Matteo Scandolof9d43412021-01-12 11:11:34 -0800213 o.Channel = make(chan bbsim.Message, 2048)
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800214
Matteo Scandolocedde462021-03-09 17:37:16 -0800215 if err := o.OperState.Event(OnuTxEnable); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800216 onuLogger.WithFields(log.Fields{
217 "OnuId": o.ID,
218 "IntfId": o.PonPortID,
219 "OnuSn": o.Sn(),
220 }).Errorf("Cannot change ONU OperState to up: %s", err.Error())
221 }
222
Pragya Arya1cbefa42020-01-13 12:15:29 +0530223 if !isMock {
224 // start ProcessOnuMessages Go routine
Matteo Scandolo4a036262020-08-17 15:56:13 -0700225 go o.ProcessOnuMessages(olt.enableContext, olt.OpenoltStream, nil)
Pragya Arya1cbefa42020-01-13 12:15:29 +0530226 }
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100227 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700228 fmt.Sprintf("enter_%s", OnuStateDiscovered): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800229 msg := bbsim.Message{
230 Type: bbsim.OnuDiscIndication,
231 Data: bbsim.OnuDiscIndicationMessage{
232 OperState: bbsim.UP,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100233 },
234 }
235 o.Channel <- msg
236 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700237 fmt.Sprintf("enter_%s", OnuStateEnabled): func(event *fsm.Event) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800238
239 if used, sn := o.PonPort.isOnuIdAllocated(o.ID); used {
240 onuLogger.WithFields(log.Fields{
241 "IntfId": o.PonPortID,
242 "OnuId": o.ID,
243 "SerialNumber": o.Sn(),
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700244 }).Errorf("onu-id-duplicated-with-%s", common.OnuSnToString(sn))
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800245 return
246 } else {
247 o.PonPort.storeOnuId(o.ID, o.SerialNumber)
248 }
249
Matteo Scandolof9d43412021-01-12 11:11:34 -0800250 msg := bbsim.Message{
251 Type: bbsim.OnuIndication,
252 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700253 OnuSN: o.SerialNumber,
254 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800255 OperState: bbsim.UP,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700256 },
257 }
258 o.Channel <- msg
259 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700260 fmt.Sprintf("enter_%s", OnuStateDisabled): func(event *fsm.Event) {
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700261
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700262 o.cleanupOnuState()
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700263
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700264 // set the OperState to disabled
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800265 if err := o.OperState.Event("disable"); err != nil {
266 onuLogger.WithFields(log.Fields{
267 "OnuId": o.ID,
268 "IntfId": o.PonPortID,
269 "OnuSn": o.Sn(),
270 }).Errorf("Cannot change ONU OperState to down: %s", err.Error())
271 }
Matteo Scandolo47ef64b2020-04-20 14:16:07 -0700272 // send the OnuIndication DOWN event
Matteo Scandolof9d43412021-01-12 11:11:34 -0800273 msg := bbsim.Message{
274 Type: bbsim.OnuIndication,
275 Data: bbsim.OnuIndicationMessage{
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700276 OnuSN: o.SerialNumber,
277 PonPortID: o.PonPortID,
Matteo Scandolof9d43412021-01-12 11:11:34 -0800278 OperState: bbsim.DOWN,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700279 },
280 }
281 o.Channel <- msg
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530282
Matteo Scandolo8a574812021-05-20 15:18:53 -0700283 // disable the UNI ports
284 for _, uni := range o.UniPorts {
285 _ = uni.Disable()
286 }
287
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530288 // verify all the flows removes are handled and
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100289 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolo8a574812021-05-20 15:18:53 -0700290 // NOTE may need to wait for the UNIs to be down too before shutting down the channel
Hardik Windlass7b3405b2020-07-08 15:10:05 +0530291 if len(o.FlowIds) == 0 {
292 close(o.Channel)
293 }
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700294 },
295 fmt.Sprintf("enter_%s", OnuStatePonDisabled): func(event *fsm.Event) {
296 o.cleanupOnuState()
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700297 },
Matteo Scandolo4a036262020-08-17 15:56:13 -0700298 // BBR states
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700299 fmt.Sprintf("enter_%s", BbrOnuStateEapolFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800300 msg := bbsim.Message{
301 Type: bbsim.SendEapolFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700302 }
303 o.Channel <- msg
304 },
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700305 fmt.Sprintf("enter_%s", BbrOnuStateDhcpFlowSent): func(e *fsm.Event) {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800306 msg := bbsim.Message{
307 Type: bbsim.SendDhcpFlow,
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700308 }
309 o.Channel <- msg
310 },
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700311 },
312 )
Mahir Gunyela1753ae2021-06-23 00:24:56 -0700313 onuLogger.WithFields(log.Fields{
314 "OnuId": o.ID,
315 "IntfId": o.PonPortID,
316 "OnuSn": o.Sn(),
317 "NumUni": olt.NumUni,
318 }).Debug("creating-uni-ports")
319 for i := 0; i < olt.NumUni; i++ {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700320 uni, err := NewUniPort(uint32(i), &o, nextCtag, nextStag)
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700321 if err != nil {
322 onuLogger.WithFields(log.Fields{
323 "OnuId": o.ID,
324 "IntfId": o.PonPortID,
325 "OnuSn": o.Sn(),
326 "Err": err,
327 }).Fatal("cannot-create-uni-port")
328 }
329 o.UniPorts = append(o.UniPorts, uni)
330 }
331
332 mibDb, err := omcilib.GenerateMibDatabase(len(o.UniPorts))
333 if err != nil {
334 onuLogger.WithFields(log.Fields{
335 "OnuId": o.ID,
336 "IntfId": o.PonPortID,
337 "OnuSn": o.Sn(),
338 }).Fatal("cannot-generate-mibdb-for-onu")
339 }
340 o.MibDb = mibDb
341
Matteo Scandolo27428702019-10-11 16:21:16 -0700342 return &o
Matteo Scandolo4747d292019-08-05 11:50:18 -0700343}
344
William Kurkian0418bc82019-11-06 12:16:24 -0500345func (o *Onu) logStateChange(src string, dst string) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700346 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700347 "OnuId": o.ID,
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700348 "IntfId": o.PonPortID,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700349 "OnuSn": o.Sn(),
Matteo Scandolo3bc73742019-08-20 14:04:04 -0700350 }).Debugf("Changing ONU InternalState from %s to %s", src, dst)
351}
352
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700353// cleanupOnuState this method is to clean the local state when the ONU is disabled
354func (o *Onu) cleanupOnuState() {
355 // clean the ONU state
Matteo Scandolod15c0b42021-03-22 11:38:13 -0700356 o.Flows = []FlowKey{}
357 o.PonPort.removeOnuId(o.ID)
358 o.PonPort.removeAllocId(o.SerialNumber)
359 o.PonPort.removeGemPortBySn(o.SerialNumber)
360
361 o.onuAlarmsInfoLock.Lock()
362 o.onuAlarmsInfo = make(map[omcilib.OnuAlarmInfoMapKey]omcilib.OnuAlarmInfo) //Basically reset everything on onu disable
363 o.onuAlarmsInfoLock.Unlock()
364}
365
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100366// ProcessOnuMessages starts indication channel for each ONU
David Bainbridge103cf022019-12-16 20:11:35 +0000367func (o *Onu) ProcessOnuMessages(ctx context.Context, stream openolt.Openolt_EnableIndicationServer, client openolt.OpenoltClient) {
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700368 onuLogger.WithFields(log.Fields{
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100369 "onuID": o.ID,
370 "onuSN": o.Sn(),
371 "ponPort": o.PonPortID,
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700372 "stream": stream,
Zdravko Bozakov681364d2019-11-10 14:28:46 +0100373 }).Debug("Starting ONU Indication Channel")
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700374
Matteo Scandolob307d8a2021-05-10 15:19:27 -0700375 defer onuLogger.WithFields(log.Fields{
376 "onuID": o.ID,
377 "onuSN": o.Sn(),
378 "stream": stream,
379 }).Debug("Stopped handling ONU Indication Channel")
380
David Bainbridge103cf022019-12-16 20:11:35 +0000381loop:
382 for {
383 select {
384 case <-ctx.Done():
385 onuLogger.WithFields(log.Fields{
386 "onuID": o.ID,
387 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700388 }).Debug("ONU message handling canceled via context")
389 break loop
390 case <-stream.Context().Done():
391 onuLogger.WithFields(log.Fields{
392 "onuID": o.ID,
393 "onuSN": o.Sn(),
394 }).Debug("ONU message handling canceled via stream context")
David Bainbridge103cf022019-12-16 20:11:35 +0000395 break loop
396 case message, ok := <-o.Channel:
397 if !ok || ctx.Err() != nil {
398 onuLogger.WithFields(log.Fields{
399 "onuID": o.ID,
400 "onuSN": o.Sn(),
Matteo Scandolo9ddb3a92021-04-14 16:16:20 -0700401 }).Debug("ONU message handling canceled via channel close")
David Bainbridge103cf022019-12-16 20:11:35 +0000402 break loop
Matteo Scandolo075b1892019-10-07 12:11:07 -0700403 }
David Bainbridge103cf022019-12-16 20:11:35 +0000404 onuLogger.WithFields(log.Fields{
405 "onuID": o.ID,
406 "onuSN": o.Sn(),
407 "messageType": message.Type,
408 }).Tracef("Received message on ONU Channel")
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700409
David Bainbridge103cf022019-12-16 20:11:35 +0000410 switch message.Type {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800411 case bbsim.OnuDiscIndication:
412 msg, _ := message.Data.(bbsim.OnuDiscIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000413 // 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 +0530414 time.Sleep(o.DiscoveryDelay)
David Bainbridge103cf022019-12-16 20:11:35 +0000415 o.sendOnuDiscIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800416 case bbsim.OnuIndication:
417 msg, _ := message.Data.(bbsim.OnuIndicationMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000418 o.sendOnuIndication(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800419 case bbsim.OMCI:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800420 // these are OMCI messages received by the ONU
Matteo Scandolof9d43412021-01-12 11:11:34 -0800421 msg, _ := message.Data.(bbsim.OmciMessage)
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200422 _ = o.handleOmciRequest(msg, stream)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800423 case bbsim.UniStatusAlarm:
424 msg, _ := message.Data.(bbsim.UniStatusAlarmMessage)
Himani Chawla13b1ee02021-03-15 01:43:53 +0530425 onuAlarmMapKey := omcilib.OnuAlarmInfoMapKey{
426 MeInstance: msg.EntityID,
427 MeClassID: me.PhysicalPathTerminationPointEthernetUniClassID,
428 }
429 seqNo := o.IncrementAlarmSequenceNumber(onuAlarmMapKey)
430 o.onuAlarmsInfoLock.Lock()
431 var alarmInfo = o.onuAlarmsInfo[onuAlarmMapKey]
432 pkt, alarmBitMap := omcilib.CreateUniStatusAlarm(msg.RaiseOMCIAlarm, msg.EntityID, seqNo)
433 if pkt != nil { //pkt will be nil if we are unable to create the alarm
434 if err := o.sendOmciIndication(pkt, 0, stream); err != nil {
435 onuLogger.WithFields(log.Fields{
436 "IntfId": o.PonPortID,
437 "SerialNumber": o.Sn(),
438 "omciPacket": pkt,
439 "adminState": msg.AdminState,
440 "entityID": msg.EntityID,
441 }).Errorf("failed-to-send-UNI-Link-Alarm: %v", err)
442 alarmInfo.SequenceNo--
443 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800444 onuLogger.WithFields(log.Fields{
445 "IntfId": o.PonPortID,
446 "SerialNumber": o.Sn(),
447 "omciPacket": pkt,
448 "adminState": msg.AdminState,
449 "entityID": msg.EntityID,
Himani Chawla13b1ee02021-03-15 01:43:53 +0530450 }).Trace("UNI-Link-alarm-sent")
451 if alarmBitMap == [28]byte{0} {
452 delete(o.onuAlarmsInfo, onuAlarmMapKey)
453 } else {
454 alarmInfo.AlarmBitMap = alarmBitMap
455 o.onuAlarmsInfo[onuAlarmMapKey] = alarmInfo
456 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800457 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530458 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800459 case bbsim.FlowAdd:
460 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700461 o.handleFlowAdd(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800462 case bbsim.FlowRemoved:
463 msg, _ := message.Data.(bbsim.OnuFlowUpdateMessage)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -0700464 o.handleFlowRemove(msg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800465 case bbsim.OnuPacketOut:
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700466
Matteo Scandolof9d43412021-01-12 11:11:34 -0800467 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000468
Matteo Scandoloadc72a82020-09-08 18:46:08 -0700469 onuLogger.WithFields(log.Fields{
David Bainbridge103cf022019-12-16 20:11:35 +0000470 "IntfId": msg.IntfId,
471 "OnuId": msg.OnuId,
472 "pktType": msg.Type,
473 }).Trace("Received OnuPacketOut Message")
474
Matteo Scandolo8a574812021-05-20 15:18:53 -0700475 uni, err := o.findUniByPortNo(msg.PortNo)
Matteo Scandolo618a6582020-09-09 12:21:29 -0700476
Matteo Scandolo8a574812021-05-20 15:18:53 -0700477 if err != nil {
478 onuLogger.WithFields(log.Fields{
479 "IntfId": msg.IntfId,
480 "OnuId": msg.OnuId,
481 "pktType": msg.Type,
482 "portNo": msg.PortNo,
483 "MacAddress": msg.MacAddress,
484 "Pkt": hex.EncodeToString(msg.Packet.Data()),
485 "OnuSn": o.Sn(),
486 }).Error("Cannot find Uni associated with packet")
487 return
David Bainbridge103cf022019-12-16 20:11:35 +0000488 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700489 uni.PacketCh <- msg
490 // BBR specific messages
Matteo Scandolof9d43412021-01-12 11:11:34 -0800491 case bbsim.OnuPacketIn:
David Bainbridge103cf022019-12-16 20:11:35 +0000492 // NOTE we only receive BBR packets here.
493 // Eapol.HandleNextPacket can handle both BBSim and BBr cases so the call is the same
494 // 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 -0800495 msg, _ := message.Data.(bbsim.OnuPacketMessage)
David Bainbridge103cf022019-12-16 20:11:35 +0000496
Matteo Scandolo8a574812021-05-20 15:18:53 -0700497 onuLogger.WithFields(log.Fields{
498 "IntfId": msg.IntfId,
499 "OnuId": msg.OnuId,
500 "PortNo": msg.PortNo,
501 "GemPortId": msg.GemPortId,
502 "pktType": msg.Type,
David Bainbridge103cf022019-12-16 20:11:35 +0000503 }).Trace("Received OnuPacketIn Message")
504
Matteo Scandolo8a574812021-05-20 15:18:53 -0700505 uni, err := o.findUniByPortNo(msg.PortNo)
506 if err != nil {
507 onuLogger.WithFields(log.Fields{
508 "IntfId": msg.IntfId,
509 "OnuId": msg.OnuId,
510 "PortNo": msg.PortNo,
511 "GemPortId": msg.GemPortId,
512 "pktType": msg.Type,
513 }).Error(err.Error())
514 }
515
516 // BBR has one service and one UNI
517 serviceId := uint32(0)
518 oltId := 0
David Bainbridge103cf022019-12-16 20:11:35 +0000519 if msg.Type == packetHandlers.EAPOL {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700520 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 +0000521 } else if msg.Type == packetHandlers.DHCP {
Matteo Scandolo4a036262020-08-17 15:56:13 -0700522 _ = dhcp.HandleNextBbrPacket(o.ID, o.PonPortID, o.Sn(), o.DoneChannel, msg.Packet, client)
David Bainbridge103cf022019-12-16 20:11:35 +0000523 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800524 case bbsim.OmciIndication:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800525 // these are OMCI messages received by BBR (VOLTHA emulator)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800526 msg, _ := message.Data.(bbsim.OmciIndicationMessage)
527 o.handleOmciResponse(msg, client)
528 case bbsim.SendEapolFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000529 o.sendEapolFlow(client)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800530 case bbsim.SendDhcpFlow:
David Bainbridge103cf022019-12-16 20:11:35 +0000531 o.sendDhcpFlow(client)
532 default:
533 onuLogger.Warnf("Received unknown message data %v for type %v in OLT Channel", message.Data, message.Type)
Matteo Scandolo40e067f2019-10-16 16:59:41 -0700534 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700535 }
536 }
Matteo Scandolo4747d292019-08-05 11:50:18 -0700537}
538
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800539func NewSN(oltid int, intfid uint32, onuid uint32) *openolt.SerialNumber {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700540 sn := new(openolt.SerialNumber)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700541 sn.VendorId = []byte("BBSM")
542 sn.VendorSpecific = []byte{0, byte(oltid % 256), byte(intfid), byte(onuid)}
Matteo Scandolo4747d292019-08-05 11:50:18 -0700543 return sn
544}
545
Matteo Scandolof9d43412021-01-12 11:11:34 -0800546func (o *Onu) sendOnuDiscIndication(msg bbsim.OnuDiscIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4747d292019-08-05 11:50:18 -0700547 discoverData := &openolt.Indication_OnuDiscInd{OnuDiscInd: &openolt.OnuDiscIndication{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800548 IntfId: o.PonPortID,
549 SerialNumber: o.SerialNumber,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700550 }}
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700551
Matteo Scandolo4747d292019-08-05 11:50:18 -0700552 if err := stream.Send(&openolt.Indication{Data: discoverData}); err != nil {
Matteo Scandolo11006992019-08-28 11:29:46 -0700553 log.Errorf("Failed to send Indication_OnuDiscInd: %v", err)
Matteo Scandolo99f18462019-10-28 14:14:28 -0700554 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700555 }
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700556
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700557 onuLogger.WithFields(log.Fields{
Matteo Scandolof9d43412021-01-12 11:11:34 -0800558 "IntfId": o.PonPortID,
559 "OnuSn": o.Sn(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700560 "OnuId": o.ID,
Matteo Scandolo4747d292019-08-05 11:50:18 -0700561 }).Debug("Sent Indication_OnuDiscInd")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800562 publishEvent("ONU-discovery-indication-sent", int32(o.PonPortID), int32(o.ID), o.Sn())
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800563
564 // after DiscoveryRetryDelay check if the state is the same and in case send a new OnuDiscIndication
565 go func(delay time.Duration) {
Matteo Scandolo569e7172019-12-20 11:51:51 -0800566 time.Sleep(delay)
Matteo Scandolocedde462021-03-09 17:37:16 -0800567 if o.InternalState.Current() == OnuStateDiscovered {
Matteo Scandoloe811ae92019-12-10 17:50:14 -0800568 o.sendOnuDiscIndication(msg, stream)
569 }
570 }(o.DiscoveryRetryDelay)
Matteo Scandolo4747d292019-08-05 11:50:18 -0700571}
572
Matteo Scandolof9d43412021-01-12 11:11:34 -0800573func (o *Onu) sendOnuIndication(msg bbsim.OnuIndicationMessage, stream openolt.Openolt_EnableIndicationServer) {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800574 // NOTE the ONU ID is set by VOLTHA in the ActivateOnu call (via openolt.proto)
575 // and stored in the Onu struct via onu.SetID
Matteo Scandolo4747d292019-08-05 11:50:18 -0700576
577 indData := &openolt.Indication_OnuInd{OnuInd: &openolt.OnuIndication{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700578 IntfId: o.PonPortID,
579 OnuId: o.ID,
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700580 OperState: msg.OperState.String(),
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700581 AdminState: o.OperState.Current(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700582 SerialNumber: o.SerialNumber,
583 }}
584 if err := stream.Send(&openolt.Indication{Data: indData}); err != nil {
Matteo Scandolod7cc6d32020-02-26 16:51:12 -0800585 // NOTE do we need to transition to a broken state?
Matteo Scandolo11006992019-08-28 11:29:46 -0700586 log.Errorf("Failed to send Indication_OnuInd: %v", err)
Matteo Scandolo75ed5b92020-09-03 09:03:16 -0700587 return
Matteo Scandolo4747d292019-08-05 11:50:18 -0700588 }
Matteo Scandolo9a3518c2019-08-13 14:36:01 -0700589 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800590 "IntfId": o.PonPortID,
591 "OnuId": o.ID,
592 "VolthaOnuId": msg.OnuID,
593 "OperState": msg.OperState.String(),
594 "AdminState": msg.OperState.String(),
595 "OnuSn": o.Sn(),
Matteo Scandolo4747d292019-08-05 11:50:18 -0700596 }).Debug("Sent Indication_OnuInd")
Matteo Scandolo10f965c2019-09-24 10:40:46 -0700597
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700598}
599
Matteo Scandolof9d43412021-01-12 11:11:34 -0800600func (o *Onu) HandleShutdownONU() error {
601
602 dyingGasp := pb.ONUAlarmRequest{
603 AlarmType: "DYING_GASP",
604 SerialNumber: o.Sn(),
605 Status: "on",
606 }
607
608 if err := alarmsim.SimulateOnuAlarm(&dyingGasp, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
609 onuLogger.WithFields(log.Fields{
610 "OnuId": o.ID,
611 "IntfId": o.PonPortID,
612 "OnuSn": o.Sn(),
613 }).Errorf("Cannot send Dying Gasp: %s", err.Error())
614 return err
615 }
616
617 losReq := pb.ONUAlarmRequest{
618 AlarmType: "ONU_ALARM_LOS",
619 SerialNumber: o.Sn(),
620 Status: "on",
621 }
622
623 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
624 onuLogger.WithFields(log.Fields{
625 "OnuId": o.ID,
626 "IntfId": o.PonPortID,
627 "OnuSn": o.Sn(),
628 }).Errorf("Cannot send LOS: %s", err.Error())
629
630 return err
631 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530632 o.SendOMCIAlarmNotificationMsg(true, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800633 // TODO if it's the last ONU on the PON, then send a PON LOS
634
Matteo Scandolocedde462021-03-09 17:37:16 -0800635 if err := o.InternalState.Event(OnuTxDisable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800636 onuLogger.WithFields(log.Fields{
637 "OnuId": o.ID,
638 "IntfId": o.PonPortID,
639 "OnuSn": o.Sn(),
640 }).Errorf("Cannot shutdown ONU: %s", err.Error())
641 return err
642 }
643
644 return nil
645}
646
647func (o *Onu) HandlePowerOnONU() error {
648 intitalState := o.InternalState.Current()
649
650 // initialize the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800651 if intitalState == OnuStateCreated || intitalState == OnuStateDisabled {
652 if err := o.InternalState.Event(OnuTxInitialize); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800653 onuLogger.WithFields(log.Fields{
654 "OnuId": o.ID,
655 "IntfId": o.PonPortID,
656 "OnuSn": o.Sn(),
657 }).Errorf("Cannot poweron ONU: %s", err.Error())
658 return err
659 }
660 }
661
662 // turn off the LOS Alarm
663 losReq := pb.ONUAlarmRequest{
664 AlarmType: "ONU_ALARM_LOS",
665 SerialNumber: o.Sn(),
666 Status: "off",
667 }
668
669 if err := alarmsim.SimulateOnuAlarm(&losReq, o.ID, o.PonPortID, o.PonPort.Olt.channel); err != nil {
670 onuLogger.WithFields(log.Fields{
671 "OnuId": o.ID,
672 "IntfId": o.PonPortID,
673 "OnuSn": o.Sn(),
674 }).Errorf("Cannot send LOS: %s", err.Error())
675 return err
676 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530677 o.SendOMCIAlarmNotificationMsg(false, losReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800678
679 // Send a ONU Discovery indication
Matteo Scandolocedde462021-03-09 17:37:16 -0800680 if err := o.InternalState.Event(OnuTxDiscover); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800681 onuLogger.WithFields(log.Fields{
682 "OnuId": o.ID,
683 "IntfId": o.PonPortID,
684 "OnuSn": o.Sn(),
685 }).Errorf("Cannot poweron ONU: %s", err.Error())
686 return err
687 }
688
689 // move o directly to enable state only when its a powercycle case
690 // in case of first time o poweron o will be moved to enable on
691 // receiving ActivateOnu request from openolt adapter
Matteo Scandolocedde462021-03-09 17:37:16 -0800692 if intitalState == OnuStateDisabled {
693 if err := o.InternalState.Event(OnuTxEnable); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800694 onuLogger.WithFields(log.Fields{
695 "OnuId": o.ID,
696 "IntfId": o.PonPortID,
697 "OnuSn": o.Sn(),
698 }).Errorf("Cannot enable ONU: %s", err.Error())
699 return err
700 }
701 }
702
703 return nil
704}
705
706func (o *Onu) SetAlarm(alarmType string, status string) error {
707 alarmReq := pb.ONUAlarmRequest{
708 AlarmType: alarmType,
709 SerialNumber: o.Sn(),
710 Status: status,
711 }
712
713 err := alarmsim.SimulateOnuAlarm(&alarmReq, o.ID, o.PonPortID, o.PonPort.Olt.channel)
714 if err != nil {
715 return err
716 }
Himani Chawla13b1ee02021-03-15 01:43:53 +0530717 raiseAlarm := false
718 if alarmReq.Status == "on" {
719 raiseAlarm = true
720 }
721 o.SendOMCIAlarmNotificationMsg(raiseAlarm, alarmReq.AlarmType)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800722 return nil
723}
724
725func (o *Onu) publishOmciEvent(msg bbsim.OmciMessage) {
Pragya Arya324337e2020-02-20 14:35:08 +0530726 if olt.PublishEvents {
Matteo Scandolob5913142021-03-19 16:10:18 -0700727 _, omciMsg, err := omcilib.ParseOpenOltOmciPacket(msg.OmciPkt.Data())
Pragya Arya324337e2020-02-20 14:35:08 +0530728 if err != nil {
729 log.Errorf("error in getting msgType %v", err)
730 return
731 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800732 if omciMsg.MessageType == omci.MibUploadRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530733 o.seqNumber = 0
734 publishEvent("MIB-upload-received", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
Matteo Scandolof9d43412021-01-12 11:11:34 -0800735 } else if omciMsg.MessageType == omci.MibUploadNextRequestType {
Pragya Arya324337e2020-02-20 14:35:08 +0530736 o.seqNumber++
737 if o.seqNumber > 290 {
738 publishEvent("MIB-upload-done", int32(o.PonPortID), int32(o.ID), common.OnuSnToString(o.SerialNumber))
739 }
740 }
741 }
742}
743
Matteo Scandolof9d43412021-01-12 11:11:34 -0800744// handleOmciRequest is responsible to parse the OMCI packets received from the openolt adapter
745// and generate the appropriate response to it
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200746func (o *Onu) handleOmciRequest(msg bbsim.OmciMessage, stream openolt.Openolt_EnableIndicationServer) error {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800747
Matteo Scandoloc559ef12019-08-20 13:24:21 -0700748 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700749 "omciMsgType": msg.OmciMsg.MessageType,
750 "transCorrId": strconv.FormatInt(int64(msg.OmciMsg.TransactionID), 16),
751 "DeviceIdent": msg.OmciMsg.DeviceIdentifier,
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -0700752 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -0700753 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -0800754 }).Trace("omci-message-decoded")
755
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000756 if o.OmciMsgCounter < maxOmciMsgCounter {
757 o.OmciMsgCounter++
758 } else {
759 o.OmciMsgCounter = 1
760 }
761 if o.OmciMsgCounter > o.OmciResponseRate {
762 onuLogger.WithFields(log.Fields{
763 "OmciMsgCounter": o.OmciMsgCounter,
764 "OmciResponseRate": o.OmciResponseRate,
765 "omciMsgType": msg.OmciMsg.MessageType,
Matteo Scandoloa96e2242021-09-28 10:13:17 -0700766 "txId": msg.OmciMsg.TransactionID,
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +0200767 }).Debug("skipping-omci-msg-response")
768 return fmt.Errorf("skipping-omci-msg-response-because-of-response-rate-%d", o.OmciResponseRate)
Holger Hildebrandtc10bab12021-04-27 09:23:48 +0000769 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800770 var responsePkt []byte
Girish Gowdrae2683102021-03-05 08:24:26 -0800771 var errResp error
Matteo Scandolob5913142021-03-19 16:10:18 -0700772 switch msg.OmciMsg.MessageType {
Matteo Scandolof9d43412021-01-12 11:11:34 -0800773 case omci.MibResetRequestType:
Matteo Scandolo992a23e2021-02-04 15:35:04 -0800774 onuLogger.WithFields(log.Fields{
775 "IntfId": o.PonPortID,
776 "OnuId": o.ID,
777 "SerialNumber": o.Sn(),
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700778 }).Debug("received-mib-reset-request")
Matteo Scandolob5913142021-03-19 16:10:18 -0700779 if responsePkt, errResp = omcilib.CreateMibResetResponse(msg.OmciMsg.TransactionID); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800780 o.MibDataSync = 0
Matteo Scandolo2fdc3b82021-04-23 15:27:21 -0700781
782 // if the MIB reset is successful then remove all the stored AllocIds and GemPorts
783 o.PonPort.removeAllocId(o.SerialNumber)
784 o.PonPort.removeGemPortBySn(o.SerialNumber)
Girish Gowdrae2683102021-03-05 08:24:26 -0800785 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800786 case omci.MibUploadRequestType:
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700787 responsePkt, _ = omcilib.CreateMibUploadResponse(msg.OmciMsg.TransactionID, o.MibDb.NumberOfCommands)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800788 case omci.MibUploadNextRequestType:
Matteo Scandoloef4e8f82021-05-17 11:20:49 -0700789 responsePkt, _ = omcilib.CreateMibUploadNextResponse(msg.OmciPkt, msg.OmciMsg, o.MibDataSync, o.MibDb)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800790 case omci.GetRequestType:
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700791 onuDown := o.AdminLockState == 1
Matteo Scandoloc00e97a2021-05-27 11:45:27 -0700792 responsePkt, _ = omcilib.CreateGetResponse(msg.OmciPkt, msg.OmciMsg, o.SerialNumber, o.MibDataSync, o.ActiveImageEntityId,
793 o.CommittedImageEntityId, o.StandbyImageVersion, o.ActiveImageVersion, o.CommittedImageVersion, onuDown)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800794 case omci.SetRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800795 success := true
Matteo Scandolob5913142021-03-19 16:10:18 -0700796 msgObj, _ := omcilib.ParseSetRequest(msg.OmciPkt)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800797 switch msgObj.EntityClass {
798 case me.PhysicalPathTerminationPointEthernetUniClassID:
799 // if we're Setting a PPTP state
Matteo Scandolo8a574812021-05-20 15:18:53 -0700800 // we need to send the appropriate alarm (handled in the UNI struct)
801 uni, err := o.FindUniByEntityId(msgObj.EntityInstance)
802 if err != nil {
803 onuLogger.Error(err)
804 success = false
805 } else {
806 // 1 locks the UNI, 0 unlocks it
Matteo Scandolof9d43412021-01-12 11:11:34 -0800807 adminState := msgObj.Attributes["AdministrativeState"].(uint8)
Matteo Scandolo8a574812021-05-20 15:18:53 -0700808 var err error
Himani Chawla13b1ee02021-03-15 01:43:53 +0530809 if adminState == 1 {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700810 err = uni.Disable()
Girish Gowdra996d81e2021-04-21 16:16:27 -0700811 } else {
Matteo Scandolo8a574812021-05-20 15:18:53 -0700812 err = uni.Enable()
Himani Chawla13b1ee02021-03-15 01:43:53 +0530813 }
Matteo Scandolo8a574812021-05-20 15:18:53 -0700814 if err != nil {
815 onuLogger.WithFields(log.Fields{
816 "IntfId": o.PonPortID,
817 "OnuId": o.ID,
818 "UniMeId": uni.MeId,
819 "UniId": uni.ID,
820 "SerialNumber": o.Sn(),
821 "Err": err.Error(),
822 }).Warn("cannot-change-uni-status")
Matteo Scandolof9d43412021-01-12 11:11:34 -0800823 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800824 }
Girish Gowdra1ddcb202021-06-25 12:17:09 -0700825 case me.OnuGClassID:
826 o.AdminLockState = msgObj.Attributes["AdministrativeState"].(uint8)
827 onuLogger.WithFields(log.Fields{
828 "IntfId": o.PonPortID,
829 "OnuId": o.ID,
830 "SerialNumber": o.Sn(),
831 "AdminLockState": o.AdminLockState,
832 }).Debug("set-onu-admin-lock-state")
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800833 case me.TContClassID:
834 allocId := msgObj.Attributes["AllocId"].(uint16)
835
836 // if the AllocId is 255 (0xFF) or 65535 (0xFFFF) it means we are removing it,
837 // otherwise we are adding it
838 if allocId == 255 || allocId == 65535 {
839 onuLogger.WithFields(log.Fields{
840 "IntfId": o.PonPortID,
841 "OnuId": o.ID,
842 "TContId": msgObj.EntityInstance,
843 "AllocId": allocId,
844 "SerialNumber": o.Sn(),
845 }).Trace("freeing-alloc-id-via-omci")
846 o.PonPort.removeAllocId(o.SerialNumber)
847 } else {
848 if used, sn := o.PonPort.isAllocIdAllocated(allocId); used {
849 onuLogger.WithFields(log.Fields{
850 "IntfId": o.PonPortID,
851 "OnuId": o.ID,
852 "AllocId": allocId,
853 "SerialNumber": o.Sn(),
854 }).Errorf("allocid-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
855 success = false
856 } else {
857 onuLogger.WithFields(log.Fields{
858 "IntfId": o.PonPortID,
859 "OnuId": o.ID,
860 "TContId": msgObj.EntityInstance,
861 "AllocId": allocId,
862 "SerialNumber": o.Sn(),
863 }).Trace("storing-alloc-id-via-omci")
864 o.PonPort.storeAllocId(allocId, o.SerialNumber)
865 }
866 }
867
868 }
869
870 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -0700871 if responsePkt, errResp = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800872 o.MibDataSync++
873 }
874 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700875 responsePkt, _ = omcilib.CreateSetResponse(msg.OmciPkt, msg.OmciMsg, me.AttributeFailure)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800876 }
877 case omci.CreateRequestType:
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800878 // check for GemPortNetworkCtp and make sure there are no duplicates on the same PON
879 var used bool
880 var sn *openolt.SerialNumber
Matteo Scandolob5913142021-03-19 16:10:18 -0700881 msgObj, err := omcilib.ParseCreateRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800882 if err == nil {
883 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
Matteo Scandolo973b0182021-04-08 11:24:42 -0700884 // GemPort 4069 is reserved for multicast and shared across ONUs
885 if msgObj.EntityInstance != 4069 {
886 if used, sn = o.PonPort.isGemPortAllocated(msgObj.EntityInstance); used {
887 onuLogger.WithFields(log.Fields{
888 "IntfId": o.PonPortID,
889 "OnuId": o.ID,
890 "GemPortId": msgObj.EntityInstance,
891 "SerialNumber": o.Sn(),
892 }).Errorf("gemport-already-allocated-to-onu-with-sn-%s", common.OnuSnToString(sn))
893 } else {
894 onuLogger.WithFields(log.Fields{
895 "IntfId": o.PonPortID,
896 "OnuId": o.ID,
897 "GemPortId": msgObj.EntityInstance,
898 "SerialNumber": o.Sn(),
899 }).Trace("storing-gem-port-id-via-omci")
900 o.PonPort.storeGemPort(msgObj.EntityInstance, o.SerialNumber)
901 }
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800902 }
903 }
904 }
905
906 // if the gemPort is valid then increment the MDS and return a successful response
907 // otherwise fail the request
908 // for now the CreateRequeste for the gemPort is the only one that can fail, if we start supporting multiple
909 // validation this check will need to be rewritten
910 if !used {
Matteo Scandolob5913142021-03-19 16:10:18 -0700911 if responsePkt, errResp = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800912 o.MibDataSync++
913 }
914 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -0700915 responsePkt, _ = omcilib.CreateCreateResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError)
Girish Gowdrae2683102021-03-05 08:24:26 -0800916 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800917 case omci.DeleteRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -0700918 msgObj, err := omcilib.ParseDeleteRequest(msg.OmciPkt)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -0800919 if err == nil {
920 if msgObj.EntityClass == me.GemPortNetworkCtpClassID {
921 onuLogger.WithFields(log.Fields{
922 "IntfId": o.PonPortID,
923 "OnuId": o.ID,
924 "GemPortId": msgObj.EntityInstance,
925 "SerialNumber": o.Sn(),
926 }).Trace("freeing-gem-port-id-via-omci")
927 o.PonPort.removeGemPort(msgObj.EntityInstance)
928 }
929 }
930
Matteo Scandolob5913142021-03-19 16:10:18 -0700931 if responsePkt, errResp = omcilib.CreateDeleteResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Girish Gowdrae2683102021-03-05 08:24:26 -0800932 o.MibDataSync++
933 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800934 case omci.RebootRequestType:
935
Matteo Scandolob5913142021-03-19 16:10:18 -0700936 responsePkt, _ = omcilib.CreateRebootResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolof9d43412021-01-12 11:11:34 -0800937
938 // powercycle the ONU
Matteo Scandolocedde462021-03-09 17:37:16 -0800939 // we run this in a separate goroutine so that
940 // the RebootRequestResponse is sent to VOLTHA
Matteo Scandolof9d43412021-01-12 11:11:34 -0800941 go func() {
Matteo Scandolocedde462021-03-09 17:37:16 -0800942 if err := o.Reboot(10 * time.Second); err != nil {
943 log.WithFields(log.Fields{
944 "IntfId": o.PonPortID,
945 "OnuId": o.ID,
946 "SerialNumber": o.Sn(),
947 "err": err,
948 }).Error("cannot-reboot-onu-after-omci-reboot-request")
949 }
Matteo Scandolof9d43412021-01-12 11:11:34 -0800950 }()
951 case omci.TestRequestType:
Girish Gowdra161d27a2021-05-05 12:01:44 -0700952 var classID me.ClassID
953 var omciResult me.Results
954 var instID uint16
955 responsePkt, errResp, classID, instID, omciResult = omcilib.CreateTestResponse(msg.OmciPkt, msg.OmciMsg)
956 // Send TestResult only in case the TestResponse omci result code is me.Success
957 if responsePkt != nil && errResp == nil && omciResult == me.Success {
958 if testResultPkt, err := omcilib.CreateTestResult(classID, instID, msg.OmciMsg.TransactionID); err == nil {
959 // send test results asynchronously
960 go func() {
961 // Send test results after a second to emulate async behavior
962 time.Sleep(1 * time.Second)
963 if testResultPkt != nil {
964 if err := o.sendOmciIndication(testResultPkt, msg.OmciMsg.TransactionID, stream); err != nil {
965 onuLogger.WithFields(log.Fields{
966 "IntfId": o.PonPortID,
967 "SerialNumber": o.Sn(),
968 "omciPacket": testResultPkt,
969 "msg.OmciMsgType": msg.OmciMsg.MessageType,
970 "transCorrId": msg.OmciMsg.TransactionID,
971 }).Errorf("failed-to-send-omci-message: %v", err)
972 }
973 }
974 }()
Matteo Scandolof9d43412021-01-12 11:11:34 -0800975 }
976 }
Girish Gowdraa539f522021-02-15 23:00:45 -0800977 case omci.SynchronizeTimeRequestType:
978 // MDS counter increment is not required for this message type
Matteo Scandolob5913142021-03-19 16:10:18 -0700979 responsePkt, _ = omcilib.CreateSyncTimeResponse(msg.OmciPkt, msg.OmciMsg)
Matteo Scandolocedde462021-03-09 17:37:16 -0800980 case omci.StartSoftwareDownloadRequestType:
981
982 o.ImageSoftwareReceivedSections = 0
983
Matteo Scandolob5913142021-03-19 16:10:18 -0700984 o.ImageSoftwareExpectedSections = omcilib.ComputeDownloadSectionsCount(msg.OmciPkt)
Matteo Scandolocedde462021-03-09 17:37:16 -0800985
Matteo Scandolob5913142021-03-19 16:10:18 -0700986 if responsePkt, errResp = omcilib.CreateStartSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -0800987 o.MibDataSync++
988 if err := o.InternalState.Event(OnuTxStartImageDownload); err != nil {
989 onuLogger.WithFields(log.Fields{
990 "OnuId": o.ID,
991 "IntfId": o.PonPortID,
992 "OnuSn": o.Sn(),
993 "Err": err.Error(),
994 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadStarted)
995 }
996 } else {
997 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -0700998 "OmciMsgType": msg.OmciMsg.MessageType,
999 "TransCorrId": msg.OmciMsg.TransactionID,
1000 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001001 "IntfId": o.PonPortID,
1002 "SerialNumber": o.Sn(),
1003 }).Error("error-while-processing-start-software-download-request")
1004 }
1005 case omci.DownloadSectionRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001006 if msgObj, err := omcilib.ParseDownloadSectionRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001007 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001008 "OmciMsgType": msg.OmciMsg.MessageType,
1009 "TransCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001010 "EntityInstance": msgObj.EntityInstance,
1011 "SectionNumber": msgObj.SectionNumber,
1012 "SectionData": msgObj.SectionData,
1013 }).Trace("received-download-section-request")
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001014 //Extracting the first 14 bytes to use as a version for this image.
1015 if o.ImageSoftwareReceivedSections == 0 {
1016 o.StandbyImageVersion = string(msgObj.SectionData[0:14])
1017 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001018 o.ImageSoftwareReceivedSections++
1019 if o.InternalState.Current() != OnuStateImageDownloadInProgress {
1020 if err := o.InternalState.Event(OnuTxProgressImageDownload); err != nil {
1021 onuLogger.WithFields(log.Fields{
1022 "OnuId": o.ID,
1023 "IntfId": o.PonPortID,
1024 "OnuSn": o.Sn(),
1025 "Err": err.Error(),
1026 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadInProgress)
1027 }
1028 }
1029 }
1030 case omci.DownloadSectionRequestWithResponseType:
1031 // NOTE we only need to respond if an ACK is requested
Matteo Scandolob5913142021-03-19 16:10:18 -07001032 responsePkt, errResp = omcilib.CreateDownloadSectionResponse(msg.OmciPkt, msg.OmciMsg)
1033 if errResp != nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001034 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001035 "OmciMsgType": msg.OmciMsg.MessageType,
1036 "TransCorrId": msg.OmciMsg.TransactionID,
1037 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001038 "IntfId": o.PonPortID,
1039 "SerialNumber": o.Sn(),
1040 }).Error("error-while-processing-create-download-section-response")
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +02001041 return fmt.Errorf("error-while-processing-create-download-section-response: %s", errResp.Error())
Matteo Scandolocedde462021-03-09 17:37:16 -08001042 }
1043 o.ImageSoftwareReceivedSections++
Matteo Scandolocedde462021-03-09 17:37:16 -08001044 case omci.EndSoftwareDownloadRequestType:
1045
1046 // In the startSoftwareDownload we get the image size and the window size.
1047 // We calculate how many DownloadSection we should receive and validate
1048 // that we got the correct amount when we receive this message
1049 success := true
1050 if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
1051 onuLogger.WithFields(log.Fields{
1052 "OnuId": o.ID,
1053 "IntfId": o.PonPortID,
1054 "OnuSn": o.Sn(),
1055 "ExpectedSections": o.ImageSoftwareExpectedSections,
1056 "ReceivedSections": o.ImageSoftwareReceivedSections,
1057 }).Errorf("onu-did-not-receive-all-image-sections")
1058 success = false
1059 }
1060
1061 if success {
Matteo Scandolob5913142021-03-19 16:10:18 -07001062 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001063 o.MibDataSync++
1064 if err := o.InternalState.Event(OnuTxCompleteImageDownload); err != nil {
1065 onuLogger.WithFields(log.Fields{
1066 "OnuId": o.ID,
1067 "IntfId": o.PonPortID,
1068 "OnuSn": o.Sn(),
1069 "Err": err.Error(),
1070 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadComplete)
1071 }
1072 } else {
1073 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001074 "OmciMsgType": msg.OmciMsg.MessageType,
1075 "TransCorrId": msg.OmciMsg.TransactionID,
1076 "Err": errResp.Error(),
Matteo Scandolocedde462021-03-09 17:37:16 -08001077 "IntfId": o.PonPortID,
1078 "SerialNumber": o.Sn(),
1079 }).Error("error-while-processing-end-software-download-request")
1080 }
1081 } else {
Matteo Scandolob5913142021-03-19 16:10:18 -07001082 if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001083 if err := o.InternalState.Event(OnuTxFailImageDownload); err != nil {
1084 onuLogger.WithFields(log.Fields{
1085 "OnuId": o.ID,
1086 "IntfId": o.PonPortID,
1087 "OnuSn": o.Sn(),
1088 "Err": err.Error(),
1089 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageDownloadError)
1090 }
1091 }
1092 }
Matteo Scandolocedde462021-03-09 17:37:16 -08001093 case omci.ActivateSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001094 if responsePkt, errResp = omcilib.CreateActivateSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001095 o.MibDataSync++
1096 if err := o.InternalState.Event(OnuTxActivateImage); err != nil {
1097 onuLogger.WithFields(log.Fields{
1098 "OnuId": o.ID,
1099 "IntfId": o.PonPortID,
1100 "OnuSn": o.Sn(),
1101 "Err": err.Error(),
1102 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageActivated)
1103 }
Matteo Scandolob5913142021-03-19 16:10:18 -07001104 if msgObj, err := omcilib.ParseActivateSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001105 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001106 previousActiveImage := o.ActiveImageVersion
1107 o.ActiveImageVersion = o.StandbyImageVersion
1108 o.StandbyImageVersion = previousActiveImage
Matteo Scandolocedde462021-03-09 17:37:16 -08001109 } else {
1110 onuLogger.Errorf("something-went-wrong-while-activating: %s", err)
1111 }
1112 onuLogger.WithFields(log.Fields{
1113 "OnuId": o.ID,
1114 "IntfId": o.PonPortID,
1115 "OnuSn": o.Sn(),
1116 "ActiveImageEntityId": o.ActiveImageEntityId,
1117 "CommittedImageEntityId": o.CommittedImageEntityId,
1118 }).Info("onu-software-image-activated")
1119
1120 // powercycle the ONU
1121 // we run this in a separate goroutine so that
1122 // the ActivateSoftwareResponse is sent to VOLTHA
1123 // NOTE do we need to wait before rebooting?
1124 go func() {
1125 if err := o.Reboot(10 * time.Second); err != nil {
1126 log.WithFields(log.Fields{
1127 "IntfId": o.PonPortID,
1128 "OnuId": o.ID,
1129 "SerialNumber": o.Sn(),
1130 "err": err,
1131 }).Error("cannot-reboot-onu-after-omci-activate-software-request")
1132 }
1133 }()
1134 }
1135 case omci.CommitSoftwareRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001136 if responsePkt, errResp = omcilib.CreateCommitSoftwareResponse(msg.OmciPkt, msg.OmciMsg); errResp == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001137 o.MibDataSync++
Matteo Scandolob5913142021-03-19 16:10:18 -07001138 if msgObj, err := omcilib.ParseCommitSoftwareRequest(msg.OmciPkt); err == nil {
Matteo Scandolocedde462021-03-09 17:37:16 -08001139 // TODO validate that the image to commit is:
1140 // - active
1141 // - not already committed
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001142 o.ActiveImageEntityId = msgObj.EntityInstance
Matteo Scandolocedde462021-03-09 17:37:16 -08001143 o.CommittedImageEntityId = msgObj.EntityInstance
Matteo Scandoloc00e97a2021-05-27 11:45:27 -07001144 //committed becomes standby
1145 o.StandbyImageVersion = o.CommittedImageVersion
1146 o.CommittedImageVersion = o.ActiveImageVersion
Matteo Scandolocedde462021-03-09 17:37:16 -08001147 } else {
1148 onuLogger.Errorf("something-went-wrong-while-committing: %s", err)
1149 }
1150 if err := o.InternalState.Event(OnuTxCommitImage); err != nil {
1151 onuLogger.WithFields(log.Fields{
1152 "OnuId": o.ID,
1153 "IntfId": o.PonPortID,
1154 "OnuSn": o.Sn(),
1155 "Err": err.Error(),
1156 }).Errorf("cannot-change-onu-internal-state-to-%s", OnuStateImageCommitted)
1157 }
1158 onuLogger.WithFields(log.Fields{
1159 "OnuId": o.ID,
1160 "IntfId": o.PonPortID,
1161 "OnuSn": o.Sn(),
1162 "ActiveImageEntityId": o.ActiveImageEntityId,
1163 "CommittedImageEntityId": o.CommittedImageEntityId,
1164 }).Info("onu-software-image-committed")
1165 }
Himani Chawla13b1ee02021-03-15 01:43:53 +05301166 case omci.GetAllAlarmsRequestType:
1167 // Reset the alarm sequence number on receiving get all alarms request.
1168 o.onuAlarmsInfoLock.Lock()
1169 for key, alarmInfo := range o.onuAlarmsInfo {
1170 // reset the alarm sequence no
1171 alarmInfo.SequenceNo = 0
1172 o.onuAlarmsInfo[key] = alarmInfo
1173 }
1174 o.onuAlarmsInfoLock.Unlock()
Matteo Scandolob5913142021-03-19 16:10:18 -07001175 responsePkt, _ = omcilib.CreateGetAllAlarmsResponse(msg.OmciMsg.TransactionID, o.onuAlarmsInfo)
Himani Chawla13b1ee02021-03-15 01:43:53 +05301176 case omci.GetAllAlarmsNextRequestType:
Matteo Scandolob5913142021-03-19 16:10:18 -07001177 if responsePkt, errResp = omcilib.CreateGetAllAlarmsNextResponse(msg.OmciPkt, msg.OmciMsg, o.onuAlarmsInfo); errResp != nil {
Himani Chawla13b1ee02021-03-15 01:43:53 +05301178 responsePkt = nil //Do not send any response for error case
1179 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001180 default:
Matteo Scandolocedde462021-03-09 17:37:16 -08001181 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001182 "omciBytes": hex.EncodeToString(msg.OmciPkt.Data()),
1183 "omciPkt": msg.OmciPkt,
1184 "omciMsgType": msg.OmciMsg.MessageType,
1185 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001186 "IntfId": o.PonPortID,
1187 "SerialNumber": o.Sn(),
1188 }).Warnf("OMCI-message-not-supported")
1189 }
1190
1191 if responsePkt != nil {
Matteo Scandolob5913142021-03-19 16:10:18 -07001192 if err := o.sendOmciIndication(responsePkt, msg.OmciMsg.TransactionID, stream); err != nil {
Matteo Scandolof9d43412021-01-12 11:11:34 -08001193 onuLogger.WithFields(log.Fields{
Matteo Scandolob5913142021-03-19 16:10:18 -07001194 "IntfId": o.PonPortID,
1195 "SerialNumber": o.Sn(),
1196 "omciPacket": responsePkt,
1197 "msg.OmciMsgType": msg.OmciMsg.MessageType,
1198 "transCorrId": msg.OmciMsg.TransactionID,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001199 }).Errorf("failed-to-send-omci-message: %v", err)
1200 }
1201 }
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001202
Pragya Arya324337e2020-02-20 14:35:08 +05301203 o.publishOmciEvent(msg)
Andrea Campanellabe1b7cf2021-04-30 09:53:40 +02001204 return nil
Matteo Scandolof9d43412021-01-12 11:11:34 -08001205}
Pragya Arya324337e2020-02-20 14:35:08 +05301206
Matteo Scandolof9d43412021-01-12 11:11:34 -08001207// sendOmciIndication takes an OMCI packet and sends it up to VOLTHA
1208func (o *Onu) sendOmciIndication(responsePkt []byte, txId uint16, stream bbsim.Stream) error {
1209 indication := &openolt.Indication_OmciInd{
1210 OmciInd: &openolt.OmciIndication{
1211 IntfId: o.PonPortID,
1212 OnuId: o.ID,
1213 Pkt: responsePkt,
1214 },
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001215 }
Matteo Scandolof9d43412021-01-12 11:11:34 -08001216 if err := stream.Send(&openolt.Indication{Data: indication}); err != nil {
1217 return fmt.Errorf("failed-to-send-omci-message: %v", err)
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001218 }
1219 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001220 "IntfId": o.PonPortID,
Matteo Scandolo27428702019-10-11 16:21:16 -07001221 "SerialNumber": o.Sn(),
Matteo Scandolof9d43412021-01-12 11:11:34 -08001222 "omciPacket": indication.OmciInd.Pkt,
1223 "transCorrId": txId,
1224 }).Trace("omci-message-sent")
1225 return nil
Matteo Scandoloc559ef12019-08-20 13:24:21 -07001226}
1227
Matteo Scandolo8a574812021-05-20 15:18:53 -07001228// FindUniById retrieves a UNI by ID
1229func (o *Onu) FindUniById(uniID uint32) (*UniPort, error) {
1230 for _, u := range o.UniPorts {
1231 uni := u.(*UniPort)
1232 if uni.ID == uniID {
1233 return uni, nil
1234 }
Matteo Scandolo27428702019-10-11 16:21:16 -07001235 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001236 return nil, fmt.Errorf("cannot-find-uni-with-id-%d-on-onu-%s", uniID, o.Sn())
1237}
1238
1239// FindUniByEntityId retrieves a uni by MeID (the OMCI entity ID)
1240func (o *Onu) FindUniByEntityId(meId uint16) (*UniPort, error) {
1241 entityId := omcilib.EntityID{}.FromUint16(meId)
1242 for _, u := range o.UniPorts {
1243 uni := u.(*UniPort)
1244 if uni.MeId.Equals(entityId) {
1245 return uni, nil
1246 }
1247 }
1248 return nil, fmt.Errorf("cannot-find-uni-with-meid-%s-on-onu-%s", entityId.ToString(), o.Sn())
Matteo Scandolo27428702019-10-11 16:21:16 -07001249}
1250
William Kurkian0418bc82019-11-06 12:16:24 -05001251func (o *Onu) SetID(id uint32) {
Matteo Scandolo583f17d2020-02-13 10:35:17 -08001252 onuLogger.WithFields(log.Fields{
1253 "IntfId": o.PonPortID,
1254 "OnuId": id,
1255 "SerialNumber": o.Sn(),
1256 }).Debug("Storing OnuId ")
William Kurkian0418bc82019-11-06 12:16:24 -05001257 o.ID = id
1258}
1259
Matteo Scandolof9d43412021-01-12 11:11:34 -08001260func (o *Onu) handleFlowAdd(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001261 onuLogger.WithFields(log.Fields{
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001262 "AllocId": msg.Flow.AllocId,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001263 "Cookie": msg.Flow.Cookie,
1264 "DstPort": msg.Flow.Classifier.DstPort,
1265 "FlowId": msg.Flow.FlowId,
1266 "FlowType": msg.Flow.FlowType,
1267 "GemportId": msg.Flow.GemportId,
1268 "InnerVlan": msg.Flow.Classifier.IVid,
1269 "IntfId": msg.Flow.AccessIntfId,
1270 "IpProto": msg.Flow.Classifier.IpProto,
1271 "OnuId": msg.Flow.OnuId,
1272 "OnuSn": o.Sn(),
1273 "OuterVlan": msg.Flow.Classifier.OVid,
1274 "PortNo": msg.Flow.PortNo,
1275 "SrcPort": msg.Flow.Classifier.SrcPort,
1276 "UniID": msg.Flow.UniId,
1277 "ClassifierEthType": fmt.Sprintf("%x", msg.Flow.Classifier.EthType),
1278 "ClassifierOPbits": msg.Flow.Classifier.OPbits,
1279 "ClassifierIVid": msg.Flow.Classifier.IVid,
1280 "ClassifierOVid": msg.Flow.Classifier.OVid,
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001281 "ReplicateFlow": msg.Flow.ReplicateFlow,
1282 "PbitToGemport": msg.Flow.PbitToGemport,
Matteo Scandoloedf30c72020-09-18 18:15:28 -07001283 }).Debug("OLT receives FlowAdd for ONU")
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001284
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001285 o.FlowIds = append(o.FlowIds, msg.Flow.FlowId)
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001286
1287 var gemPortId uint32
1288 if msg.Flow.ReplicateFlow {
1289 // This means that the OLT should replicate the flow for each PBIT, for BBSim it's enough to use the
1290 // first available gemport (we only need to send one packet)
1291 // NOTE different TP may create different mapping between PBits and GemPorts, this may require some changes
1292 gemPortId = msg.Flow.PbitToGemport[0]
1293 } else {
1294 // if replicateFlows is false, then the flow is carrying the correct GemPortId
1295 gemPortId = uint32(msg.Flow.GemportId)
1296 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001297
1298 uni, err := o.FindUniById(uint32(msg.Flow.UniId))
1299 if err != nil {
1300 onuLogger.WithFields(log.Fields{
1301 "IntfId": o.PonPortID,
1302 "OnuId": o.ID,
1303 "UniId": msg.Flow.UniId,
1304 "PortNo": msg.Flow.PortNo,
1305 "SerialNumber": o.Sn(),
1306 "FlowId": msg.Flow.FlowId,
1307 "FlowType": msg.Flow.FlowType,
1308 }).Error("cannot-find-uni-port-for-flow")
1309 }
1310
1311 uni.addGemPortToService(gemPortId, msg.Flow.Classifier.EthType, msg.Flow.Classifier.OVid, msg.Flow.Classifier.IVid)
1312 uni.StorePortNo(msg.Flow.PortNo)
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001313
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001314 if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeEAPOL) && msg.Flow.Classifier.OVid == 4091 {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001315 uni.HandleAuth()
Matteo Scandolo4b3fc7e2019-09-17 16:49:54 -07001316 } else if msg.Flow.Classifier.EthType == uint32(layers.EthernetTypeIPv4) &&
1317 msg.Flow.Classifier.SrcPort == uint32(68) &&
Matteo Scandolobd875b32020-09-18 17:46:31 -07001318 msg.Flow.Classifier.DstPort == uint32(67) {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001319 uni.HandleDhcp(uint8(msg.Flow.Classifier.OPbits), int(msg.Flow.Classifier.OVid))
Matteo Scandolo3bc73742019-08-20 14:04:04 -07001320 }
1321}
1322
Matteo Scandolof9d43412021-01-12 11:11:34 -08001323func (o *Onu) handleFlowRemove(msg bbsim.OnuFlowUpdateMessage) {
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001324 onuLogger.WithFields(log.Fields{
1325 "IntfId": o.PonPortID,
1326 "OnuId": o.ID,
1327 "SerialNumber": o.Sn(),
1328 "FlowId": msg.Flow.FlowId,
1329 "FlowType": msg.Flow.FlowType,
1330 }).Debug("ONU receives FlowRemove")
1331
1332 for idx, flow := range o.FlowIds {
1333 // If the gemport is found, delete it from local cache.
1334 if flow == msg.Flow.FlowId {
1335 o.FlowIds = append(o.FlowIds[:idx], o.FlowIds[idx+1:]...)
1336 break
1337 }
1338 }
1339
1340 if len(o.FlowIds) == 0 {
1341 onuLogger.WithFields(log.Fields{
1342 "IntfId": o.PonPortID,
1343 "OnuId": o.ID,
1344 "SerialNumber": o.Sn(),
1345 }).Info("Resetting GemPort")
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001346
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301347 // check if ONU delete is performed and
1348 // terminate the ONU's ProcessOnuMessages Go routine
Matteo Scandolocedde462021-03-09 17:37:16 -08001349 if o.InternalState.Current() == OnuStateDisabled {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301350 close(o.Channel)
1351 }
Matteo Scandoloeb6b5af2020-06-24 16:23:58 -07001352 }
1353}
1354
Matteo Scandolocedde462021-03-09 17:37:16 -08001355func (o *Onu) Reboot(timeout time.Duration) error {
1356 onuLogger.WithFields(log.Fields{
1357 "IntfId": o.PonPortID,
1358 "OnuId": o.ID,
1359 "SerialNumber": o.Sn(),
1360 }).Debug("shutting-down-onu")
1361 if err := o.HandleShutdownONU(); err != nil {
1362 return err
1363 }
1364 time.Sleep(timeout)
1365 onuLogger.WithFields(log.Fields{
1366 "IntfId": o.PonPortID,
1367 "OnuId": o.ID,
1368 "SerialNumber": o.Sn(),
1369 }).Debug("power-on-onu")
1370 if err := o.HandlePowerOnONU(); err != nil {
1371 return err
1372 }
1373 return nil
1374}
1375
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001376// BBR methods
1377
1378func sendOmciMsg(pktBytes []byte, intfId uint32, onuId uint32, sn *openolt.SerialNumber, msgType string, client openolt.OpenoltClient) {
1379 omciMsg := openolt.OmciMsg{
1380 IntfId: intfId,
1381 OnuId: onuId,
1382 Pkt: pktBytes,
1383 }
1384
1385 if _, err := client.OmciMsgOut(context.Background(), &omciMsg); err != nil {
1386 log.WithFields(log.Fields{
1387 "IntfId": intfId,
1388 "OnuId": onuId,
1389 "SerialNumber": common.OnuSnToString(sn),
1390 "Pkt": omciMsg.Pkt,
1391 }).Fatalf("Failed to send MIB Reset")
1392 }
1393 log.WithFields(log.Fields{
1394 "IntfId": intfId,
1395 "OnuId": onuId,
1396 "SerialNumber": common.OnuSnToString(sn),
1397 "Pkt": omciMsg.Pkt,
1398 }).Tracef("Sent OMCI message %s", msgType)
1399}
1400
1401func (onu *Onu) getNextTid(highPriority ...bool) uint16 {
1402 var next uint16
1403 if len(highPriority) > 0 && highPriority[0] {
1404 next = onu.hpTid
1405 onu.hpTid += 1
1406 if onu.hpTid < 0x8000 {
1407 onu.hpTid = 0x8000
1408 }
1409 } else {
1410 next = onu.tid
1411 onu.tid += 1
1412 if onu.tid >= 0x8000 {
1413 onu.tid = 1
1414 }
1415 }
1416 return next
1417}
1418
1419// TODO move this method in responders/omcisim
Matteo Scandolo8a574812021-05-20 15:18:53 -07001420// StartOmci is called in BBR to start the OMCI state machine
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001421func (o *Onu) StartOmci(client openolt.OpenoltClient) {
1422 mibReset, _ := omcilib.CreateMibResetRequest(o.getNextTid(false))
1423 sendOmciMsg(mibReset, o.PonPortID, o.ID, o.SerialNumber, "mibReset", client)
1424}
1425
Matteo Scandolof9d43412021-01-12 11:11:34 -08001426// handleOmciResponse is used in BBR to generate the OMCI packets the openolt-adapter would send to the device
1427func (o *Onu) handleOmciResponse(msg bbsim.OmciIndicationMessage, client openolt.OpenoltClient) {
1428
1429 // we need to encode the packet in HEX
1430 pkt := make([]byte, len(msg.OmciInd.Pkt)*2)
1431 hex.Encode(pkt, msg.OmciInd.Pkt)
1432 packet, omciMsg, err := omcilib.ParseOpenOltOmciPacket(pkt)
1433 if err != nil {
1434 log.WithFields(log.Fields{
1435 "IntfId": o.PonPortID,
1436 "SerialNumber": o.Sn(),
1437 "omciPacket": msg.OmciInd.Pkt,
1438 }).Error("BBR Cannot parse OMCI packet")
1439 }
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001440
1441 log.WithFields(log.Fields{
1442 "IntfId": msg.OmciInd.IntfId,
1443 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001444 "OnuSn": o.Sn(),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001445 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001446 "msgType": omciMsg.MessageType,
Anand S Katti09541352020-01-29 15:54:01 +05301447 }).Trace("ONU Receives OMCI Msg")
Matteo Scandolof9d43412021-01-12 11:11:34 -08001448 switch omciMsg.MessageType {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001449 default:
Matteo Scandolo813402b2019-10-23 19:24:52 -07001450 log.WithFields(log.Fields{
1451 "IntfId": msg.OmciInd.IntfId,
1452 "OnuId": msg.OmciInd.OnuId,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001453 "OnuSn": o.Sn(),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001454 "Pkt": msg.OmciInd.Pkt,
Matteo Scandolof9d43412021-01-12 11:11:34 -08001455 "msgType": omciMsg.MessageType,
Matteo Scandolo813402b2019-10-23 19:24:52 -07001456 }).Fatalf("unexpected frame: %v", packet)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001457 case omci.MibResetResponseType:
1458 mibUpload, _ := omcilib.CreateMibUploadRequest(o.getNextTid(false))
1459 sendOmciMsg(mibUpload, o.PonPortID, o.ID, o.SerialNumber, "mibUpload", client)
1460 case omci.MibUploadResponseType:
1461 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1462 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
1463 case omci.MibUploadNextResponseType:
1464 o.seqNumber++
Matteo Scandolo8a574812021-05-20 15:18:53 -07001465 // once the mibUpload is complete send a SetRequest for the PPTP to enable the UNI
1466 // NOTE that in BBR we only enable the first UNI
1467 if o.seqNumber == o.MibDb.NumberOfCommands {
1468 meId := omcilib.GenerateUniPortEntityId(1)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001469
Matteo Scandolo8a574812021-05-20 15:18:53 -07001470 meParams := me.ParamData{
1471 EntityID: meId.ToUint16(),
1472 Attributes: me.AttributeValueMap{"AdministrativeState": 0},
1473 }
1474 managedEntity, omciError := me.NewPhysicalPathTerminationPointEthernetUni(meParams)
1475 if omciError.GetError() != nil {
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001476 onuLogger.WithFields(log.Fields{
1477 "OnuId": o.ID,
1478 "IntfId": o.PonPortID,
1479 "OnuSn": o.Sn(),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001480 }).Fatal(omciError.GetError())
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001481 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001482
1483 setPPtp, _ := omcilib.CreateSetRequest(managedEntity, 1)
1484 sendOmciMsg(setPPtp, o.PonPortID, o.ID, o.SerialNumber, "setRquest", client)
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001485 } else {
1486 mibUploadNext, _ := omcilib.CreateMibUploadNextRequest(o.getNextTid(false), o.seqNumber)
1487 sendOmciMsg(mibUploadNext, o.PonPortID, o.ID, o.SerialNumber, "mibUploadNext", client)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001488 }
Matteo Scandolo8a574812021-05-20 15:18:53 -07001489 case omci.SetResponseType:
1490 // once we set the PPTP to active we can start sending flows
1491
1492 if err := o.InternalState.Event(BbrOnuTxSendEapolFlow); err != nil {
1493 onuLogger.WithFields(log.Fields{
1494 "OnuId": o.ID,
1495 "IntfId": o.PonPortID,
1496 "OnuSn": o.Sn(),
1497 }).Errorf("Error while transitioning ONU State %v", err)
1498 }
1499 case omci.AlarmNotificationType:
1500 log.Info("bbr-received-alarm")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001501 }
1502}
1503
1504func (o *Onu) sendEapolFlow(client openolt.OpenoltClient) {
1505
1506 classifierProto := openolt.Classifier{
1507 EthType: uint32(layers.EthernetTypeEAPOL),
1508 OVid: 4091,
1509 }
1510
1511 actionProto := openolt.Action{}
1512
1513 downstreamFlow := openolt.Flow{
1514 AccessIntfId: int32(o.PonPortID),
1515 OnuId: int32(o.ID),
Matteo Scandolo813402b2019-10-23 19:24:52 -07001516 UniId: int32(0), // NOTE do not hardcode this, we need to support multiple UNIs
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001517 FlowId: uint64(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001518 FlowType: "downstream",
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001519 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001520 Classifier: &classifierProto,
1521 Action: &actionProto,
1522 Priority: int32(100),
1523 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001524 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1525 // AllocId and GemPorts need to be unique per PON
1526 // for now use the ONU-ID, will need to change once we support multiple UNIs
1527 AllocId: int32(o.ID),
1528 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001529 }
1530
1531 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1532 log.WithFields(log.Fields{
1533 "IntfId": o.PonPortID,
1534 "OnuId": o.ID,
1535 "FlowId": downstreamFlow.FlowId,
1536 "PortNo": downstreamFlow.PortNo,
1537 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001538 "Err": err,
Matteo Scandolob0e3e622020-04-23 17:00:29 -07001539 }).Fatalf("Failed to add EAPOL Flow")
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001540 }
1541 log.WithFields(log.Fields{
1542 "IntfId": o.PonPortID,
1543 "OnuId": o.ID,
1544 "FlowId": downstreamFlow.FlowId,
1545 "PortNo": downstreamFlow.PortNo,
1546 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1547 }).Info("Sent EAPOL Flow")
1548}
1549
1550func (o *Onu) sendDhcpFlow(client openolt.OpenoltClient) {
Matteo Scandolo4a036262020-08-17 15:56:13 -07001551
Matteo Scandolo8a574812021-05-20 15:18:53 -07001552 // BBR only works with a single UNI and a single service (ATT HSIA)
1553 hsia := o.UniPorts[0].(*UniPort).Services[0].(*Service)
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001554 classifierProto := openolt.Classifier{
1555 EthType: uint32(layers.EthernetTypeIPv4),
1556 SrcPort: uint32(68),
1557 DstPort: uint32(67),
Matteo Scandolo4a036262020-08-17 15:56:13 -07001558 OVid: uint32(hsia.CTag),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001559 OPbits: 255,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001560 }
1561
1562 actionProto := openolt.Action{}
1563
1564 downstreamFlow := openolt.Flow{
1565 AccessIntfId: int32(o.PonPortID),
1566 OnuId: int32(o.ID),
Matteo Scandolo8a574812021-05-20 15:18:53 -07001567 UniId: int32(0), // BBR only supports a single UNI
Matteo Scandolo4f4ac792020-10-01 16:33:21 -07001568 FlowId: uint64(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001569 FlowType: "downstream",
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001570 NetworkIntfId: int32(0),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001571 Classifier: &classifierProto,
1572 Action: &actionProto,
1573 Priority: int32(100),
1574 Cookie: uint64(o.ID),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001575 PortNo: o.ID, // NOTE we are using this to map an incoming packetIndication to an ONU
1576 // AllocId and GemPorts need to be unique per PON
1577 // for now use the ONU-ID, will need to change once we support multiple UNIs
1578 AllocId: int32(o.ID),
1579 GemportId: int32(o.ID),
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001580 }
1581
1582 if _, err := client.FlowAdd(context.Background(), &downstreamFlow); err != nil {
1583 log.WithFields(log.Fields{
1584 "IntfId": o.PonPortID,
1585 "OnuId": o.ID,
1586 "FlowId": downstreamFlow.FlowId,
1587 "PortNo": downstreamFlow.PortNo,
1588 "SerialNumber": common.OnuSnToString(o.SerialNumber),
Matteo Scandolo4b077aa2021-02-16 17:33:37 -08001589 "Err": err,
Matteo Scandolo40e067f2019-10-16 16:59:41 -07001590 }).Fatalf("Failed to send DHCP Flow")
1591 }
1592 log.WithFields(log.Fields{
1593 "IntfId": o.PonPortID,
1594 "OnuId": o.ID,
1595 "FlowId": downstreamFlow.FlowId,
1596 "PortNo": downstreamFlow.PortNo,
1597 "SerialNumber": common.OnuSnToString(o.SerialNumber),
1598 }).Info("Sent DHCP Flow")
1599}
Pragya Arya8bdb4532020-03-02 17:08:09 +05301600
1601// DeleteFlow method search and delete flowKey from the onu flows slice
1602func (onu *Onu) DeleteFlow(key FlowKey) {
1603 for pos, flowKey := range onu.Flows {
1604 if flowKey == key {
1605 // delete the flowKey by shifting all flowKeys by one
1606 onu.Flows = append(onu.Flows[:pos], onu.Flows[pos+1:]...)
1607 t := make([]FlowKey, len(onu.Flows))
1608 copy(t, onu.Flows)
1609 onu.Flows = t
1610 break
1611 }
1612 }
1613}
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301614
1615func (onu *Onu) ReDiscoverOnu() {
1616 // Wait for few seconds to be sure of the cleanup
1617 time.Sleep(5 * time.Second)
1618
1619 onuLogger.WithFields(log.Fields{
1620 "IntfId": onu.PonPortID,
1621 "OnuId": onu.ID,
1622 "OnuSn": onu.Sn(),
1623 }).Debug("Send ONU Re-Discovery")
1624
1625 // ONU Re-Discovery
Matteo Scandolocedde462021-03-09 17:37:16 -08001626 if err := onu.InternalState.Event(OnuTxInitialize); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301627 log.WithFields(log.Fields{
1628 "IntfId": onu.PonPortID,
1629 "OnuSn": onu.Sn(),
1630 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001631 }).Infof("Failed to transition ONU to %s state: %s", OnuStateInitialized, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301632 }
1633
Matteo Scandolocedde462021-03-09 17:37:16 -08001634 if err := onu.InternalState.Event(OnuTxDiscover); err != nil {
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301635 log.WithFields(log.Fields{
1636 "IntfId": onu.PonPortID,
1637 "OnuSn": onu.Sn(),
1638 "OnuId": onu.ID,
Matteo Scandolocedde462021-03-09 17:37:16 -08001639 }).Infof("Failed to transition ONU to %s state: %s", OnuStateDiscovered, err.Error())
Hardik Windlass7b3405b2020-07-08 15:10:05 +05301640 }
1641}
Matteo Scandolo4a036262020-08-17 15:56:13 -07001642
Matteo Scandolo8a574812021-05-20 15:18:53 -07001643// deprecated, delegate this to the uniPort
Matteo Scandolo4a036262020-08-17 15:56:13 -07001644func (onu *Onu) findServiceByMacAddress(macAddress net.HardwareAddr) (*Service, error) {
Matteo Scandolo8a574812021-05-20 15:18:53 -07001645 // FIXME is there a better way to avoid this loop?
1646 for _, u := range onu.UniPorts {
1647 uni := u.(*UniPort)
1648 for _, s := range uni.Services {
1649 service := s.(*Service)
1650 if service.HwAddress.String() == macAddress.String() {
1651 return service, nil
1652 }
Matteo Scandolo4a036262020-08-17 15:56:13 -07001653 }
1654 }
1655 return nil, fmt.Errorf("cannot-find-service-with-mac-address-%s", macAddress.String())
1656}
Himani Chawla13b1ee02021-03-15 01:43:53 +05301657
Matteo Scandolo8a574812021-05-20 15:18:53 -07001658func (onu *Onu) findUniByPortNo(portNo uint32) (*UniPort, error) {
1659 for _, u := range onu.UniPorts {
1660 uni := u.(*UniPort)
1661 if uni.PortNo == portNo {
1662 return uni, nil
1663 }
1664 }
1665 return nil, fmt.Errorf("cannot-find-uni-with-port-no-%d", portNo)
1666}
1667
Himani Chawla13b1ee02021-03-15 01:43:53 +05301668func (o *Onu) SendOMCIAlarmNotificationMsg(raiseOMCIAlarm bool, alarmType string) {
1669 switch alarmType {
1670 case "ONU_ALARM_LOS":
1671 msg := bbsim.Message{
1672 Type: bbsim.UniStatusAlarm,
1673 Data: bbsim.UniStatusAlarmMessage{
1674 OnuSN: o.SerialNumber,
1675 OnuID: o.ID,
1676 EntityID: 257,
1677 RaiseOMCIAlarm: raiseOMCIAlarm,
1678 },
1679 }
1680 o.Channel <- msg
1681 }
1682
1683}
1684
1685func (o *Onu) IncrementAlarmSequenceNumber(key omcilib.OnuAlarmInfoMapKey) uint8 {
1686 o.onuAlarmsInfoLock.Lock()
1687 defer o.onuAlarmsInfoLock.Unlock()
1688 if alarmInfo, ok := o.onuAlarmsInfo[key]; ok {
1689 if alarmInfo.SequenceNo == 255 {
1690 alarmInfo.SequenceNo = 1
1691 } else {
1692 alarmInfo.SequenceNo++
1693 }
1694 o.onuAlarmsInfo[key] = alarmInfo
1695 return alarmInfo.SequenceNo
1696 } else {
1697 // This is the first time alarm notification message is being sent
1698 o.onuAlarmsInfo[key] = omcilib.OnuAlarmInfo{
1699 SequenceNo: 1,
1700 }
1701 return 1
1702 }
1703}