blob: d968edb77299c04a8fb8ded94a3c99213b0ea1d5 [file] [log] [blame]
mpagenko3dbcdd22020-07-22 07:38:45 +00001/*
2 * Copyright 2020-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
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "errors"
23 "strconv"
24 "time"
25
26 "github.com/looplab/fsm"
27
28 "github.com/opencord/omci-lib-go"
29 me "github.com/opencord/omci-lib-go/generated"
30 "github.com/opencord/voltha-lib-go/v3/pkg/log"
31 //ic "github.com/opencord/voltha-protos/v3/go/inter_container"
32 //"github.com/opencord/voltha-protos/v3/go/openflow_13"
33 //"github.com/opencord/voltha-protos/v3/go/voltha"
34)
35
36//UniPonAniConfigFsm defines the structure for the state machine to lock/unlock the ONU UNI ports via OMCI
37type UniPonAniConfigFsm struct {
38 pOmciCC *OmciCC
39 pOnuUniPort *OnuUniPort
40 pUniTechProf *OnuUniTechProf
41 pOnuDB *OnuDeviceDB
42 techProfileID uint16
43 requestEvent OnuDeviceEvent
44 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
45 pAdaptFsm *AdapterFsm
46 chSuccess chan<- uint8
47 procStep uint8
48 chanSet bool
49 mapperSP0ID uint16
50 macBPCD0ID uint16
51 tcont0ID uint16
52 alloc0ID uint16
53 gemPortXID []uint16
54 upQueueXID []uint16
55 downQueueXID []uint16
56}
57
58//NewUniPonAniConfigFsm is the 'constructor' for the state machine to lock/unlock the ONU UNI ports via OMCI
59func NewUniPonAniConfigFsm(apDevOmciCC *OmciCC, apUniPort *OnuUniPort, apUniTechProf *OnuUniTechProf,
60 apOnuDB *OnuDeviceDB, aTechProfileID uint16, aRequestEvent OnuDeviceEvent, aName string,
61 aDeviceID string, aCommChannel chan Message) *UniPonAniConfigFsm {
62 instFsm := &UniPonAniConfigFsm{
63 pOmciCC: apDevOmciCC,
64 pOnuUniPort: apUniPort,
65 pUniTechProf: apUniTechProf,
66 pOnuDB: apOnuDB,
67 techProfileID: aTechProfileID,
68 requestEvent: aRequestEvent,
69 chanSet: false,
70 }
71 instFsm.pAdaptFsm = NewAdapterFsm(aName, aDeviceID, aCommChannel)
72 if instFsm.pAdaptFsm == nil {
73 logger.Errorw("UniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
74 "device-id": aDeviceID})
75 return nil
76 }
77
78 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
79 "disabled",
80 fsm.Events{
81
82 {Name: "start", Src: []string{"disabled"}, Dst: "starting"},
83
84 //Note: .1p-Mapper and MBPCD might also have multi instances (per T-Cont) - by now only one 1 T-Cont considered!
85 {Name: "start_config", Src: []string{"starting"}, Dst: "creatingDot1PMapper"},
86 {Name: "rx_dot1pmap_cresp", Src: []string{"creatingDot1PMapper"}, Dst: "creatingMBPCD"},
87 {Name: "rx_mbpcd_resp", Src: []string{"creatingMBPCD"}, Dst: "settingTconts"},
88 {Name: "rx_tconts_resp", Src: []string{"settingTconts"}, Dst: "creatingGemNCTPs"},
89 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
90 {Name: "rx_gemntcps_resp", Src: []string{"creatingGemNCTPs"}, Dst: "creatingGemIWs"},
91 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
92 {Name: "rx_gemiws_resp", Src: []string{"creatingGemIWs"}, Dst: "settingPQs"},
93 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
94 {Name: "rx_prioqs_resp", Src: []string{"settingPQs"}, Dst: "settingDot1PMapper"},
95 {Name: "rx_dot1pmap_sresp", Src: []string{"settingDot1PMapper"}, Dst: "aniConfigDone"},
96
97 {Name: "timeout_simple", Src: []string{
98 "creatingDot1PMapper", "creatingMBPCD", "settingTconts", "settingDot1PMapper"}, Dst: "starting"},
99 {Name: "timeout_mids", Src: []string{
100 "creatingGemNCTPs", "creatingGemIWs", "settingPQs"}, Dst: "starting"},
101
102 // exceptional treatment for all states except "resetting"
103 {Name: "reset", Src: []string{"starting", "creatingDot1PMapper", "creatingMBPCD",
104 "settingTconts", "creatingGemNCTPs", "creatingGemIWs", "settingPQs", "settingDot1PMapper",
105 "aniConfigDone"}, Dst: "resetting"},
106 // the only way to get to resource-cleared disabled state again is via "resseting"
107 {Name: "restart", Src: []string{"resetting"}, Dst: "disabled"},
108 },
109
110 fsm.Callbacks{
111 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
112 "enter_starting": func(e *fsm.Event) { instFsm.enterConfigStartingState(e) },
113 "enter_creatingDot1PMapper": func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(e) },
114 "enter_creatingMBPCD": func(e *fsm.Event) { instFsm.enterCreatingMBPCD(e) },
115 "enter_settingTconts": func(e *fsm.Event) { instFsm.enterSettingTconts(e) },
116 "enter_creatingGemNCTPs": func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(e) },
117 "enter_creatingGemIWs": func(e *fsm.Event) { instFsm.enterCreatingGemIWs(e) },
118 "enter_settingPQs": func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
119 "enter_settingDot1PMapper": func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
120 "enter_aniConfigDone": func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
121 "enter_resetting": func(e *fsm.Event) { instFsm.enterResettingState(e) },
122 },
123 )
124 if instFsm.pAdaptFsm.pFsm == nil {
125 logger.Errorw("UniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
126 "device-id": aDeviceID})
127 return nil
128 }
129
130 logger.Infow("UniPonAniConfigFsm created", log.Fields{"device-id": aDeviceID})
131 return instFsm
132}
133
134//SetFsmCompleteChannel sets the requested channel and channel result for transfer on success
135func (oFsm *UniPonAniConfigFsm) SetFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
136 oFsm.chSuccess = aChSuccess
137 oFsm.procStep = aProcStep
138 oFsm.chanSet = true
139}
140
141func (oFsm *UniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
142 logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
143 "device-id": oFsm.pAdaptFsm.deviceID})
144 // in case the used channel is not yet defined (can be re-used after restarts)
145 if oFsm.omciMIdsResponseReceived == nil {
146 oFsm.omciMIdsResponseReceived = make(chan bool)
147 logger.Debug("UniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
148 } else {
149 // as we may 're-use' this instance of FSM and the connected channel
150 // make sure there is no 'lingering' request in the already existing channel:
151 // (simple loop sufficient as we are the only receiver)
152 for len(oFsm.omciMIdsResponseReceived) > 0 {
153 <-oFsm.omciMIdsResponseReceived
154 }
155 }
156 // start go routine for processing of LockState messages
157 go oFsm.ProcessOmciAniMessages()
158
159 //let the state machine run forward from here directly
160 pConfigAniStateAFsm := oFsm.pAdaptFsm
161 if pConfigAniStateAFsm != nil {
162 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
163 go func(a_pAFsm *AdapterFsm) {
164 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
165 //stick to pythonAdapter numbering scheme
166 //index 0 in naming refers to possible usage of multiple instances (later)
167 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + oFsm.techProfileID
168 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityId) + oFsm.techProfileID
169 oFsm.tcont0ID = 0x8001 //TODO!: for now fixed, but target is to use value from MibUpload (mibDB)
170 oFsm.alloc0ID = (*(oFsm.pUniTechProf.mapPonAniConfig[uint32(oFsm.pOnuUniPort.uniId)]))[0].tcontParams.allocID
171 //TODO!! this is just for the first GemPort right now - needs update
172 oFsm.gemPortXID = append(oFsm.gemPortXID,
173 (*(oFsm.pUniTechProf.mapPonAniConfig[uint32(oFsm.pOnuUniPort.uniId)]))[0].mapGemPortParams[0].gemPortID)
174 oFsm.upQueueXID = append(oFsm.upQueueXID, 0x8001) //TODO!: for now fixed, but target is to use value from MibUpload (mibDB)
175 //TODO!: for now fixed, but target is to use value from MibUpload (mibDB), also TechProf setting dependency may exist!
176 oFsm.downQueueXID = append(oFsm.downQueueXID, 1)
177
178 a_pAFsm.pFsm.Event("start_config")
179 }
180 }(pConfigAniStateAFsm)
181 }
182}
183
184func (oFsm *UniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
185 logger.Debugw("UniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
186 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
187 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
188 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
189 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
190 //accept also nil as (error) return value for writing to LastTx
191 // - this avoids misinterpretation of new received OMCI messages
192 oFsm.pOmciCC.pLastTxMeInstance = meInstance
193}
194
195func (oFsm *UniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
196 logger.Debugw("UniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
197 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
198 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
199 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
200 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
201 meParams := me.ParamData{
202 EntityID: oFsm.macBPCD0ID,
203 Attributes: me.AttributeValueMap{
204 "BridgeIdPointer": bridgePtr,
205 "PortNum": 0xFF, //fixed unique ANI side indication
206 "TpType": 3, //for .1PMapper
207 "TpPointer": oFsm.mapperSP0ID,
208 },
209 }
210 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
211 oFsm.pAdaptFsm.commChan, meParams)
212 //accept also nil as (error) return value for writing to LastTx
213 // - this avoids misinterpretation of new received OMCI messages
214 oFsm.pOmciCC.pLastTxMeInstance = meInstance
215
216}
217
218func (oFsm *UniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
219 logger.Debugw("UniPonAniConfigFsm Tx Set::Tcont", log.Fields{
220 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
221 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
222 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
223 meParams := me.ParamData{
224 EntityID: oFsm.tcont0ID,
225 Attributes: me.AttributeValueMap{
226 "AllocId": oFsm.alloc0ID,
227 },
228 }
229 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
230 oFsm.pAdaptFsm.commChan, meParams)
231 //accept also nil as (error) return value for writing to LastTx
232 // - this avoids misinterpretation of new received OMCI messages
233 oFsm.pOmciCC.pLastTxMeInstance = meInstance
234}
235
236func (oFsm *UniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
237 //TODO!! this is just for the first GemPort right now - needs update
238 logger.Debugw("UniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
239 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
240 go oFsm.performCreatingGemNCTPs()
241}
242
243func (oFsm *UniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
244 logger.Debugw("UniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
245 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
246 go oFsm.performCreatingGemIWs()
247}
248
249func (oFsm *UniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
250 logger.Debugw("UniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
251 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
252 go oFsm.performSettingPQs()
253}
254
255func (oFsm *UniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
256 logger.Debugw("UniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
257 "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
258
259 //TODO!! in MultiGemPort constellation the IwTpPtr setting will get variable -f(Prio) based on pUniTechProf
260 logger.Debugw("UniPonAniConfigFsm Tx Set::1pMapper SingleGem", log.Fields{
261 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
262 "GemIwTpPtr": strconv.FormatInt(int64(oFsm.gemPortXID[0]), 16),
263 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
264 meParams := me.ParamData{
265 EntityID: oFsm.mapperSP0ID,
266 Attributes: me.AttributeValueMap{
267 "InterworkTpPointerForPBitPriority0": oFsm.gemPortXID[0],
268 "InterworkTpPointerForPBitPriority1": oFsm.gemPortXID[0],
269 "InterworkTpPointerForPBitPriority2": oFsm.gemPortXID[0],
270 "InterworkTpPointerForPBitPriority3": oFsm.gemPortXID[0],
271 "InterworkTpPointerForPBitPriority4": oFsm.gemPortXID[0],
272 "InterworkTpPointerForPBitPriority5": oFsm.gemPortXID[0],
273 "InterworkTpPointerForPBitPriority6": oFsm.gemPortXID[0],
274 "InterworkTpPointerForPBitPriority7": oFsm.gemPortXID[0],
275 },
276 }
277 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
278 oFsm.pAdaptFsm.commChan, meParams)
279 //accept also nil as (error) return value for writing to LastTx
280 // - this avoids misinterpretation of new received OMCI messages
281 oFsm.pOmciCC.pLastTxMeInstance = meInstance
282}
283
284func (oFsm *UniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
285
286 //mirror the chanSet state as it will be reset by FSM reset
287 loChanSet := oFsm.chanSet
288
289 //let's reset the state machine in order to release all resources now
290 pConfigAniStateAFsm := oFsm.pAdaptFsm
291 if pConfigAniStateAFsm != nil {
292 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
293 go func(a_pAFsm *AdapterFsm) {
294 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
295 a_pAFsm.pFsm.Event("reset")
296 }
297 }(pConfigAniStateAFsm)
298 }
299
300 logger.Debugw("UniPonAniConfigFsm send dh event notification", log.Fields{
301 "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
302 //use DeviceHandler event notification directly
303 oFsm.pOmciCC.pBaseDeviceHandler.DeviceProcStatusUpdate(oFsm.requestEvent)
304
305 if loChanSet {
306 // indicate processing done to the caller
307 logger.Debugw("UniPonAniConfigFsm processingDone on channel", log.Fields{
308 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
309 oFsm.chSuccess <- oFsm.procStep
310 }
311}
312
313func (oFsm *UniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
314 logger.Debugw("UniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
315 oFsm.chanSet = false //reset the internal channel state
316 pConfigAniStateAFsm := oFsm.pAdaptFsm
317 if pConfigAniStateAFsm != nil {
318 // abort running message processing
319 fsmAbortMsg := Message{
320 Type: TestMsg,
321 Data: TestMessage{
322 TestMessageVal: AbortMessageProcessing,
323 },
324 }
325 pConfigAniStateAFsm.commChan <- fsmAbortMsg
326
327 //try to restart the FSM to 'disabled', decouple event transfer
328 go func(a_pAFsm *AdapterFsm) {
329 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
330 a_pAFsm.pFsm.Event("restart")
331 }
332 }(pConfigAniStateAFsm)
333 }
334}
335
336func (oFsm *UniPonAniConfigFsm) ProcessOmciAniMessages( /*ctx context.Context*/ ) {
337 logger.Debugw("Start UniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
338loop:
339 for {
340 select {
341 // case <-ctx.Done():
342 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.pAdaptFsm.deviceID})
343 // break loop
344 case message, ok := <-oFsm.pAdaptFsm.commChan:
345 if !ok {
346 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
347 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
348 oFsm.pAdaptFsm.pFsm.Event("reset")
349 break loop
350 }
351 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
352
353 switch message.Type {
354 case TestMsg:
355 msg, _ := message.Data.(TestMessage)
356 if msg.TestMessageVal == AbortMessageProcessing {
357 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
358 break loop
359 }
360 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "MessageVal": msg.TestMessageVal})
361 case OMCI:
362 msg, _ := message.Data.(OmciMessage)
363 oFsm.handleOmciAniConfigMessage(msg)
364 default:
365 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
366 "message.Type": message.Type})
367 }
368 }
369 }
370 logger.Infow("End UniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
371}
372
373func (oFsm *UniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
374 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
375 "msgType": msg.OmciMsg.MessageType})
376
377 switch msg.OmciMsg.MessageType {
378 case omci.CreateResponseType:
379 {
380 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
381 if msgLayer == nil {
382 logger.Error("Omci Msg layer could not be detected for CreateResponse")
383 return
384 }
385 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
386 if !msgOk {
387 logger.Error("Omci Msg layer could not be assigned for CreateResponse")
388 return
389 }
390 logger.Debugw("CreateResponse Data", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
391 if msgObj.Result != me.Success {
392 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
393 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
394 return
395 }
396 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
397 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
398 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
399 // if, then something like:
400 //oFsm.pOnuDB.StoreMe(msgObj)
401
402 // maybe we can use just the same eventName for different state transitions like "forward"
403 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
404 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
405 case "Ieee8021PMapperServiceProfile":
406 { // let the FSM proceed ...
407 oFsm.pAdaptFsm.pFsm.Event("rx_dot1pmap_cresp")
408 }
409 case "MacBridgePortConfigurationData":
410 { // let the FSM proceed ...
411 oFsm.pAdaptFsm.pFsm.Event("rx_mbpcd_resp")
412 }
413 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
414 { // let aniConfig Multi-Id processing proceed by stopping the wait function
415 oFsm.omciMIdsResponseReceived <- true
416 }
417 }
418 }
419 } //CreateResponseType
420 case omci.SetResponseType:
421 {
422 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
423 if msgLayer == nil {
424 logger.Error("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse")
425 return
426 }
427 msgObj, msgOk := msgLayer.(*omci.SetResponse)
428 if !msgOk {
429 logger.Error("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse")
430 return
431 }
432 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
433 if msgObj.Result != me.Success {
434 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
435 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
436 return
437 }
438 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
439 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
440 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
441 // if, then something like:
442 //oFsm.pOnuDB.StoreMe(msgObj)
443
444 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
445 case "TCont":
446 { // let the FSM proceed ...
447 oFsm.pAdaptFsm.pFsm.Event("rx_tconts_resp")
448 }
449 case "PriorityQueue":
450 { // let the PrioQueue init proceed by stopping the wait function
451 oFsm.omciMIdsResponseReceived <- true
452 }
453 case "Ieee8021PMapperServiceProfile":
454 { // let the FSM proceed ...
455 oFsm.pAdaptFsm.pFsm.Event("rx_dot1pmap_sresp")
456 }
457 }
458 }
459 } //SetResponseType
460 default:
461 {
462 logger.Errorw("UniPonAniConfigFsm - Rx OMCI unhandled MsgType", log.Fields{"omciMsgType": msg.OmciMsg.MessageType})
463 return
464 }
465 }
466}
467
468func (oFsm *UniPonAniConfigFsm) performCreatingGemNCTPs() {
469 //TODO!! this is just for the first GemPort right now - needs update
470 // .. for gemPort in range gemPortXID
471 logger.Infow("UniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
472 "EntitytId": strconv.FormatInt(int64(oFsm.gemPortXID[0]), 16),
473 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
474 "device-id": oFsm.pAdaptFsm.deviceID})
475 meParams := me.ParamData{
476 EntityID: oFsm.gemPortXID[0],
477 Attributes: me.AttributeValueMap{
478 "PortId": oFsm.gemPortXID[0], //same as EntityID
479 "TContPointer": oFsm.tcont0ID,
480 "Direction": (*(oFsm.pUniTechProf.mapPonAniConfig[uint32(oFsm.pOnuUniPort.uniId)]))[0].mapGemPortParams[0].direction,
481 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
482 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
483 "TrafficManagementPointerForUpstream": oFsm.upQueueXID[0], //might be different in wrr-only Setup - tcont0ID
484 "PriorityQueuePointerForDownStream": oFsm.downQueueXID[0],
485 },
486 }
487 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
488 oFsm.pAdaptFsm.commChan, meParams)
489 //accept also nil as (error) return value for writing to LastTx
490 // - this avoids misinterpretation of new received OMCI messages
491 oFsm.pOmciCC.pLastTxMeInstance = meInstance
492
493 //verify response
494 err := oFsm.waitforOmciResponse()
495 if err != nil {
496 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
497 log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "GemIndex": 0}) //running index in loop later!
498 oFsm.pAdaptFsm.pFsm.Event("reset")
499 return
500 }
501 //for all GemPortID's ports - later
502
503 // if Config has been done for all GemPort instances let the FSM proceed
504 logger.Debugw("GemNWCtp create loop finished", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID})
505 oFsm.pAdaptFsm.pFsm.Event("rx_gemntcps_resp")
506 return
507}
508
509func (oFsm *UniPonAniConfigFsm) performCreatingGemIWs() {
510 //TODO!! this is just for the first GemPort right now - needs update
511 // .. for gemPort in range gemPortXID
512 logger.Infow("UniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
513 "EntitytId": strconv.FormatInt(int64(oFsm.gemPortXID[0]), 16),
514 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
515 "device-id": oFsm.pAdaptFsm.deviceID})
516 meParams := me.ParamData{
517 EntityID: oFsm.gemPortXID[0],
518 Attributes: me.AttributeValueMap{
519 "GemPortNetworkCtpConnectivityPointer": oFsm.gemPortXID[0], //same as EntityID, see above
520 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
521 "ServiceProfilePointer": oFsm.mapperSP0ID,
522 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
523 "GalProfilePointer": galEthernetEID,
524 },
525 }
526 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
527 oFsm.pAdaptFsm.commChan, meParams)
528 //accept also nil as (error) return value for writing to LastTx
529 // - this avoids misinterpretation of new received OMCI messages
530 oFsm.pOmciCC.pLastTxMeInstance = meInstance
531
532 //verify response
533 err := oFsm.waitforOmciResponse()
534 if err != nil {
535 logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
536 log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "GemIndex": 0}) //running index in loop later!
537 oFsm.pAdaptFsm.pFsm.Event("reset")
538 return
539 }
540 //for all GemPortID's ports - later
541
542 // if Config has been done for all GemPort instances let the FSM proceed
543 logger.Debugw("GemIwTp create loop finished", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID})
544 oFsm.pAdaptFsm.pFsm.Event("rx_gemiws_resp")
545 return
546}
547
548func (oFsm *UniPonAniConfigFsm) performSettingPQs() {
549 //TODO!! this is just for the first upstream PrioQueue right now - needs update
550 //TODO!! implementation is restricted to WRR setting on the TrafficScheduler/Tcont
551 // SP setting would allow relatedPort(Prio) setting in case ONU supports config (ONU-2G QOS)
552
553 // .. for prioQueu in range upQueueXID
554 weight := (*(oFsm.pUniTechProf.mapPonAniConfig[uint32(oFsm.pOnuUniPort.uniId)]))[0].mapGemPortParams[0].queueWeight
555 logger.Infow("UniPonAniConfigFsm Tx Set::PrioQueue", log.Fields{
556 "EntitytId": strconv.FormatInt(int64(oFsm.upQueueXID[0]), 16),
557 "Weight": weight,
558 "device-id": oFsm.pAdaptFsm.deviceID})
559 meParams := me.ParamData{
560 EntityID: oFsm.upQueueXID[0],
561 Attributes: me.AttributeValueMap{
562 "Weight": weight,
563 },
564 }
565 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
566 oFsm.pAdaptFsm.commChan, meParams)
567 //accept also nil as (error) return value for writing to LastTx
568 // - this avoids misinterpretation of new received OMCI messages
569 oFsm.pOmciCC.pLastTxMeInstance = meInstance
570
571 //verify response
572 err := oFsm.waitforOmciResponse()
573 if err != nil {
574 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
575 log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "QueueIndex": 0}) //running index in loop later!
576 oFsm.pAdaptFsm.pFsm.Event("reset")
577 return
578 }
579 //for all upstream prioQueus - later
580
581 // if Config has been done for all PrioQueue instances let the FSM proceed
582 logger.Debugw("PrioQueue set loop finished", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID})
583 oFsm.pAdaptFsm.pFsm.Event("rx_prioqs_resp")
584 return
585}
586
587func (oFsm *UniPonAniConfigFsm) waitforOmciResponse() error {
588 select {
589 // maybe be also some outside cancel (but no context modelled for the moment ...)
590 // case <-ctx.Done():
591 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
592 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
593 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
594 return errors.New("UniPonAniConfigFsm multi entity timeout")
595 case success := <-oFsm.omciMIdsResponseReceived:
596 if success == true {
597 logger.Debug("UniPonAniConfigFsm multi entity response received")
598 return nil
599 }
600 // should not happen so far
601 logger.Warnw("UniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
602 return errors.New("UniPonAniConfigFsm multi entity responseError")
603 }
604}