blob: 4d461578545658a9fc6cb2fdcd38b8b6c05e4383 [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
Girish Gowdra041dcb32020-11-16 16:54:30 -080067const (
68 tpIDOffset = 64
69)
70
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000071type ponAniGemPortAttribs struct {
72 gemPortID uint16
73 upQueueID uint16
74 downQueueID uint16
75 direction uint8
76 qosPolicy string
77 weight uint8
78 pbitString string
79}
80
Himani Chawla6d2ae152020-09-02 13:11:20 +053081//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
82type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +000083 pDeviceHandler *deviceHandler
84 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +053085 pOmciCC *omciCC
86 pOnuUniPort *onuUniPort
87 pUniTechProf *onuUniTechProf
88 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -080089 techProfileID uint8
mpagenko3dbcdd22020-07-22 07:38:45 +000090 requestEvent OnuDeviceEvent
Himani Chawla4d908332020-08-31 12:30:20 +053091 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +000092 pAdaptFsm *AdapterFsm
93 chSuccess chan<- uint8
94 procStep uint8
95 chanSet bool
96 mapperSP0ID uint16
97 macBPCD0ID uint16
98 tcont0ID uint16
99 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000100 gemPortAttribsSlice []ponAniGemPortAttribs
mpagenko01e726e2020-10-23 09:45:29 +0000101 pLastTxMeInstance *me.ManagedEntity
mpagenko3dbcdd22020-07-22 07:38:45 +0000102}
103
Himani Chawla6d2ae152020-09-02 13:11:20 +0530104//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
105func newUniPonAniConfigFsm(apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800106 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000107 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530108 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000109 pDeviceHandler: apDeviceHandler,
110 deviceID: apDeviceHandler.deviceID,
111 pOmciCC: apDevOmciCC,
112 pOnuUniPort: apUniPort,
113 pUniTechProf: apUniTechProf,
114 pOnuDB: apOnuDB,
115 techProfileID: aTechProfileID,
116 requestEvent: aRequestEvent,
117 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000118 }
mpagenko01e726e2020-10-23 09:45:29 +0000119 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000120 if instFsm.pAdaptFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530121 logger.Errorw("uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000122 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000123 return nil
124 }
125
126 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000127 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000128 fsm.Events{
129
mpagenko1cc3cb42020-07-27 15:24:38 +0000130 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000131
132 //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 +0000133 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000134 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000135 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
136 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000137 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000138 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000139 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000140 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000141 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000142 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000143 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000144
mpagenko1cc3cb42020-07-27 15:24:38 +0000145 {Name: aniEvTimeoutSimple, Src: []string{
146 aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper}, Dst: aniStStarting},
147 {Name: aniEvTimeoutMids, Src: []string{
148 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000149
mpagenko1cc3cb42020-07-27 15:24:38 +0000150 // exceptional treatment for all states except aniStResetting
151 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
152 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
153 aniStConfigDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000154 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000155 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000156 },
157
158 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000159 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
160 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(e) },
161 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(e) },
162 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(e) },
163 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(e) },
164 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(e) },
165 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(e) },
166 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
167 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
168 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
169 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(e) },
170 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000171 },
172 )
173 if instFsm.pAdaptFsm.pFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530174 logger.Errorw("uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000175 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000176 return nil
177 }
178
mpagenko01e726e2020-10-23 09:45:29 +0000179 logger.Infow("uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000180 return instFsm
181}
182
Himani Chawla6d2ae152020-09-02 13:11:20 +0530183//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
184func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000185 oFsm.chSuccess = aChSuccess
186 oFsm.procStep = aProcStep
187 oFsm.chanSet = true
188}
189
Himani Chawla6d2ae152020-09-02 13:11:20 +0530190func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530191 if aPAFsm != nil && aPAFsm.pFsm != nil {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800192 uniTpKey := uniTP{uniID: oFsm.pOnuUniPort.uniID, tpID: oFsm.techProfileID}
Himani Chawla26e555c2020-08-31 12:30:20 +0530193 //stick to pythonAdapter numbering scheme
194 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800195 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
196 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530197
Girish Gowdra041dcb32020-11-16 16:54:30 -0800198 /*
199 // Find a free TCONT Instance ID and use it
200 foundFreeTcontInstID := false
201 */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530202 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800203
204 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
205 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
206 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
207 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
208 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
209 // when the ONU is discovered.
210 /*
211 for _, tcontInstID := range tcontInstKeys {
212 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
213 returnVal := tconInst["AllocId"]
214 if returnVal != nil {
215 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
216 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
217 if allocID == 0xff || allocID == 0xffff {
218 foundFreeTcontInstID = true
219 oFsm.tcont0ID = uint16(tcontInstID)
220 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
221 "device-id": oFsm.deviceID})
222 break
223 }
224 } else {
225 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
226 }
227 } else {
228 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
229 }
230 }
231 */
232
233 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
234 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
235 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
236 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
237 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
238 // TP ID will increment in single digit
239 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
240 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
241 "device-id": oFsm.deviceID})
242 } else {
243 logger.Errorw("tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
244 if oFsm.chanSet {
245 // indicate processing error/abort to the caller
246 oFsm.chSuccess <- 0
247 oFsm.chanSet = false //reset the internal channel state
248 }
249 //reset the state machine to enable usage on subsequent requests
250 _ = aPAFsm.pFsm.Event(aniEvReset)
251 return
252 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530253 } else {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800254 logger.Errorw("No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
255 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530256 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800257 /*
258 if !foundFreeTcontInstID {
259 // This should never happen. If it does, the behavior is unpredictable.
260 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
261 }*/
262
263 // Access critical state with lock
264 oFsm.pUniTechProf.mutexTPState.Lock()
265 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[uniTpKey].tcontParams.allocID
266 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[uniTpKey].mapGemPortParams
267 oFsm.pUniTechProf.mutexTPState.Unlock()
268
Himani Chawla26e555c2020-08-31 12:30:20 +0530269 loGemPortAttribs := ponAniGemPortAttribs{}
270 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800271
272 for _, gemEntry := range mapGemPortParams {
Himani Chawla26e555c2020-08-31 12:30:20 +0530273 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
274
Himani Chawla6d2ae152020-09-02 13:11:20 +0530275 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530276
277 loGemPortAttribs.gemPortID = gemEntry.gemPortID
278 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
279 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
280 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
281 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
282
283 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
284 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
285 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
286 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
287 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
288 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
289
290 usQueueFound := false
291 dsQueueFound := false
292 for _, mgmtEntityID := range queueInstKeys {
293 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
294 returnVal := meAttributes["RelatedPort"]
295 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530296 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530297 if relatedPort == usQrelPortMask {
298 loGemPortAttribs.upQueueID = mgmtEntityID
299 logger.Debugw("UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000300 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530301 usQueueFound = true
302 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
303 loGemPortAttribs.downQueueID = mgmtEntityID
304 logger.Debugw("DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000305 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530306 dsQueueFound = true
307 }
308 if usQueueFound && dsQueueFound {
309 break
310 }
311 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000312 logger.Warnw("Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530313 }
314 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000315 logger.Warnw("'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530316 }
317 } else {
318 logger.Warnw("No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000319 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530320 }
321 }
322 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000323 logger.Warnw("No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530324 }
325 loGemPortAttribs.direction = gemEntry.direction
326 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
327 loGemPortAttribs.weight = gemEntry.queueWeight
328 loGemPortAttribs.pbitString = gemEntry.pbitString
329
330 logger.Debugw("prio-related GemPort attributes:", log.Fields{
331 "gemPortID": loGemPortAttribs.gemPortID,
332 "upQueueID": loGemPortAttribs.upQueueID,
333 "downQueueID": loGemPortAttribs.downQueueID,
334 "pbitString": loGemPortAttribs.pbitString,
335 "prioQueueIndex": gemEntry.prioQueueIndex,
336 })
337
338 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
339 }
340 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
341 }
342}
343
Himani Chawla6d2ae152020-09-02 13:11:20 +0530344func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000345 logger.Debugw("UniPonAniConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000346 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000347 // in case the used channel is not yet defined (can be re-used after restarts)
348 if oFsm.omciMIdsResponseReceived == nil {
349 oFsm.omciMIdsResponseReceived = make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530350 logger.Debug("uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000351 } else {
352 // as we may 're-use' this instance of FSM and the connected channel
353 // make sure there is no 'lingering' request in the already existing channel:
354 // (simple loop sufficient as we are the only receiver)
355 for len(oFsm.omciMIdsResponseReceived) > 0 {
356 <-oFsm.omciMIdsResponseReceived
357 }
358 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000359 //ensure internal slices are empty (which might be set from previous run) - release memory
360 oFsm.gemPortAttribsSlice = nil
361
mpagenko3dbcdd22020-07-22 07:38:45 +0000362 // start go routine for processing of LockState messages
mpagenkodff5dda2020-08-28 11:52:01 +0000363 go oFsm.processOmciAniMessages()
mpagenko3dbcdd22020-07-22 07:38:45 +0000364
365 //let the state machine run forward from here directly
366 pConfigAniStateAFsm := oFsm.pAdaptFsm
367 if pConfigAniStateAFsm != nil {
368 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530369 go oFsm.prepareAndEnterConfigState(pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000370
mpagenko3dbcdd22020-07-22 07:38:45 +0000371 }
372}
373
Himani Chawla6d2ae152020-09-02 13:11:20 +0530374func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
375 logger.Debugw("uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000376 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000377 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000378 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
379 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
380 //accept also nil as (error) return value for writing to LastTx
381 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000382 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000383}
384
Himani Chawla6d2ae152020-09-02 13:11:20 +0530385func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
386 logger.Debugw("uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000387 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
388 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000389 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000390 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
391 meParams := me.ParamData{
392 EntityID: oFsm.macBPCD0ID,
393 Attributes: me.AttributeValueMap{
394 "BridgeIdPointer": bridgePtr,
395 "PortNum": 0xFF, //fixed unique ANI side indication
396 "TpType": 3, //for .1PMapper
397 "TpPointer": oFsm.mapperSP0ID,
398 },
399 }
400 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
401 oFsm.pAdaptFsm.commChan, meParams)
402 //accept also nil as (error) return value for writing to LastTx
403 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000404 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000405
406}
407
Himani Chawla6d2ae152020-09-02 13:11:20 +0530408func (oFsm *uniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
409 logger.Debugw("uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000410 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
411 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000412 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000413 meParams := me.ParamData{
414 EntityID: oFsm.tcont0ID,
415 Attributes: me.AttributeValueMap{
416 "AllocId": oFsm.alloc0ID,
417 },
418 }
419 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
420 oFsm.pAdaptFsm.commChan, meParams)
421 //accept also nil as (error) return value for writing to LastTx
422 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000423 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000424}
425
Himani Chawla6d2ae152020-09-02 13:11:20 +0530426func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
427 logger.Debugw("uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000428 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000429 go oFsm.performCreatingGemNCTPs()
430}
431
Himani Chawla6d2ae152020-09-02 13:11:20 +0530432func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
433 logger.Debugw("uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000434 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000435 go oFsm.performCreatingGemIWs()
436}
437
Himani Chawla6d2ae152020-09-02 13:11:20 +0530438func (oFsm *uniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
439 logger.Debugw("uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000440 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000441 go oFsm.performSettingPQs()
442}
443
Himani Chawla6d2ae152020-09-02 13:11:20 +0530444func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
445 logger.Debugw("uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko01e726e2020-10-23 09:45:29 +0000446 "toGemIw": 1024 /* cmp above */, "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000447
Himani Chawla6d2ae152020-09-02 13:11:20 +0530448 logger.Debugw("uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000449 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000450 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000451
mpagenko3dbcdd22020-07-22 07:38:45 +0000452 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000453 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530454 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000455 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000456
457 //assign the GemPorts according to the configured Prio
458 var loPrioGemPortArray [8]uint16
459 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
460 for i := 0; i < 8; i++ {
461 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
462 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
463 if prio == 1 { // Check this p-bit is set
464 if loPrioGemPortArray[i] == 0 {
465 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
466 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530467 logger.Warnw("uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000468 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000469 "SetGemPort": loPrioGemPortArray[i]})
470 }
471 }
472 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530473 logger.Warnw("uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000474 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000475 "prioString": gemPortAttribs.pbitString, "position": i})
476 }
477
478 }
479 }
480 var foundIwPtr bool = false
Himani Chawla4d908332020-08-31 12:30:20 +0530481 for index, value := range loPrioGemPortArray {
482 if value != 0 {
483 foundIwPtr = true
484 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530485 meParams.Attributes[meAttribute] = value
mpagenko01e726e2020-10-23 09:45:29 +0000486 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
487 "for Prio": index,
488 "IwPtr": strconv.FormatInt(int64(value), 16),
489 "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530490 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000491 }
Himani Chawla4d908332020-08-31 12:30:20 +0530492
493 if !foundIwPtr {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000494 logger.Errorw("UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000495 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000496 //let's reset the state machine in order to release all resources now
497 pConfigAniStateAFsm := oFsm.pAdaptFsm
498 if pConfigAniStateAFsm != nil {
499 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530500 go func(aPAFsm *AdapterFsm) {
501 if aPAFsm != nil && aPAFsm.pFsm != nil {
502 _ = aPAFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000503 }
504 }(pConfigAniStateAFsm)
505 }
506 }
507
mpagenko3dbcdd22020-07-22 07:38:45 +0000508 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
509 oFsm.pAdaptFsm.commChan, meParams)
510 //accept also nil as (error) return value for writing to LastTx
511 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000512 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000513}
514
Himani Chawla6d2ae152020-09-02 13:11:20 +0530515func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000516 logger.Debugw("uniPonAniConfigFsm send dh event notification recheck pending flow config", log.Fields{
517 "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
518 //use DeviceHandler event notification directly
519 oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
520 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800521 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000522 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
523 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
mpagenko3dbcdd22020-07-22 07:38:45 +0000524
mpagenko01e726e2020-10-23 09:45:29 +0000525 if oFsm.chanSet {
526 // indicate processing done to the caller
527 logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
528 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
529 oFsm.chSuccess <- oFsm.procStep
530 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000531 }
mpagenko01e726e2020-10-23 09:45:29 +0000532
533 //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 +0000534}
535
Himani Chawla6d2ae152020-09-02 13:11:20 +0530536func (oFsm *uniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000537 logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000538
mpagenko3dbcdd22020-07-22 07:38:45 +0000539 pConfigAniStateAFsm := oFsm.pAdaptFsm
540 if pConfigAniStateAFsm != nil {
541 // abort running message processing
542 fsmAbortMsg := Message{
543 Type: TestMsg,
544 Data: TestMessage{
545 TestMessageVal: AbortMessageProcessing,
546 },
547 }
548 pConfigAniStateAFsm.commChan <- fsmAbortMsg
549
550 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530551 go func(aPAFsm *AdapterFsm) {
552 if aPAFsm != nil && aPAFsm.pFsm != nil {
553 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000554 }
555 }(pConfigAniStateAFsm)
556 }
557}
558
Himani Chawla6d2ae152020-09-02 13:11:20 +0530559func (oFsm *uniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000560 logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
561 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000562
mpagenko01e726e2020-10-23 09:45:29 +0000563 //remove all TechProf related internal data to allow for new configuration (e.g. with disable/enable procedure)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800564 oFsm.pUniTechProf.clearAniSideConfig(oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000565}
566
Himani Chawla6d2ae152020-09-02 13:11:20 +0530567func (oFsm *uniPonAniConfigFsm) processOmciAniMessages( /*ctx context.Context*/ ) {
mpagenko01e726e2020-10-23 09:45:29 +0000568 logger.Debugw("Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000569loop:
570 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000571 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000572 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000573 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530574 message, ok := <-oFsm.pAdaptFsm.commChan
575 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +0000576 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530577 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
578 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
579 break loop
580 }
mpagenko01e726e2020-10-23 09:45:29 +0000581 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530582
583 switch message.Type {
584 case TestMsg:
585 msg, _ := message.Data.(TestMessage)
586 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +0000587 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000588 break loop
589 }
mpagenko01e726e2020-10-23 09:45:29 +0000590 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530591 case OMCI:
592 msg, _ := message.Data.(OmciMessage)
593 oFsm.handleOmciAniConfigMessage(msg)
594 default:
mpagenko01e726e2020-10-23 09:45:29 +0000595 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530596 "message.Type": message.Type})
597 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000598
Himani Chawla4d908332020-08-31 12:30:20 +0530599 }
mpagenko01e726e2020-10-23 09:45:29 +0000600 logger.Infow("End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530601}
602
Himani Chawla6d2ae152020-09-02 13:11:20 +0530603func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530604 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
605 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200606 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000607 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530608 return
609 }
610 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
611 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200612 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000613 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530614 return
615 }
mpagenko01e726e2020-10-23 09:45:29 +0000616 logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000617 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
618 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
619 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
620 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
621 // maybe we can use just the same eventName for different state transitions like "forward"
622 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
623 switch oFsm.pLastTxMeInstance.GetName() {
624 case "Ieee8021PMapperServiceProfile":
625 { // let the FSM proceed ...
626 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
627 }
628 case "MacBridgePortConfigurationData":
629 { // let the FSM proceed ...
630 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
631 }
632 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
633 { // let aniConfig Multi-Id processing proceed by stopping the wait function
634 oFsm.omciMIdsResponseReceived <- true
635 }
636 }
637 }
638 } else {
Himani Chawla4d908332020-08-31 12:30:20 +0530639 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
640 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
641 return
642 }
Himani Chawla4d908332020-08-31 12:30:20 +0530643}
644
Himani Chawla6d2ae152020-09-02 13:11:20 +0530645func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530646 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
647 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200648 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000649 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530650 return
651 }
652 msgObj, msgOk := msgLayer.(*omci.SetResponse)
653 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200654 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000655 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530656 return
657 }
mpagenko01e726e2020-10-23 09:45:29 +0000658 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530659 if msgObj.Result != me.Success {
Andrea Campanella6515c582020-10-05 11:25:00 +0200660 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000661 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530662 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
663 return
664 }
mpagenko01e726e2020-10-23 09:45:29 +0000665 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
666 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530667 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
668 // if, then something like:
669 //oFsm.pOnuDB.StoreMe(msgObj)
670
mpagenko01e726e2020-10-23 09:45:29 +0000671 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530672 case "TCont":
673 { // let the FSM proceed ...
674 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
675 }
676 case "PriorityQueue":
677 { // let the PrioQueue init proceed by stopping the wait function
678 oFsm.omciMIdsResponseReceived <- true
679 }
680 case "Ieee8021PMapperServiceProfile":
681 { // let the FSM proceed ...
682 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
683 }
684 }
685 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000686}
687
Himani Chawla6d2ae152020-09-02 13:11:20 +0530688func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +0000689 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000690 "msgType": msg.OmciMsg.MessageType})
691
692 switch msg.OmciMsg.MessageType {
693 case omci.CreateResponseType:
694 {
Himani Chawla4d908332020-08-31 12:30:20 +0530695 oFsm.handleOmciAniConfigCreateResponseMessage(msg)
696
mpagenko3dbcdd22020-07-22 07:38:45 +0000697 } //CreateResponseType
698 case omci.SetResponseType:
699 {
Himani Chawla4d908332020-08-31 12:30:20 +0530700 oFsm.handleOmciAniConfigSetResponseMessage(msg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000701
mpagenko3dbcdd22020-07-22 07:38:45 +0000702 } //SetResponseType
703 default:
704 {
Andrea Campanella6515c582020-10-05 11:25:00 +0200705 logger.Errorw("uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +0000706 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000707 return
708 }
709 }
710}
711
Himani Chawla6d2ae152020-09-02 13:11:20 +0530712func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000713 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
714 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530715 logger.Debugw("uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000716 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
717 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000718 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000719 meParams := me.ParamData{
720 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
721 Attributes: me.AttributeValueMap{
722 "PortId": gemPortAttribs.gemPortID,
723 "TContPointer": oFsm.tcont0ID,
724 "Direction": gemPortAttribs.direction,
725 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
726 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
727 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
728 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
729 },
730 }
731 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
732 oFsm.pAdaptFsm.commChan, meParams)
733 //accept also nil as (error) return value for writing to LastTx
734 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000735 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000736
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000737 //verify response
738 err := oFsm.waitforOmciResponse()
739 if err != nil {
740 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000741 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530742 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000743 return
744 }
745 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000746
747 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000748 logger.Debugw("GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530749 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000750}
751
Himani Chawla6d2ae152020-09-02 13:11:20 +0530752func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000753 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
754 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530755 logger.Debugw("uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000756 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
757 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000758 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000759 meParams := me.ParamData{
760 EntityID: gemPortAttribs.gemPortID,
761 Attributes: me.AttributeValueMap{
762 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
763 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
764 "ServiceProfilePointer": oFsm.mapperSP0ID,
765 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
766 "GalProfilePointer": galEthernetEID,
767 },
768 }
769 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
770 oFsm.pAdaptFsm.commChan, meParams)
771 //accept also nil as (error) return value for writing to LastTx
772 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000773 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000774
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000775 //verify response
776 err := oFsm.waitforOmciResponse()
777 if err != nil {
778 logger.Errorw("GemIwTp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000779 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530780 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000781 return
782 }
783 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000784
785 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000786 logger.Debugw("GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530787 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000788}
789
Himani Chawla6d2ae152020-09-02 13:11:20 +0530790func (oFsm *uniPonAniConfigFsm) performSettingPQs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000791 const cu16StrictPrioWeight uint16 = 0xFFFF
792 //find all upstream PrioQueues related to this T-Cont
793 loQueueMap := ordered_map.NewOrderedMap()
794 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
795 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +0530796 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000797 //key does not yet exist
798 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
799 }
800 } else {
801 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
802 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000803 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000804
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000805 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
806 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
807 // complete chain is not valid, then some error should be thrown and configuration can be aborted
808 // or even be finished without correct SP/WRR setting
809
810 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
811 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
812 // even though its T-Cont seems to be wrong ...
813 loTrafficSchedulerEID := 0x8000
814 //for all found queues
815 iter := loQueueMap.IterFunc()
816 for kv, ok := iter(); ok; kv, ok = iter() {
817 queueIndex := (kv.Key).(uint16)
818 meParams := me.ParamData{
819 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +0530820 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000821 }
822 if (kv.Value).(uint16) == cu16StrictPrioWeight {
823 //StrictPrio indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530824 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000825 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000826 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000827 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
828 } else {
829 //WRR indication
Himani Chawla6d2ae152020-09-02 13:11:20 +0530830 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000831 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
832 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +0000833 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000834 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
835 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
836 }
837 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
838 oFsm.pAdaptFsm.commChan, meParams)
839 //accept also nil as (error) return value for writing to LastTx
840 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000841 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000842
843 //verify response
844 err := oFsm.waitforOmciResponse()
845 if err != nil {
846 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000847 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +0530848 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000849 return
850 }
851
852 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
853 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
854 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
855 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
856
857 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +0000858
859 // if Config has been done for all PrioQueue instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000860 logger.Debugw("PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530861 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000862}
863
Himani Chawla6d2ae152020-09-02 13:11:20 +0530864func (oFsm *uniPonAniConfigFsm) waitforOmciResponse() error {
mpagenko3dbcdd22020-07-22 07:38:45 +0000865 select {
Himani Chawla4d908332020-08-31 12:30:20 +0530866 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +0000867 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000868 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000869 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 +0000870 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
871 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000872 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +0530873 if success {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530874 logger.Debug("uniPonAniConfigFsm multi entity response received")
mpagenko3dbcdd22020-07-22 07:38:45 +0000875 return nil
876 }
877 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +0000878 logger.Warnw("uniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
879 return fmt.Errorf("uniPonAniConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +0000880 }
881}