blob: 4669751ae09e8f3474581472a4794277b2cc0536 [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"
Himani Chawla4d908332020-08-31 12:30:20 +053022 "fmt"
mpagenko3dbcdd22020-07-22 07:38:45 +000023 "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
Himani Chawla6d2ae152020-09-02 13:11:20 +053077//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
78type uniPonAniConfigFsm struct {
79 pOmciCC *omciCC
80 pOnuUniPort *onuUniPort
81 pUniTechProf *onuUniTechProf
82 pOnuDB *onuDeviceDB
mpagenko3dbcdd22020-07-22 07:38:45 +000083 techProfileID uint16
84 requestEvent OnuDeviceEvent
Himani Chawla4d908332020-08-31 12:30:20 +053085 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +000086 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
Himani Chawla6d2ae152020-09-02 13:11:20 +053098//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
99func 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 {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530114 logger.Errorw("uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000115 "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 {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530167 logger.Errorw("uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000168 "device-id": aDeviceID})
169 return nil
170 }
171
Himani Chawla6d2ae152020-09-02 13:11:20 +0530172 logger.Infow("uniPonAniConfigFsm created", log.Fields{"device-id": aDeviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000173 return instFsm
174}
175
Himani Chawla6d2ae152020-09-02 13:11:20 +0530176//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
177func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000178 oFsm.chSuccess = aChSuccess
179 oFsm.procStep = aProcStep
180 oFsm.chanSet = true
181}
182
Himani Chawla6d2ae152020-09-02 13:11:20 +0530183func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530184 if aPAFsm != nil && aPAFsm.pFsm != nil {
185 //stick to pythonAdapter numbering scheme
186 //index 0 in naming refers to possible usage of multiple instances (later)
187 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + oFsm.techProfileID
188 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + oFsm.techProfileID
189
190 // For the time being: if there are multiple T-Conts on the ONU the first one from the entityID-ordered list is used
191 // TODO!: if more T-Conts have to be supported (tcontXID!), then use the first instances of the entity-ordered list
192 // or use the py code approach, which might be a bit more complicated, but also more secure, as it
193 // ensures that the selected T-Cont also has queues (which I would assume per definition from ONU, but who knows ...)
194 // so this approach would search the (sorted) upstream PrioQueue list and use the T-Cont (if available) from highest Bytes
195 // or sndHighByte of relatedPort Attribute (T-Cont Reference) and in case of multiple TConts find the next free TContIndex
196 // that way from PrioQueue.relatedPort list
Himani Chawla6d2ae152020-09-02 13:11:20 +0530197 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.TContClassID); len(tcontInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530198 oFsm.tcont0ID = tcontInstKeys[0]
199 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
200 "device-id": oFsm.pAdaptFsm.deviceID})
201 } else {
202 logger.Warnw("No TCont instances found", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
203 }
204 oFsm.alloc0ID = (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniID]))[0].tcontParams.allocID
205 loGemPortAttribs := ponAniGemPortAttribs{}
206 //for all TechProfile set GemIndices
207 for _, gemEntry := range (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniID]))[0].mapGemPortParams {
208 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
209
Himani Chawla6d2ae152020-09-02 13:11:20 +0530210 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530211
212 loGemPortAttribs.gemPortID = gemEntry.gemPortID
213 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
214 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
215 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
216 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
217
218 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
219 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
220 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
221 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
222 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
223 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
224
225 usQueueFound := false
226 dsQueueFound := false
227 for _, mgmtEntityID := range queueInstKeys {
228 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
229 returnVal := meAttributes["RelatedPort"]
230 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530231 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530232 if relatedPort == usQrelPortMask {
233 loGemPortAttribs.upQueueID = mgmtEntityID
234 logger.Debugw("UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
235 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.pAdaptFsm.deviceID})
236 usQueueFound = true
237 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
238 loGemPortAttribs.downQueueID = mgmtEntityID
239 logger.Debugw("DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
240 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.pAdaptFsm.deviceID})
241 dsQueueFound = true
242 }
243 if usQueueFound && dsQueueFound {
244 break
245 }
246 } else {
247 logger.Warnw("Could not convert attribute value", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
248 }
249 } else {
250 logger.Warnw("'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
251 }
252 } else {
253 logger.Warnw("No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
254 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.pAdaptFsm.deviceID})
255 }
256 }
257 } else {
258 logger.Warnw("No PriorityQueue instances found", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
259 }
260 loGemPortAttribs.direction = gemEntry.direction
261 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
262 loGemPortAttribs.weight = gemEntry.queueWeight
263 loGemPortAttribs.pbitString = gemEntry.pbitString
264
265 logger.Debugw("prio-related GemPort attributes:", log.Fields{
266 "gemPortID": loGemPortAttribs.gemPortID,
267 "upQueueID": loGemPortAttribs.upQueueID,
268 "downQueueID": loGemPortAttribs.downQueueID,
269 "pbitString": loGemPortAttribs.pbitString,
270 "prioQueueIndex": gemEntry.prioQueueIndex,
271 })
272
273 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
274 }
275 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
276 }
277}
278
Himani Chawla6d2ae152020-09-02 13:11:20 +0530279func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000280 logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
281 "device-id": oFsm.pAdaptFsm.deviceID})
282 // in case the used channel is not yet defined (can be re-used after restarts)
283 if oFsm.omciMIdsResponseReceived == nil {
284 oFsm.omciMIdsResponseReceived = make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530285 logger.Debug("uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000286 } else {
287 // as we may 're-use' this instance of FSM and the connected channel
288 // make sure there is no 'lingering' request in the already existing channel:
289 // (simple loop sufficient as we are the only receiver)
290 for len(oFsm.omciMIdsResponseReceived) > 0 {
291 <-oFsm.omciMIdsResponseReceived
292 }
293 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000294 //ensure internal slices are empty (which might be set from previous run) - release memory
295 oFsm.gemPortAttribsSlice = nil
296
mpagenko3dbcdd22020-07-22 07:38:45 +0000297 // start go routine for processing of LockState messages
mpagenkodff5dda2020-08-28 11:52:01 +0000298 go oFsm.processOmciAniMessages()
mpagenko3dbcdd22020-07-22 07:38:45 +0000299
300 //let the state machine run forward from here directly
301 pConfigAniStateAFsm := oFsm.pAdaptFsm
302 if pConfigAniStateAFsm != nil {
303 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530304 go oFsm.prepareAndEnterConfigState(pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000305
mpagenko3dbcdd22020-07-22 07:38:45 +0000306 }
307}
308
Himani Chawla6d2ae152020-09-02 13:11:20 +0530309func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
310 logger.Debugw("uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000311 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
312 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
313 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
314 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
315 //accept also nil as (error) return value for writing to LastTx
316 // - this avoids misinterpretation of new received OMCI messages
317 oFsm.pOmciCC.pLastTxMeInstance = meInstance
318}
319
Himani Chawla6d2ae152020-09-02 13:11:20 +0530320func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
321 logger.Debugw("uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000322 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
323 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
324 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
325 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
326 meParams := me.ParamData{
327 EntityID: oFsm.macBPCD0ID,
328 Attributes: me.AttributeValueMap{
329 "BridgeIdPointer": bridgePtr,
330 "PortNum": 0xFF, //fixed unique ANI side indication
331 "TpType": 3, //for .1PMapper
332 "TpPointer": oFsm.mapperSP0ID,
333 },
334 }
335 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
336 oFsm.pAdaptFsm.commChan, meParams)
337 //accept also nil as (error) return value for writing to LastTx
338 // - this avoids misinterpretation of new received OMCI messages
339 oFsm.pOmciCC.pLastTxMeInstance = meInstance
340
341}
342
Himani Chawla6d2ae152020-09-02 13:11:20 +0530343func (oFsm *uniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
344 logger.Debugw("uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000345 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
346 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
347 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
348 meParams := me.ParamData{
349 EntityID: oFsm.tcont0ID,
350 Attributes: me.AttributeValueMap{
351 "AllocId": oFsm.alloc0ID,
352 },
353 }
354 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
355 oFsm.pAdaptFsm.commChan, meParams)
356 //accept also nil as (error) return value for writing to LastTx
357 // - this avoids misinterpretation of new received OMCI messages
358 oFsm.pOmciCC.pLastTxMeInstance = meInstance
359}
360
Himani Chawla6d2ae152020-09-02 13:11:20 +0530361func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
362 logger.Debugw("uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000363 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
364 go oFsm.performCreatingGemNCTPs()
365}
366
Himani Chawla6d2ae152020-09-02 13:11:20 +0530367func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
368 logger.Debugw("uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000369 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
370 go oFsm.performCreatingGemIWs()
371}
372
Himani Chawla6d2ae152020-09-02 13:11:20 +0530373func (oFsm *uniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
374 logger.Debugw("uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000375 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
376 go oFsm.performSettingPQs()
377}
378
Himani Chawla6d2ae152020-09-02 13:11:20 +0530379func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
380 logger.Debugw("uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko3dbcdd22020-07-22 07:38:45 +0000381 "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
382
Himani Chawla6d2ae152020-09-02 13:11:20 +0530383 logger.Debugw("uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000384 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
385 "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
386
mpagenko3dbcdd22020-07-22 07:38:45 +0000387 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000388 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530389 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000390 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000391
392 //assign the GemPorts according to the configured Prio
393 var loPrioGemPortArray [8]uint16
394 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
395 for i := 0; i < 8; i++ {
396 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
397 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
398 if prio == 1 { // Check this p-bit is set
399 if loPrioGemPortArray[i] == 0 {
400 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
401 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530402 logger.Warnw("uniPonAniConfigFsm PrioString not unique", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000403 "device-id": oFsm.pAdaptFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
404 "SetGemPort": loPrioGemPortArray[i]})
405 }
406 }
407 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530408 logger.Warnw("uniPonAniConfigFsm PrioString evaluation error", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000409 "device-id": oFsm.pAdaptFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
410 "prioString": gemPortAttribs.pbitString, "position": i})
411 }
412
413 }
414 }
415 var foundIwPtr bool = false
Himani Chawla4d908332020-08-31 12:30:20 +0530416 for index, value := range loPrioGemPortArray {
417 if value != 0 {
418 foundIwPtr = true
419 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
420 logger.Debugf("UniPonAniConfigFsm Set::1pMapper", log.Fields{
421 "IwPtr for Prio%d": strconv.FormatInt(int64(value), 16), "device-id": oFsm.pAdaptFsm.deviceID}, index)
422 meParams.Attributes[meAttribute] = value
423
424 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000425 }
Himani Chawla4d908332020-08-31 12:30:20 +0530426
427 if !foundIwPtr {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000428 logger.Errorw("UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
429 "device-id": oFsm.pAdaptFsm.deviceID})
430 //let's reset the state machine in order to release all resources now
431 pConfigAniStateAFsm := oFsm.pAdaptFsm
432 if pConfigAniStateAFsm != nil {
433 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530434 go func(aPAFsm *AdapterFsm) {
435 if aPAFsm != nil && aPAFsm.pFsm != nil {
436 _ = aPAFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000437 }
438 }(pConfigAniStateAFsm)
439 }
440 }
441
mpagenko3dbcdd22020-07-22 07:38:45 +0000442 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
443 oFsm.pAdaptFsm.commChan, meParams)
444 //accept also nil as (error) return value for writing to LastTx
445 // - this avoids misinterpretation of new received OMCI messages
446 oFsm.pOmciCC.pLastTxMeInstance = meInstance
447}
448
Himani Chawla6d2ae152020-09-02 13:11:20 +0530449func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000450
mpagenko1cc3cb42020-07-27 15:24:38 +0000451 oFsm.aniConfigCompleted = true
mpagenko3dbcdd22020-07-22 07:38:45 +0000452
453 //let's reset the state machine in order to release all resources now
454 pConfigAniStateAFsm := oFsm.pAdaptFsm
455 if pConfigAniStateAFsm != nil {
456 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530457 go func(aPAFsm *AdapterFsm) {
458 if aPAFsm != nil && aPAFsm.pFsm != nil {
459 _ = aPAFsm.pFsm.Event(aniEvReset)
mpagenko3dbcdd22020-07-22 07:38:45 +0000460 }
461 }(pConfigAniStateAFsm)
462 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000463}
464
Himani Chawla6d2ae152020-09-02 13:11:20 +0530465func (oFsm *uniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
466 logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000467
mpagenko3dbcdd22020-07-22 07:38:45 +0000468 pConfigAniStateAFsm := oFsm.pAdaptFsm
469 if pConfigAniStateAFsm != nil {
470 // abort running message processing
471 fsmAbortMsg := Message{
472 Type: TestMsg,
473 Data: TestMessage{
474 TestMessageVal: AbortMessageProcessing,
475 },
476 }
477 pConfigAniStateAFsm.commChan <- fsmAbortMsg
478
479 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530480 go func(aPAFsm *AdapterFsm) {
481 if aPAFsm != nil && aPAFsm.pFsm != nil {
482 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000483 }
484 }(pConfigAniStateAFsm)
485 }
486}
487
Himani Chawla6d2ae152020-09-02 13:11:20 +0530488func (oFsm *uniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
489 logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
mpagenko1cc3cb42020-07-27 15:24:38 +0000490
491 if oFsm.aniConfigCompleted {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530492 logger.Debugw("uniPonAniConfigFsm send dh event notification", log.Fields{
mpagenko1cc3cb42020-07-27 15:24:38 +0000493 "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
494 //use DeviceHandler event notification directly
Himani Chawla6d2ae152020-09-02 13:11:20 +0530495 oFsm.pOmciCC.pBaseDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
mpagenko1cc3cb42020-07-27 15:24:38 +0000496 oFsm.aniConfigCompleted = false
497 }
mpagenkodff5dda2020-08-28 11:52:01 +0000498 //store that the UNI related techProfile processing is done for the given Profile and Uni
Himani Chawla26e555c2020-08-31 12:30:20 +0530499 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, true)
mpagenkodff5dda2020-08-28 11:52:01 +0000500 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
501 go oFsm.pOmciCC.pBaseDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
mpagenko1cc3cb42020-07-27 15:24:38 +0000502
503 if oFsm.chanSet {
504 // indicate processing done to the caller
Himani Chawla6d2ae152020-09-02 13:11:20 +0530505 logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko1cc3cb42020-07-27 15:24:38 +0000506 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
507 oFsm.chSuccess <- oFsm.procStep
508 oFsm.chanSet = false //reset the internal channel state
509 }
510
511}
512
Himani Chawla6d2ae152020-09-02 13:11:20 +0530513func (oFsm *uniPonAniConfigFsm) processOmciAniMessages( /*ctx context.Context*/ ) {
514 logger.Debugw("Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000515loop:
516 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000517 // case <-ctx.Done():
518 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.pAdaptFsm.deviceID})
519 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530520 message, ok := <-oFsm.pAdaptFsm.commChan
521 if !ok {
522 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
523 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
524 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
525 break loop
526 }
527 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
528
529 switch message.Type {
530 case TestMsg:
531 msg, _ := message.Data.(TestMessage)
532 if msg.TestMessageVal == AbortMessageProcessing {
533 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000534 break loop
535 }
Himani Chawla4d908332020-08-31 12:30:20 +0530536 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "MessageVal": msg.TestMessageVal})
537 case OMCI:
538 msg, _ := message.Data.(OmciMessage)
539 oFsm.handleOmciAniConfigMessage(msg)
540 default:
541 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
542 "message.Type": message.Type})
543 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000544
Himani Chawla4d908332020-08-31 12:30:20 +0530545 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530546 logger.Infow("End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530547}
548
Himani Chawla6d2ae152020-09-02 13:11:20 +0530549func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530550 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
551 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200552 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
553 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530554 return
555 }
556 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
557 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200558 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
559 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530560 return
561 }
562 logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
563 if msgObj.Result != me.Success {
564 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
565 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
566 return
567 }
568 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
569 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
570 // maybe we can use just the same eventName for different state transitions like "forward"
571 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
572 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
573 case "Ieee8021PMapperServiceProfile":
574 { // let the FSM proceed ...
575 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
576 }
577 case "MacBridgePortConfigurationData":
578 { // let the FSM proceed ...
579 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
580 }
581 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
582 { // let aniConfig Multi-Id processing proceed by stopping the wait function
583 oFsm.omciMIdsResponseReceived <- true
mpagenko3dbcdd22020-07-22 07:38:45 +0000584 }
585 }
586 }
Himani Chawla4d908332020-08-31 12:30:20 +0530587}
588
Himani Chawla6d2ae152020-09-02 13:11:20 +0530589func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530590 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
591 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200592 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
593 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530594 return
595 }
596 msgObj, msgOk := msgLayer.(*omci.SetResponse)
597 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200598 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
599 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530600 return
601 }
602 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
603 if msgObj.Result != me.Success {
Andrea Campanella6515c582020-10-05 11:25:00 +0200604 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
605 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530606 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
607 return
608 }
609 if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
610 msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
611 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
612 // if, then something like:
613 //oFsm.pOnuDB.StoreMe(msgObj)
614
615 switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
616 case "TCont":
617 { // let the FSM proceed ...
618 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
619 }
620 case "PriorityQueue":
621 { // let the PrioQueue init proceed by stopping the wait function
622 oFsm.omciMIdsResponseReceived <- true
623 }
624 case "Ieee8021PMapperServiceProfile":
625 { // let the FSM proceed ...
626 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
627 }
628 }
629 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000630}
631
Himani Chawla6d2ae152020-09-02 13:11:20 +0530632func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000633 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
634 "msgType": msg.OmciMsg.MessageType})
635
636 switch msg.OmciMsg.MessageType {
637 case omci.CreateResponseType:
638 {
Himani Chawla4d908332020-08-31 12:30:20 +0530639 oFsm.handleOmciAniConfigCreateResponseMessage(msg)
640
mpagenko3dbcdd22020-07-22 07:38:45 +0000641 } //CreateResponseType
642 case omci.SetResponseType:
643 {
Himani Chawla4d908332020-08-31 12:30:20 +0530644 oFsm.handleOmciAniConfigSetResponseMessage(msg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000645
mpagenko3dbcdd22020-07-22 07:38:45 +0000646 } //SetResponseType
647 default:
648 {
Andrea Campanella6515c582020-10-05 11:25:00 +0200649 logger.Errorw("uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
650 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.pAdaptFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000651 return
652 }
653 }
654}
655
Himani Chawla6d2ae152020-09-02 13:11:20 +0530656func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000657 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
658 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530659 logger.Debugw("uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000660 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
661 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
662 "device-id": oFsm.pAdaptFsm.deviceID})
663 meParams := me.ParamData{
664 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
665 Attributes: me.AttributeValueMap{
666 "PortId": gemPortAttribs.gemPortID,
667 "TContPointer": oFsm.tcont0ID,
668 "Direction": gemPortAttribs.direction,
669 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
670 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
671 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
672 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
673 },
674 }
675 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
676 oFsm.pAdaptFsm.commChan, meParams)
677 //accept also nil as (error) return value for writing to LastTx
678 // - this avoids misinterpretation of new received OMCI messages
679 oFsm.pOmciCC.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000680
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000681 //verify response
682 err := oFsm.waitforOmciResponse()
683 if err != nil {
684 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000685 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530686 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000687 return
688 }
689 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000690
691 // if Config has been done for all GemPort instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000692 logger.Debugw("GemNWCtp create loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530693 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000694}
695
Himani Chawla6d2ae152020-09-02 13:11:20 +0530696func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000697 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
698 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530699 logger.Debugw("uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000700 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
701 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
702 "device-id": oFsm.pAdaptFsm.deviceID})
703 meParams := me.ParamData{
704 EntityID: gemPortAttribs.gemPortID,
705 Attributes: me.AttributeValueMap{
706 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
707 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
708 "ServiceProfilePointer": oFsm.mapperSP0ID,
709 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
710 "GalProfilePointer": galEthernetEID,
711 },
712 }
713 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
714 oFsm.pAdaptFsm.commChan, meParams)
715 //accept also nil as (error) return value for writing to LastTx
716 // - this avoids misinterpretation of new received OMCI messages
717 oFsm.pOmciCC.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000718
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000719 //verify response
720 err := oFsm.waitforOmciResponse()
721 if err != nil {
722 logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000723 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530724 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000725 return
726 }
727 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000728
729 // if Config has been done for all GemPort instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000730 logger.Debugw("GemIwTp create loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530731 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000732}
733
Himani Chawla6d2ae152020-09-02 13:11:20 +0530734func (oFsm *uniPonAniConfigFsm) performSettingPQs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000735 const cu16StrictPrioWeight uint16 = 0xFFFF
736 //find all upstream PrioQueues related to this T-Cont
737 loQueueMap := ordered_map.NewOrderedMap()
738 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
739 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +0530740 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000741 //key does not yet exist
742 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
743 }
744 } else {
745 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
746 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000747 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000748
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000749 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
750 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
751 // complete chain is not valid, then some error should be thrown and configuration can be aborted
752 // or even be finished without correct SP/WRR setting
753
754 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
755 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
756 // even though its T-Cont seems to be wrong ...
757 loTrafficSchedulerEID := 0x8000
758 //for all found queues
759 iter := loQueueMap.IterFunc()
760 for kv, ok := iter(); ok; kv, ok = iter() {
761 queueIndex := (kv.Key).(uint16)
762 meParams := me.ParamData{
763 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +0530764 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000765 }
766 if (kv.Value).(uint16) == cu16StrictPrioWeight {
767 //StrictPrio indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530768 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000769 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
770 "device-id": oFsm.pAdaptFsm.deviceID})
771 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
772 } else {
773 //WRR indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530774 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000775 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
776 "Weight": kv.Value,
777 "device-id": oFsm.pAdaptFsm.deviceID})
778 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
779 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
780 }
781 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
782 oFsm.pAdaptFsm.commChan, meParams)
783 //accept also nil as (error) return value for writing to LastTx
784 // - this avoids misinterpretation of new received OMCI messages
785 oFsm.pOmciCC.pLastTxMeInstance = meInstance
786
787 //verify response
788 err := oFsm.waitforOmciResponse()
789 if err != nil {
790 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
divyadesai4d299552020-08-18 07:13:49 +0000791 log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +0530792 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000793 return
794 }
795
796 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
797 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
798 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
799 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
800
801 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +0000802
803 // if Config has been done for all PrioQueue instances let the FSM proceed
divyadesai4d299552020-08-18 07:13:49 +0000804 logger.Debugw("PrioQueue set loop finished", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530805 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000806}
807
Himani Chawla6d2ae152020-09-02 13:11:20 +0530808func (oFsm *uniPonAniConfigFsm) waitforOmciResponse() error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000809 select {
Himani Chawla4d908332020-08-31 12:30:20 +0530810 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +0000811 // case <-ctx.Done():
812 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
813 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
814 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200815 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.pAdaptFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000816 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +0530817 if success {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530818 logger.Debug("uniPonAniConfigFsm multi entity response received")
mpagenko3dbcdd22020-07-22 07:38:45 +0000819 return nil
820 }
821 // should not happen so far
Himani Chawla6d2ae152020-09-02 13:11:20 +0530822 logger.Warnw("uniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
Andrea Campanella6515c582020-10-05 11:25:00 +0200823 return fmt.Errorf("uniPonAniConfigFsm multi entity responseError %s", oFsm.pAdaptFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000824 }
825}