blob: 70f172abec7ee990eae066dc6b2fa2daf6125dc5 [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 {
mpagenko01e726e2020-10-23 09:45:29 +000079 pDeviceHandler *deviceHandler
80 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +053081 pOmciCC *omciCC
82 pOnuUniPort *onuUniPort
83 pUniTechProf *onuUniTechProf
84 pOnuDB *onuDeviceDB
mpagenko3dbcdd22020-07-22 07:38:45 +000085 techProfileID uint16
86 requestEvent OnuDeviceEvent
Himani Chawla4d908332020-08-31 12:30:20 +053087 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +000088 pAdaptFsm *AdapterFsm
89 chSuccess chan<- uint8
90 procStep uint8
91 chanSet bool
92 mapperSP0ID uint16
93 macBPCD0ID uint16
94 tcont0ID uint16
95 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000096 gemPortAttribsSlice []ponAniGemPortAttribs
mpagenko01e726e2020-10-23 09:45:29 +000097 pLastTxMeInstance *me.ManagedEntity
mpagenko3dbcdd22020-07-22 07:38:45 +000098}
99
Himani Chawla6d2ae152020-09-02 13:11:20 +0530100//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
101func newUniPonAniConfigFsm(apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
102 apOnuDB *onuDeviceDB, aTechProfileID uint16, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000103 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530104 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000105 pDeviceHandler: apDeviceHandler,
106 deviceID: apDeviceHandler.deviceID,
107 pOmciCC: apDevOmciCC,
108 pOnuUniPort: apUniPort,
109 pUniTechProf: apUniTechProf,
110 pOnuDB: apOnuDB,
111 techProfileID: aTechProfileID,
112 requestEvent: aRequestEvent,
113 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000114 }
mpagenko01e726e2020-10-23 09:45:29 +0000115 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000116 if instFsm.pAdaptFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530117 logger.Errorw("uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000118 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000119 return nil
120 }
121
122 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000123 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000124 fsm.Events{
125
mpagenko1cc3cb42020-07-27 15:24:38 +0000126 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000127
128 //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 +0000129 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000130 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000131 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
132 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000133 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000134 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000135 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000136 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000137 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000138 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000139 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000140
mpagenko1cc3cb42020-07-27 15:24:38 +0000141 {Name: aniEvTimeoutSimple, Src: []string{
142 aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper}, Dst: aniStStarting},
143 {Name: aniEvTimeoutMids, Src: []string{
144 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000145
mpagenko1cc3cb42020-07-27 15:24:38 +0000146 // exceptional treatment for all states except aniStResetting
147 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
148 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
149 aniStConfigDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000150 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000151 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000152 },
153
154 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000155 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
156 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(e) },
157 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(e) },
158 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(e) },
159 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(e) },
160 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(e) },
161 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(e) },
162 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
163 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
164 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
165 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(e) },
166 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000167 },
168 )
169 if instFsm.pAdaptFsm.pFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530170 logger.Errorw("uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000171 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000172 return nil
173 }
174
mpagenko01e726e2020-10-23 09:45:29 +0000175 logger.Infow("uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000176 return instFsm
177}
178
Himani Chawla6d2ae152020-09-02 13:11:20 +0530179//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
180func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000181 oFsm.chSuccess = aChSuccess
182 oFsm.procStep = aProcStep
183 oFsm.chanSet = true
184}
185
Himani Chawla6d2ae152020-09-02 13:11:20 +0530186func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530187 if aPAFsm != nil && aPAFsm.pFsm != nil {
188 //stick to pythonAdapter numbering scheme
189 //index 0 in naming refers to possible usage of multiple instances (later)
190 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + oFsm.techProfileID
191 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + oFsm.techProfileID
192
193 // For the time being: if there are multiple T-Conts on the ONU the first one from the entityID-ordered list is used
194 // TODO!: if more T-Conts have to be supported (tcontXID!), then use the first instances of the entity-ordered list
195 // or use the py code approach, which might be a bit more complicated, but also more secure, as it
196 // ensures that the selected T-Cont also has queues (which I would assume per definition from ONU, but who knows ...)
197 // so this approach would search the (sorted) upstream PrioQueue list and use the T-Cont (if available) from highest Bytes
198 // or sndHighByte of relatedPort Attribute (T-Cont Reference) and in case of multiple TConts find the next free TContIndex
199 // that way from PrioQueue.relatedPort list
Himani Chawla6d2ae152020-09-02 13:11:20 +0530200 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.TContClassID); len(tcontInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530201 oFsm.tcont0ID = tcontInstKeys[0]
202 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000203 "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530204 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000205 logger.Warnw("No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530206 }
207 oFsm.alloc0ID = (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniID]))[0].tcontParams.allocID
208 loGemPortAttribs := ponAniGemPortAttribs{}
209 //for all TechProfile set GemIndices
210 for _, gemEntry := range (*(oFsm.pUniTechProf.mapPonAniConfig[oFsm.pOnuUniPort.uniID]))[0].mapGemPortParams {
211 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
212
Himani Chawla6d2ae152020-09-02 13:11:20 +0530213 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530214
215 loGemPortAttribs.gemPortID = gemEntry.gemPortID
216 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
217 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
218 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
219 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
220
221 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
222 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
223 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
224 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
225 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
226 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
227
228 usQueueFound := false
229 dsQueueFound := false
230 for _, mgmtEntityID := range queueInstKeys {
231 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
232 returnVal := meAttributes["RelatedPort"]
233 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530234 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530235 if relatedPort == usQrelPortMask {
236 loGemPortAttribs.upQueueID = mgmtEntityID
237 logger.Debugw("UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000238 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530239 usQueueFound = true
240 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
241 loGemPortAttribs.downQueueID = mgmtEntityID
242 logger.Debugw("DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000243 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530244 dsQueueFound = true
245 }
246 if usQueueFound && dsQueueFound {
247 break
248 }
249 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000250 logger.Warnw("Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530251 }
252 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000253 logger.Warnw("'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530254 }
255 } else {
256 logger.Warnw("No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000257 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530258 }
259 }
260 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000261 logger.Warnw("No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530262 }
263 loGemPortAttribs.direction = gemEntry.direction
264 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
265 loGemPortAttribs.weight = gemEntry.queueWeight
266 loGemPortAttribs.pbitString = gemEntry.pbitString
267
268 logger.Debugw("prio-related GemPort attributes:", log.Fields{
269 "gemPortID": loGemPortAttribs.gemPortID,
270 "upQueueID": loGemPortAttribs.upQueueID,
271 "downQueueID": loGemPortAttribs.downQueueID,
272 "pbitString": loGemPortAttribs.pbitString,
273 "prioQueueIndex": gemEntry.prioQueueIndex,
274 })
275
276 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
277 }
278 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
279 }
280}
281
Himani Chawla6d2ae152020-09-02 13:11:20 +0530282func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000283 logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000284 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000285 // in case the used channel is not yet defined (can be re-used after restarts)
286 if oFsm.omciMIdsResponseReceived == nil {
287 oFsm.omciMIdsResponseReceived = make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530288 logger.Debug("uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000289 } else {
290 // as we may 're-use' this instance of FSM and the connected channel
291 // make sure there is no 'lingering' request in the already existing channel:
292 // (simple loop sufficient as we are the only receiver)
293 for len(oFsm.omciMIdsResponseReceived) > 0 {
294 <-oFsm.omciMIdsResponseReceived
295 }
296 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000297 //ensure internal slices are empty (which might be set from previous run) - release memory
298 oFsm.gemPortAttribsSlice = nil
299
mpagenko3dbcdd22020-07-22 07:38:45 +0000300 // start go routine for processing of LockState messages
mpagenkodff5dda2020-08-28 11:52:01 +0000301 go oFsm.processOmciAniMessages()
mpagenko3dbcdd22020-07-22 07:38:45 +0000302
303 //let the state machine run forward from here directly
304 pConfigAniStateAFsm := oFsm.pAdaptFsm
305 if pConfigAniStateAFsm != nil {
306 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530307 go oFsm.prepareAndEnterConfigState(pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000308
mpagenko3dbcdd22020-07-22 07:38:45 +0000309 }
310}
311
Himani Chawla6d2ae152020-09-02 13:11:20 +0530312func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
313 logger.Debugw("uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000314 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000315 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000316 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
317 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
318 //accept also nil as (error) return value for writing to LastTx
319 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000320 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000321}
322
Himani Chawla6d2ae152020-09-02 13:11:20 +0530323func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
324 logger.Debugw("uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000325 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
326 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000327 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000328 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
329 meParams := me.ParamData{
330 EntityID: oFsm.macBPCD0ID,
331 Attributes: me.AttributeValueMap{
332 "BridgeIdPointer": bridgePtr,
333 "PortNum": 0xFF, //fixed unique ANI side indication
334 "TpType": 3, //for .1PMapper
335 "TpPointer": oFsm.mapperSP0ID,
336 },
337 }
338 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
339 oFsm.pAdaptFsm.commChan, meParams)
340 //accept also nil as (error) return value for writing to LastTx
341 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000342 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000343
344}
345
Himani Chawla6d2ae152020-09-02 13:11:20 +0530346func (oFsm *uniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
347 logger.Debugw("uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000348 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
349 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000350 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000351 meParams := me.ParamData{
352 EntityID: oFsm.tcont0ID,
353 Attributes: me.AttributeValueMap{
354 "AllocId": oFsm.alloc0ID,
355 },
356 }
357 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
358 oFsm.pAdaptFsm.commChan, meParams)
359 //accept also nil as (error) return value for writing to LastTx
360 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000361 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000362}
363
Himani Chawla6d2ae152020-09-02 13:11:20 +0530364func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
365 logger.Debugw("uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000366 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000367 go oFsm.performCreatingGemNCTPs()
368}
369
Himani Chawla6d2ae152020-09-02 13:11:20 +0530370func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
371 logger.Debugw("uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000372 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000373 go oFsm.performCreatingGemIWs()
374}
375
Himani Chawla6d2ae152020-09-02 13:11:20 +0530376func (oFsm *uniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
377 logger.Debugw("uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000378 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000379 go oFsm.performSettingPQs()
380}
381
Himani Chawla6d2ae152020-09-02 13:11:20 +0530382func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
383 logger.Debugw("uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko01e726e2020-10-23 09:45:29 +0000384 "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000385
Himani Chawla6d2ae152020-09-02 13:11:20 +0530386 logger.Debugw("uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000387 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000388 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000389
mpagenko3dbcdd22020-07-22 07:38:45 +0000390 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000391 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530392 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000393 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000394
395 //assign the GemPorts according to the configured Prio
396 var loPrioGemPortArray [8]uint16
397 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
398 for i := 0; i < 8; i++ {
399 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
400 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
401 if prio == 1 { // Check this p-bit is set
402 if loPrioGemPortArray[i] == 0 {
403 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
404 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530405 logger.Warnw("uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000406 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000407 "SetGemPort": loPrioGemPortArray[i]})
408 }
409 }
410 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530411 logger.Warnw("uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000412 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000413 "prioString": gemPortAttribs.pbitString, "position": i})
414 }
415
416 }
417 }
418 var foundIwPtr bool = false
Himani Chawla4d908332020-08-31 12:30:20 +0530419 for index, value := range loPrioGemPortArray {
420 if value != 0 {
421 foundIwPtr = true
422 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530423 meParams.Attributes[meAttribute] = value
mpagenko01e726e2020-10-23 09:45:29 +0000424 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
425 "for Prio": index,
426 "IwPtr": strconv.FormatInt(int64(value), 16),
427 "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530428 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000429 }
Himani Chawla4d908332020-08-31 12:30:20 +0530430
431 if !foundIwPtr {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000432 logger.Errorw("UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000433 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000434 //let's reset the state machine in order to release all resources now
435 pConfigAniStateAFsm := oFsm.pAdaptFsm
436 if pConfigAniStateAFsm != nil {
437 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530438 go func(aPAFsm *AdapterFsm) {
439 if aPAFsm != nil && aPAFsm.pFsm != nil {
440 _ = aPAFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000441 }
442 }(pConfigAniStateAFsm)
443 }
444 }
445
mpagenko3dbcdd22020-07-22 07:38:45 +0000446 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
447 oFsm.pAdaptFsm.commChan, meParams)
448 //accept also nil as (error) return value for writing to LastTx
449 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000450 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000451}
452
Himani Chawla6d2ae152020-09-02 13:11:20 +0530453func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000454 logger.Debugw("uniPonAniConfigFsm send dh event notification recheck pending flow config", log.Fields{
455 "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
456 //use DeviceHandler event notification directly
457 oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
458 //store that the UNI related techProfile processing is done for the given Profile and Uni
459 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, true)
460 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
461 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
mpagenko3dbcdd22020-07-22 07:38:45 +0000462
mpagenko01e726e2020-10-23 09:45:29 +0000463 if oFsm.chanSet {
464 // indicate processing done to the caller
465 logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
466 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
467 oFsm.chSuccess <- oFsm.procStep
468 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000469 }
mpagenko01e726e2020-10-23 09:45:29 +0000470
471 //the FSM is left active in this state as long as no specific reset or remove is requested from outside
mpagenko3dbcdd22020-07-22 07:38:45 +0000472}
473
Himani Chawla6d2ae152020-09-02 13:11:20 +0530474func (oFsm *uniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000475 logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000476
mpagenko3dbcdd22020-07-22 07:38:45 +0000477 pConfigAniStateAFsm := oFsm.pAdaptFsm
478 if pConfigAniStateAFsm != nil {
479 // abort running message processing
480 fsmAbortMsg := Message{
481 Type: TestMsg,
482 Data: TestMessage{
483 TestMessageVal: AbortMessageProcessing,
484 },
485 }
486 pConfigAniStateAFsm.commChan <- fsmAbortMsg
487
488 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530489 go func(aPAFsm *AdapterFsm) {
490 if aPAFsm != nil && aPAFsm.pFsm != nil {
491 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000492 }
493 }(pConfigAniStateAFsm)
494 }
495}
496
Himani Chawla6d2ae152020-09-02 13:11:20 +0530497func (oFsm *uniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000498 logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
499 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000500
mpagenko01e726e2020-10-23 09:45:29 +0000501 //remove all TechProf related internal data to allow for new configuration (e.g. with disable/enable procedure)
502 oFsm.pUniTechProf.clearAniSideConfig(oFsm.pOnuUniPort.uniID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000503}
504
Himani Chawla6d2ae152020-09-02 13:11:20 +0530505func (oFsm *uniPonAniConfigFsm) processOmciAniMessages( /*ctx context.Context*/ ) {
mpagenko01e726e2020-10-23 09:45:29 +0000506 logger.Debugw("Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000507loop:
508 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000509 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000510 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000511 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530512 message, ok := <-oFsm.pAdaptFsm.commChan
513 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +0000514 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530515 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
516 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
517 break loop
518 }
mpagenko01e726e2020-10-23 09:45:29 +0000519 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530520
521 switch message.Type {
522 case TestMsg:
523 msg, _ := message.Data.(TestMessage)
524 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +0000525 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000526 break loop
527 }
mpagenko01e726e2020-10-23 09:45:29 +0000528 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530529 case OMCI:
530 msg, _ := message.Data.(OmciMessage)
531 oFsm.handleOmciAniConfigMessage(msg)
532 default:
mpagenko01e726e2020-10-23 09:45:29 +0000533 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530534 "message.Type": message.Type})
535 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000536
Himani Chawla4d908332020-08-31 12:30:20 +0530537 }
mpagenko01e726e2020-10-23 09:45:29 +0000538 logger.Infow("End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530539}
540
Himani Chawla6d2ae152020-09-02 13:11:20 +0530541func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530542 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
543 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200544 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000545 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530546 return
547 }
548 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
549 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200550 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000551 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530552 return
553 }
mpagenko01e726e2020-10-23 09:45:29 +0000554 logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530555 if msgObj.Result != me.Success {
556 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
557 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
558 return
559 }
mpagenko01e726e2020-10-23 09:45:29 +0000560 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
561 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530562 // maybe we can use just the same eventName for different state transitions like "forward"
563 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
mpagenko01e726e2020-10-23 09:45:29 +0000564 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530565 case "Ieee8021PMapperServiceProfile":
566 { // let the FSM proceed ...
567 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
568 }
569 case "MacBridgePortConfigurationData":
570 { // let the FSM proceed ...
571 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
572 }
573 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
574 { // let aniConfig Multi-Id processing proceed by stopping the wait function
575 oFsm.omciMIdsResponseReceived <- true
mpagenko3dbcdd22020-07-22 07:38:45 +0000576 }
577 }
578 }
Himani Chawla4d908332020-08-31 12:30:20 +0530579}
580
Himani Chawla6d2ae152020-09-02 13:11:20 +0530581func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530582 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
583 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200584 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000585 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530586 return
587 }
588 msgObj, msgOk := msgLayer.(*omci.SetResponse)
589 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200590 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000591 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530592 return
593 }
mpagenko01e726e2020-10-23 09:45:29 +0000594 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530595 if msgObj.Result != me.Success {
Andrea Campanella6515c582020-10-05 11:25:00 +0200596 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000597 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530598 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
599 return
600 }
mpagenko01e726e2020-10-23 09:45:29 +0000601 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
602 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530603 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
604 // if, then something like:
605 //oFsm.pOnuDB.StoreMe(msgObj)
606
mpagenko01e726e2020-10-23 09:45:29 +0000607 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530608 case "TCont":
609 { // let the FSM proceed ...
610 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
611 }
612 case "PriorityQueue":
613 { // let the PrioQueue init proceed by stopping the wait function
614 oFsm.omciMIdsResponseReceived <- true
615 }
616 case "Ieee8021PMapperServiceProfile":
617 { // let the FSM proceed ...
618 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
619 }
620 }
621 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000622}
623
Himani Chawla6d2ae152020-09-02 13:11:20 +0530624func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +0000625 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000626 "msgType": msg.OmciMsg.MessageType})
627
628 switch msg.OmciMsg.MessageType {
629 case omci.CreateResponseType:
630 {
Himani Chawla4d908332020-08-31 12:30:20 +0530631 oFsm.handleOmciAniConfigCreateResponseMessage(msg)
632
mpagenko3dbcdd22020-07-22 07:38:45 +0000633 } //CreateResponseType
634 case omci.SetResponseType:
635 {
Himani Chawla4d908332020-08-31 12:30:20 +0530636 oFsm.handleOmciAniConfigSetResponseMessage(msg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000637
mpagenko3dbcdd22020-07-22 07:38:45 +0000638 } //SetResponseType
639 default:
640 {
Andrea Campanella6515c582020-10-05 11:25:00 +0200641 logger.Errorw("uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +0000642 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000643 return
644 }
645 }
646}
647
Himani Chawla6d2ae152020-09-02 13:11:20 +0530648func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000649 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
650 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530651 logger.Debugw("uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000652 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
653 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000654 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000655 meParams := me.ParamData{
656 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
657 Attributes: me.AttributeValueMap{
658 "PortId": gemPortAttribs.gemPortID,
659 "TContPointer": oFsm.tcont0ID,
660 "Direction": gemPortAttribs.direction,
661 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
662 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
663 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
664 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
665 },
666 }
667 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
668 oFsm.pAdaptFsm.commChan, meParams)
669 //accept also nil as (error) return value for writing to LastTx
670 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000671 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000672
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000673 //verify response
674 err := oFsm.waitforOmciResponse()
675 if err != nil {
676 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000677 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530678 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000679 return
680 }
681 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000682
683 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000684 logger.Debugw("GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530685 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000686}
687
Himani Chawla6d2ae152020-09-02 13:11:20 +0530688func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000689 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
690 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530691 logger.Debugw("uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000692 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
693 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000694 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000695 meParams := me.ParamData{
696 EntityID: gemPortAttribs.gemPortID,
697 Attributes: me.AttributeValueMap{
698 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
699 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
700 "ServiceProfilePointer": oFsm.mapperSP0ID,
701 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
702 "GalProfilePointer": galEthernetEID,
703 },
704 }
705 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
706 oFsm.pAdaptFsm.commChan, meParams)
707 //accept also nil as (error) return value for writing to LastTx
708 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000709 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000710
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000711 //verify response
712 err := oFsm.waitforOmciResponse()
713 if err != nil {
714 logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000715 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530716 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000717 return
718 }
719 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000720
721 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000722 logger.Debugw("GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530723 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000724}
725
Himani Chawla6d2ae152020-09-02 13:11:20 +0530726func (oFsm *uniPonAniConfigFsm) performSettingPQs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000727 const cu16StrictPrioWeight uint16 = 0xFFFF
728 //find all upstream PrioQueues related to this T-Cont
729 loQueueMap := ordered_map.NewOrderedMap()
730 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
731 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +0530732 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000733 //key does not yet exist
734 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
735 }
736 } else {
737 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
738 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000739 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000740
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000741 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
742 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
743 // complete chain is not valid, then some error should be thrown and configuration can be aborted
744 // or even be finished without correct SP/WRR setting
745
746 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
747 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
748 // even though its T-Cont seems to be wrong ...
749 loTrafficSchedulerEID := 0x8000
750 //for all found queues
751 iter := loQueueMap.IterFunc()
752 for kv, ok := iter(); ok; kv, ok = iter() {
753 queueIndex := (kv.Key).(uint16)
754 meParams := me.ParamData{
755 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +0530756 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000757 }
758 if (kv.Value).(uint16) == cu16StrictPrioWeight {
759 //StrictPrio indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530760 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000761 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000762 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000763 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
764 } else {
765 //WRR indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530766 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000767 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
768 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +0000769 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000770 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
771 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
772 }
773 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
774 oFsm.pAdaptFsm.commChan, meParams)
775 //accept also nil as (error) return value for writing to LastTx
776 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000777 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000778
779 //verify response
780 err := oFsm.waitforOmciResponse()
781 if err != nil {
782 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000783 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +0530784 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000785 return
786 }
787
788 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
789 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
790 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
791 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
792
793 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +0000794
795 // if Config has been done for all PrioQueue instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000796 logger.Debugw("PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530797 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000798}
799
Himani Chawla6d2ae152020-09-02 13:11:20 +0530800func (oFsm *uniPonAniConfigFsm) waitforOmciResponse() error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000801 select {
Himani Chawla4d908332020-08-31 12:30:20 +0530802 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +0000803 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000804 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000805 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
mpagenko01e726e2020-10-23 09:45:29 +0000806 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
807 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000808 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +0530809 if success {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530810 logger.Debug("uniPonAniConfigFsm multi entity response received")
mpagenko3dbcdd22020-07-22 07:38:45 +0000811 return nil
812 }
813 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +0000814 logger.Warnw("uniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
815 return fmt.Errorf("uniPonAniConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000816 }
817}