blob: b15281849f5b80985740025ce48d5b8b0e926f2a [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
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000026 "github.com/cevaris/ordered_map"
mpagenko3dbcdd22020-07-22 07:38:45 +000027 "github.com/looplab/fsm"
mpagenko3dbcdd22020-07-22 07:38:45 +000028 "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
mpagenko1cc3cb42020-07-27 15:24:38 +000036const (
37 // events of config PON ANI port FSM
38 aniEvStart = "uniEvStart"
39 aniEvStartConfig = "aniEvStartConfig"
mpagenkodff5dda2020-08-28 11:52:01 +000040 aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
mpagenko1cc3cb42020-07-27 15:24:38 +000041 aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
42 aniEvRxTcontsResp = "aniEvRxTcontsResp"
43 aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
44 aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
45 aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
mpagenkodff5dda2020-08-28 11:52:01 +000046 aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
mpagenko1cc3cb42020-07-27 15:24:38 +000047 aniEvTimeoutSimple = "aniEvTimeoutSimple"
48 aniEvTimeoutMids = "aniEvTimeoutMids"
49 aniEvReset = "aniEvReset"
50 aniEvRestart = "aniEvRestart"
51)
52const (
53 // states of config PON ANI port FSM
54 aniStDisabled = "aniStDisabled"
55 aniStStarting = "aniStStarting"
56 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
57 aniStCreatingMBPCD = "aniStCreatingMBPCD"
58 aniStSettingTconts = "aniStSettingTconts"
59 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
60 aniStCreatingGemIWs = "aniStCreatingGemIWs"
61 aniStSettingPQs = "aniStSettingPQs"
62 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
63 aniStConfigDone = "aniStConfigDone"
64 aniStResetting = "aniStResetting"
65)
66
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000067type ponAniGemPortAttribs struct {
68 gemPortID uint16
69 upQueueID uint16
70 downQueueID uint16
71 direction uint8
72 qosPolicy string
73 weight uint8
74 pbitString string
75}
76
mpagenko1cc3cb42020-07-27 15:24:38 +000077//UniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
mpagenko3dbcdd22020-07-22 07:38:45 +000078type UniPonAniConfigFsm struct {
79 pOmciCC *OmciCC
80 pOnuUniPort *OnuUniPort
81 pUniTechProf *OnuUniTechProf
82 pOnuDB *OnuDeviceDB
83 techProfileID uint16
84 requestEvent OnuDeviceEvent
85 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
86 pAdaptFsm *AdapterFsm
mpagenko1cc3cb42020-07-27 15:24:38 +000087 aniConfigCompleted bool
mpagenko3dbcdd22020-07-22 07:38:45 +000088 chSuccess chan<- uint8
89 procStep uint8
90 chanSet bool
91 mapperSP0ID uint16
92 macBPCD0ID uint16
93 tcont0ID uint16
94 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000095 gemPortAttribsSlice []ponAniGemPortAttribs
mpagenko3dbcdd22020-07-22 07:38:45 +000096}
97
mpagenko1cc3cb42020-07-27 15:24:38 +000098//NewUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
mpagenko3dbcdd22020-07-22 07:38:45 +000099func NewUniPonAniConfigFsm(apDevOmciCC *OmciCC, apUniPort *OnuUniPort, apUniTechProf *OnuUniTechProf,
100 apOnuDB *OnuDeviceDB, aTechProfileID uint16, aRequestEvent OnuDeviceEvent, aName string,
101 aDeviceID string, aCommChannel chan Message) *UniPonAniConfigFsm {
102 instFsm := &UniPonAniConfigFsm{
mpagenko1cc3cb42020-07-27 15:24:38 +0000103 pOmciCC: apDevOmciCC,
104 pOnuUniPort: apUniPort,
105 pUniTechProf: apUniTechProf,
106 pOnuDB: apOnuDB,
107 techProfileID: aTechProfileID,
108 requestEvent: aRequestEvent,
109 aniConfigCompleted: false,
110 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000111 }
112 instFsm.pAdaptFsm = NewAdapterFsm(aName, aDeviceID, aCommChannel)
113 if instFsm.pAdaptFsm == nil {
114 logger.Errorw("UniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
115 "device-id": aDeviceID})
116 return nil
117 }
118
119 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000120 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000121 fsm.Events{
122
mpagenko1cc3cb42020-07-27 15:24:38 +0000123 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000124
125 //Note: .1p-Mapper and MBPCD might also have multi instances (per T-Cont) - by now only one 1 T-Cont considered!
mpagenko1cc3cb42020-07-27 15:24:38 +0000126 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000127 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000128 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
129 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000130 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000131 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000132 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000133 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000134 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000135 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000136 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000137
mpagenko1cc3cb42020-07-27 15:24:38 +0000138 {Name: aniEvTimeoutSimple, Src: []string{
139 aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper}, Dst: aniStStarting},
140 {Name: aniEvTimeoutMids, Src: []string{
141 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000142
mpagenko1cc3cb42020-07-27 15:24:38 +0000143 // exceptional treatment for all states except aniStResetting
144 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
145 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
146 aniStConfigDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000147 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000148 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000149 },
150
151 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000152 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
153 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(e) },
154 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(e) },
155 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(e) },
156 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(e) },
157 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(e) },
158 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(e) },
159 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
160 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
161 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
162 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(e) },
163 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000164 },
165 )
166 if instFsm.pAdaptFsm.pFsm == nil {
167 logger.Errorw("UniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
168 "device-id": aDeviceID})
169 return nil
170 }
171
172 logger.Infow("UniPonAniConfigFsm created", log.Fields{"device-id": aDeviceID})
173 return instFsm
174}
175
176//SetFsmCompleteChannel sets the requested channel and channel result for transfer on success
177func (oFsm *UniPonAniConfigFsm) SetFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
178 oFsm.chSuccess = aChSuccess
179 oFsm.procStep = aProcStep
180 oFsm.chanSet = true
181}
182
183func (oFsm *UniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
184 logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
185 "device-id": oFsm.pAdaptFsm.deviceID})
186 // in case the used channel is not yet defined (can be re-used after restarts)
187 if oFsm.omciMIdsResponseReceived == nil {
188 oFsm.omciMIdsResponseReceived = make(chan bool)
189 logger.Debug("UniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
190 } else {
191 // as we may 're-use' this instance of FSM and the connected channel
192 // make sure there is no 'lingering' request in the already existing channel:
193 // (simple loop sufficient as we are the only receiver)
194 for len(oFsm.omciMIdsResponseReceived) > 0 {
195 <-oFsm.omciMIdsResponseReceived
196 }
197 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000198 //ensure internal slices are empty (which might be set from previous run) - release memory
199 oFsm.gemPortAttribsSlice = nil
200
mpagenko3dbcdd22020-07-22 07:38:45 +0000201 // start go routine for processing of LockState messages
mpagenkodff5dda2020-08-28 11:52:01 +0000202 go oFsm.processOmciAniMessages()
mpagenko3dbcdd22020-07-22 07:38:45 +0000203
204 //let the state machine run forward from here directly
205 pConfigAniStateAFsm := oFsm.pAdaptFsm
206 if pConfigAniStateAFsm != nil {
207 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
208 go func(a_pAFsm *AdapterFsm) {
209 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
210 //stick to pythonAdapter numbering scheme
211 //index 0 in naming refers to possible usage of multiple instances (later)
212 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + oFsm.techProfileID
213 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityId) + oFsm.techProfileID
mpagenko3dbcdd22020-07-22 07:38:45 +0000214
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000215 // For the time beeing: if there are multiple T-Conts on the ONU the first one from the entityID-ordered list is used
216 // TODO!: if more T-Conts have to be supported (tcontXID!), then use the first instances of the entity-ordered list
217 // or use the py code approach, which might be a bit more complicated, but also more secure, as it
218 // ensures that the selected T-Cont also has queues (which I would assume per definition from ONU, but who knows ...)
219 // so this approach would search the (sorted) upstream PrioQueue list and use the T-Cont (if available) from highest Bytes
220 // or sndHighByte of relatedPort Attribute (T-Cont Reference) and in case of multiple TConts find the next free TContIndex
221 // that way from PrioQueue.relatedPort list
222 if tcontInstKeys := oFsm.pOnuDB.GetSortedInstKeys(me.TContClassID); len(tcontInstKeys) > 0 {
223 oFsm.tcont0ID = tcontInstKeys[0]
224 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
225 "device-id": oFsm.pAdaptFsm.deviceID})
226 } else {
divyadesai4d299552020-08-18 07:13:49 +0000227 logger.Warnw("No TCont instances found", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000228 }
mpagenkodff5dda2020-08-28 11:52:01 +0000229 oFsm.alloc0ID = (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniId]))[0].tcontParams.allocID
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000230 loGemPortAttribs := ponAniGemPortAttribs{}
231 //for all TechProfile set GemIndices
mpagenkodff5dda2020-08-28 11:52:01 +0000232 for _, gemEntry := range (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniId]))[0].mapGemPortParams {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000233 //collect all GemConfigData in a seperate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
234
235 if queueInstKeys := oFsm.pOnuDB.GetSortedInstKeys(me.PriorityQueueClassID); len(queueInstKeys) > 0 {
236
237 loGemPortAttribs.gemPortID = gemEntry.gemPortID
238 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
239 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
240 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
241 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
242
243 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
244 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniId,
245 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
246 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
247 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
248 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniId + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
249
250 usQueueFound := false
251 dsQueueFound := false
252 for _, mgmtEntityId := range queueInstKeys {
253 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityId); meAttributes != nil {
254 returnVal := meAttributes["RelatedPort"]
255 if returnVal != nil {
Holger Hildebrandt2ff21f12020-08-13 14:38:02 +0000256 if relatedPort, err := oFsm.pOnuDB.GetUint32Attrib(returnVal); err == nil {
257 if relatedPort == usQrelPortMask {
258 loGemPortAttribs.upQueueID = mgmtEntityId
259 logger.Debugw("UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
260 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.pAdaptFsm.deviceID})
261 usQueueFound = true
262 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityId < 0x8000 {
263 loGemPortAttribs.downQueueID = mgmtEntityId
264 logger.Debugw("DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
265 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.pAdaptFsm.deviceID})
266 dsQueueFound = true
267 }
268 if usQueueFound && dsQueueFound {
269 break
270 }
271 } else {
272 logger.Warnw("Could not convert attribute value", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000273 }
274 } else {
mpagenkodff5dda2020-08-28 11:52:01 +0000275 logger.Warnw("'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000276 }
277 } else {
278 logger.Warnw("No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
divyadesai4d299552020-08-18 07:13:49 +0000279 "mgmtEntityId": mgmtEntityId, "device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000280 }
281 }
282 } else {
divyadesai4d299552020-08-18 07:13:49 +0000283 logger.Warnw("No PriorityQueue instances found", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000284 }
285 loGemPortAttribs.direction = gemEntry.direction
286 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
287 loGemPortAttribs.weight = gemEntry.queueWeight
288 loGemPortAttribs.pbitString = gemEntry.pbitString
289
Holger Hildebrandt2ff21f12020-08-13 14:38:02 +0000290 logger.Debugw("prio-related GemPort attributes:", log.Fields{
291 "gemPortID": loGemPortAttribs.gemPortID,
292 "upQueueID": loGemPortAttribs.upQueueID,
293 "downQueueID": loGemPortAttribs.downQueueID,
294 "pbitString": loGemPortAttribs.pbitString,
295 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000296 })
297
298 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
299 }
mpagenko1cc3cb42020-07-27 15:24:38 +0000300 a_pAFsm.pFsm.Event(aniEvStartConfig)
mpagenko3dbcdd22020-07-22 07:38:45 +0000301 }
302 }(pConfigAniStateAFsm)
303 }
304}
305
306func (oFsm *UniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
307 logger.Debugw("UniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
308 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
309 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
310 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
311 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
312 //accept also nil as (error) return value for writing to LastTx
313 // - this avoids misinterpretation of new received OMCI messages
314 oFsm.pOmciCC.pLastTxMeInstance = meInstance
315}
316
317func (oFsm *UniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
318 logger.Debugw("UniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
319 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
320 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
321 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
322 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
323 meParams := me.ParamData{
324 EntityID: oFsm.macBPCD0ID,
325 Attributes: me.AttributeValueMap{
326 "BridgeIdPointer": bridgePtr,
327 "PortNum": 0xFF, //fixed unique ANI side indication
328 "TpType": 3, //for .1PMapper
329 "TpPointer": oFsm.mapperSP0ID,
330 },
331 }
332 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
333 oFsm.pAdaptFsm.commChan, meParams)
334 //accept also nil as (error) return value for writing to LastTx
335 // - this avoids misinterpretation of new received OMCI messages
336 oFsm.pOmciCC.pLastTxMeInstance = meInstance
337
338}
339
340func (oFsm *UniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
341 logger.Debugw("UniPonAniConfigFsm Tx Set::Tcont", log.Fields{
342 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
343 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
344 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
345 meParams := me.ParamData{
346 EntityID: oFsm.tcont0ID,
347 Attributes: me.AttributeValueMap{
348 "AllocId": oFsm.alloc0ID,
349 },
350 }
351 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
352 oFsm.pAdaptFsm.commChan, meParams)
353 //accept also nil as (error) return value for writing to LastTx
354 // - this avoids misinterpretation of new received OMCI messages
355 oFsm.pOmciCC.pLastTxMeInstance = meInstance
356}
357
358func (oFsm *UniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000359 logger.Debugw("UniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
360 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
361 go oFsm.performCreatingGemNCTPs()
362}
363
364func (oFsm *UniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
365 logger.Debugw("UniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
366 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
367 go oFsm.performCreatingGemIWs()
368}
369
370func (oFsm *UniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
371 logger.Debugw("UniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
372 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
373 go oFsm.performSettingPQs()
374}
375
376func (oFsm *UniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
377 logger.Debugw("UniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
378 "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
379
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000380 logger.Debugw("UniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
381 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
382 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
383
mpagenko3dbcdd22020-07-22 07:38:45 +0000384 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000385 EntityID: oFsm.mapperSP0ID,
386 Attributes: make(me.AttributeValueMap, 0),
mpagenko3dbcdd22020-07-22 07:38:45 +0000387 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000388
389 //assign the GemPorts according to the configured Prio
390 var loPrioGemPortArray [8]uint16
391 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
392 for i := 0; i < 8; i++ {
393 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
394 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
395 if prio == 1 { // Check this p-bit is set
396 if loPrioGemPortArray[i] == 0 {
397 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
398 } else {
399 logger.Warnw("UniPonAniConfigFsm PrioString not unique", log.Fields{
400 "device-id": oFsm.pAdaptFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
401 "SetGemPort": loPrioGemPortArray[i]})
402 }
403 }
404 } else {
405 logger.Warnw("UniPonAniConfigFsm PrioString evaluation error", log.Fields{
406 "device-id": oFsm.pAdaptFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
407 "prioString": gemPortAttribs.pbitString, "position": i})
408 }
409
410 }
411 }
412 var foundIwPtr bool = false
413 if loPrioGemPortArray[0] != 0 {
414 foundIwPtr = true
415 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
416 "IwPtr for Prio0": strconv.FormatInt(int64(loPrioGemPortArray[0]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
417 meParams.Attributes["InterworkTpPointerForPBitPriority0"] = loPrioGemPortArray[0]
418 }
419 if loPrioGemPortArray[1] != 0 {
420 foundIwPtr = true
421 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
422 "IwPtr for Prio1": strconv.FormatInt(int64(loPrioGemPortArray[1]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
423 meParams.Attributes["InterworkTpPointerForPBitPriority1"] = loPrioGemPortArray[1]
424 }
425 if loPrioGemPortArray[2] != 0 {
426 foundIwPtr = true
427 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
428 "IwPtr for Prio2": strconv.FormatInt(int64(loPrioGemPortArray[2]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
429 meParams.Attributes["InterworkTpPointerForPBitPriority2"] = loPrioGemPortArray[2]
430 }
431 if loPrioGemPortArray[3] != 0 {
432 foundIwPtr = true
433 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
434 "IwPtr for Prio3": strconv.FormatInt(int64(loPrioGemPortArray[3]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
435 meParams.Attributes["InterworkTpPointerForPBitPriority3"] = loPrioGemPortArray[3]
436 }
437 if loPrioGemPortArray[4] != 0 {
438 foundIwPtr = true
439 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
440 "IwPtr for Prio4": strconv.FormatInt(int64(loPrioGemPortArray[4]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
441 meParams.Attributes["InterworkTpPointerForPBitPriority4"] = loPrioGemPortArray[4]
442 }
443 if loPrioGemPortArray[5] != 0 {
444 foundIwPtr = true
445 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
446 "IwPtr for Prio5": strconv.FormatInt(int64(loPrioGemPortArray[5]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
447 meParams.Attributes["InterworkTpPointerForPBitPriority5"] = loPrioGemPortArray[5]
448 }
449 if loPrioGemPortArray[6] != 0 {
450 foundIwPtr = true
451 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
452 "IwPtr for Prio6": strconv.FormatInt(int64(loPrioGemPortArray[6]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
453 meParams.Attributes["InterworkTpPointerForPBitPriority6"] = loPrioGemPortArray[6]
454 }
455 if loPrioGemPortArray[7] != 0 {
456 foundIwPtr = true
457 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
458 "IwPtr for Prio7": strconv.FormatInt(int64(loPrioGemPortArray[7]), 16), "device-id": oFsm.pAdaptFsm.deviceID})
459 meParams.Attributes["InterworkTpPointerForPBitPriority7"] = loPrioGemPortArray[7]
460 }
461 if foundIwPtr == false {
462 logger.Errorw("UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
463 "device-id": oFsm.pAdaptFsm.deviceID})
464 //let's reset the state machine in order to release all resources now
465 pConfigAniStateAFsm := oFsm.pAdaptFsm
466 if pConfigAniStateAFsm != nil {
467 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
468 go func(a_pAFsm *AdapterFsm) {
469 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
470 a_pAFsm.pFsm.Event(aniEvReset)
471 }
472 }(pConfigAniStateAFsm)
473 }
474 }
475
mpagenko3dbcdd22020-07-22 07:38:45 +0000476 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
477 oFsm.pAdaptFsm.commChan, meParams)
478 //accept also nil as (error) return value for writing to LastTx
479 // - this avoids misinterpretation of new received OMCI messages
480 oFsm.pOmciCC.pLastTxMeInstance = meInstance
481}
482
483func (oFsm *UniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
484
mpagenko1cc3cb42020-07-27 15:24:38 +0000485 oFsm.aniConfigCompleted = true
mpagenko3dbcdd22020-07-22 07:38:45 +0000486
487 //let's reset the state machine in order to release all resources now
488 pConfigAniStateAFsm := oFsm.pAdaptFsm
489 if pConfigAniStateAFsm != nil {
490 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
491 go func(a_pAFsm *AdapterFsm) {
492 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000493 a_pAFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000494 }
495 }(pConfigAniStateAFsm)
496 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000497}
498
499func (oFsm *UniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
500 logger.Debugw("UniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000501
mpagenko3dbcdd22020-07-22 07:38:45 +0000502 pConfigAniStateAFsm := oFsm.pAdaptFsm
503 if pConfigAniStateAFsm != nil {
504 // abort running message processing
505 fsmAbortMsg := Message{
506 Type: TestMsg,
507 Data: TestMessage{
508 TestMessageVal: AbortMessageProcessing,
509 },
510 }
511 pConfigAniStateAFsm.commChan <- fsmAbortMsg
512
513 //try to restart the FSM to 'disabled', decouple event transfer
514 go func(a_pAFsm *AdapterFsm) {
515 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko1cc3cb42020-07-27 15:24:38 +0000516 a_pAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000517 }
518 }(pConfigAniStateAFsm)
519 }
520}
521
mpagenko1cc3cb42020-07-27 15:24:38 +0000522func (oFsm *UniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
523 logger.Debugw("UniPonAniConfigFsm enters disabled state", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
524
525 if oFsm.aniConfigCompleted {
526 logger.Debugw("UniPonAniConfigFsm send dh event notification", log.Fields{
527 "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
528 //use DeviceHandler event notification directly
529 oFsm.pOmciCC.pBaseDeviceHandler.DeviceProcStatusUpdate(oFsm.requestEvent)
530 oFsm.aniConfigCompleted = false
531 }
mpagenkodff5dda2020-08-28 11:52:01 +0000532 //store that the UNI related techProfile processing is done for the given Profile and Uni
533 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniId, true)
534 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
535 go oFsm.pOmciCC.pBaseDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
mpagenko1cc3cb42020-07-27 15:24:38 +0000536
537 if oFsm.chanSet {
538 // indicate processing done to the caller
539 logger.Debugw("UniPonAniConfigFsm processingDone on channel", log.Fields{
540 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
541 oFsm.chSuccess <- oFsm.procStep
542 oFsm.chanSet = false //reset the internal channel state
543 }
544
545}
546
mpagenkodff5dda2020-08-28 11:52:01 +0000547func (oFsm *UniPonAniConfigFsm) processOmciAniMessages( /*ctx context.Context*/ ) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000548 logger.Debugw("Start UniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
549loop:
550 for {
551 select {
552 // case <-ctx.Done():
553 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.pAdaptFsm.deviceID})
554 // break loop
555 case message, ok := <-oFsm.pAdaptFsm.commChan:
556 if !ok {
557 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
558 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
mpagenko1cc3cb42020-07-27 15:24:38 +0000559 oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000560 break loop
561 }
562 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
563
564 switch message.Type {
565 case TestMsg:
566 msg, _ := message.Data.(TestMessage)
567 if msg.TestMessageVal == AbortMessageProcessing {
568 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
569 break loop
570 }
571 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "MessageVal": msg.TestMessageVal})
572 case OMCI:
573 msg, _ := message.Data.(OmciMessage)
574 oFsm.handleOmciAniConfigMessage(msg)
575 default:
576 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
577 "message.Type": message.Type})
578 }
579 }
580 }
581 logger.Infow("End UniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
582}
583
584func (oFsm *UniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
585 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
586 "msgType": msg.OmciMsg.MessageType})
587
588 switch msg.OmciMsg.MessageType {
589 case omci.CreateResponseType:
590 {
591 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
592 if msgLayer == nil {
593 logger.Error("Omci Msg layer could not be detected for CreateResponse")
594 return
595 }
596 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
597 if !msgOk {
598 logger.Error("Omci Msg layer could not be assigned for CreateResponse")
599 return
600 }
divyadesai4d299552020-08-18 07:13:49 +0000601 logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
mpagenko3dbcdd22020-07-22 07:38:45 +0000602 if msgObj.Result != me.Success {
603 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
604 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
605 return
606 }
607 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
608 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
mpagenko3dbcdd22020-07-22 07:38:45 +0000609 // maybe we can use just the same eventName for different state transitions like "forward"
610 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
611 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
612 case "Ieee8021PMapperServiceProfile":
613 { // let the FSM proceed ...
mpagenkodff5dda2020-08-28 11:52:01 +0000614 oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000615 }
616 case "MacBridgePortConfigurationData":
617 { // let the FSM proceed ...
mpagenko1cc3cb42020-07-27 15:24:38 +0000618 oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000619 }
620 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
621 { // let aniConfig Multi-Id processing proceed by stopping the wait function
622 oFsm.omciMIdsResponseReceived <- true
623 }
624 }
625 }
626 } //CreateResponseType
627 case omci.SetResponseType:
628 {
629 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
630 if msgLayer == nil {
631 logger.Error("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse")
632 return
633 }
634 msgObj, msgOk := msgLayer.(*omci.SetResponse)
635 if !msgOk {
636 logger.Error("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse")
637 return
638 }
divyadesai4d299552020-08-18 07:13:49 +0000639 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
mpagenko3dbcdd22020-07-22 07:38:45 +0000640 if msgObj.Result != me.Success {
641 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
642 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
643 return
644 }
645 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
646 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
647 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
648 // if, then something like:
649 //oFsm.pOnuDB.StoreMe(msgObj)
650
651 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
652 case "TCont":
653 { // let the FSM proceed ...
mpagenko1cc3cb42020-07-27 15:24:38 +0000654 oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000655 }
656 case "PriorityQueue":
657 { // let the PrioQueue init proceed by stopping the wait function
658 oFsm.omciMIdsResponseReceived <- true
659 }
660 case "Ieee8021PMapperServiceProfile":
661 { // let the FSM proceed ...
mpagenkodff5dda2020-08-28 11:52:01 +0000662 oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000663 }
664 }
665 }
666 } //SetResponseType
667 default:
668 {
669 logger.Errorw("UniPonAniConfigFsm - Rx OMCI unhandled MsgType", log.Fields{"omciMsgType": msg.OmciMsg.MessageType})
670 return
671 }
672 }
673}
674
675func (oFsm *UniPonAniConfigFsm) performCreatingGemNCTPs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000676 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
677 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
678 logger.Debugw("UniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
679 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
680 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
681 "device-id": oFsm.pAdaptFsm.deviceID})
682 meParams := me.ParamData{
683 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
684 Attributes: me.AttributeValueMap{
685 "PortId": gemPortAttribs.gemPortID,
686 "TContPointer": oFsm.tcont0ID,
687 "Direction": gemPortAttribs.direction,
688 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
689 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
690 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
691 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
692 },
693 }
694 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
695 oFsm.pAdaptFsm.commChan, meParams)
696 //accept also nil as (error) return value for writing to LastTx
697 // - this avoids misinterpretation of new received OMCI messages
698 oFsm.pOmciCC.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000699
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000700 //verify response
701 err := oFsm.waitforOmciResponse()
702 if err != nil {
703 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000704 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "GemIndex": gemIndex})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000705 oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
706 return
707 }
708 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000709
710 // if Config has been done for all GemPort instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000711 logger.Debugw("GemNWCtp create loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000712 oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000713 return
714}
715
716func (oFsm *UniPonAniConfigFsm) performCreatingGemIWs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000717 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
718 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
719 logger.Debugw("UniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
720 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
721 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
722 "device-id": oFsm.pAdaptFsm.deviceID})
723 meParams := me.ParamData{
724 EntityID: gemPortAttribs.gemPortID,
725 Attributes: me.AttributeValueMap{
726 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
727 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
728 "ServiceProfilePointer": oFsm.mapperSP0ID,
729 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
730 "GalProfilePointer": galEthernetEID,
731 },
732 }
733 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
734 oFsm.pAdaptFsm.commChan, meParams)
735 //accept also nil as (error) return value for writing to LastTx
736 // - this avoids misinterpretation of new received OMCI messages
737 oFsm.pOmciCC.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000738
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000739 //verify response
740 err := oFsm.waitforOmciResponse()
741 if err != nil {
742 logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000743 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "GemIndex": gemIndex})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000744 oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
745 return
746 }
747 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000748
749 // if Config has been done for all GemPort instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000750 logger.Debugw("GemIwTp create loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000751 oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000752 return
753}
754
755func (oFsm *UniPonAniConfigFsm) performSettingPQs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000756 const cu16StrictPrioWeight uint16 = 0xFFFF
757 //find all upstream PrioQueues related to this T-Cont
758 loQueueMap := ordered_map.NewOrderedMap()
759 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
760 if gemPortAttribs.qosPolicy == "WRR" {
761 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); ok == false {
762 //key does not yet exist
763 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
764 }
765 } else {
766 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
767 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000768 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000769
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000770 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
771 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
772 // complete chain is not valid, then some error should be thrown and configuration can be aborted
773 // or even be finished without correct SP/WRR setting
774
775 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
776 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
777 // even though its T-Cont seems to be wrong ...
778 loTrafficSchedulerEID := 0x8000
779 //for all found queues
780 iter := loQueueMap.IterFunc()
781 for kv, ok := iter(); ok; kv, ok = iter() {
782 queueIndex := (kv.Key).(uint16)
783 meParams := me.ParamData{
784 EntityID: queueIndex,
785 Attributes: make(me.AttributeValueMap, 0),
786 }
787 if (kv.Value).(uint16) == cu16StrictPrioWeight {
788 //StrictPrio indication
789 logger.Debugw("UniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
790 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
791 "device-id": oFsm.pAdaptFsm.deviceID})
792 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
793 } else {
794 //WRR indication
795 logger.Debugw("UniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
796 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
797 "Weight": kv.Value,
798 "device-id": oFsm.pAdaptFsm.deviceID})
799 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
800 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
801 }
802 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
803 oFsm.pAdaptFsm.commChan, meParams)
804 //accept also nil as (error) return value for writing to LastTx
805 // - this avoids misinterpretation of new received OMCI messages
806 oFsm.pOmciCC.pLastTxMeInstance = meInstance
807
808 //verify response
809 err := oFsm.waitforOmciResponse()
810 if err != nil {
811 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000812 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000813 oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
814 return
815 }
816
817 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
818 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
819 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
820 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
821
822 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +0000823
824 // if Config has been done for all PrioQueue instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000825 logger.Debugw("PrioQueue set loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000826 oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000827 return
828}
829
830func (oFsm *UniPonAniConfigFsm) waitforOmciResponse() error {
831 select {
832 // maybe be also some outside cancel (but no context modelled for the moment ...)
833 // case <-ctx.Done():
834 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
835 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
836 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
837 return errors.New("UniPonAniConfigFsm multi entity timeout")
838 case success := <-oFsm.omciMIdsResponseReceived:
839 if success == true {
840 logger.Debug("UniPonAniConfigFsm multi entity response received")
841 return nil
842 }
843 // should not happen so far
844 logger.Warnw("UniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
845 return errors.New("UniPonAniConfigFsm multi entity responseError")
846 }
847}