blob: 2cef9897a38c5ce529bd50f9f61702a2ec610b57 [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"
ozgecanetsia4b232302020-11-11 10:58:10 +030022 "encoding/binary"
Himani Chawla4d908332020-08-31 12:30:20 +053023 "fmt"
ozgecanetsia4b232302020-11-11 10:58:10 +030024 "net"
mpagenko3dbcdd22020-07-22 07:38:45 +000025 "strconv"
26 "time"
27
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000028 "github.com/cevaris/ordered_map"
mpagenko3dbcdd22020-07-22 07:38:45 +000029 "github.com/looplab/fsm"
mpagenko3dbcdd22020-07-22 07:38:45 +000030 "github.com/opencord/omci-lib-go"
31 me "github.com/opencord/omci-lib-go/generated"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 //ic "github.com/opencord/voltha-protos/v3/go/inter_container"
34 //"github.com/opencord/voltha-protos/v3/go/openflow_13"
35 //"github.com/opencord/voltha-protos/v3/go/voltha"
36)
37
mpagenko1cc3cb42020-07-27 15:24:38 +000038const (
39 // events of config PON ANI port FSM
mpagenko8b07c1b2020-11-26 10:36:31 +000040 aniEvStart = "aniEvStart"
41 aniEvStartConfig = "aniEvStartConfig"
42 aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
43 aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
44 aniEvRxTcontsResp = "aniEvRxTcontsResp"
45 aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
46 aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
47 aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
48 aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
49 aniEvRemGemiw = "aniEvRemGemiw"
50 aniEvRxRemGemiwResp = "aniEvRxRemGemiwResp"
51 aniEvRxRemGemntpResp = "aniEvRxRemGemntpResp"
52 aniEvRemTcontPath = "aniEvRemTcontPath"
53 aniEvRxResetTcontResp = "aniEvRxResetTcontResp"
54 aniEvRxRem1pMapperResp = "aniEvRxRem1pMapperResp"
55 aniEvRxRemAniBPCDResp = "aniEvRxRemAniBPCDResp"
56 aniEvTimeoutSimple = "aniEvTimeoutSimple"
57 aniEvTimeoutMids = "aniEvTimeoutMids"
58 aniEvReset = "aniEvReset"
59 aniEvRestart = "aniEvRestart"
mpagenko1cc3cb42020-07-27 15:24:38 +000060)
61const (
62 // states of config PON ANI port FSM
63 aniStDisabled = "aniStDisabled"
64 aniStStarting = "aniStStarting"
65 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
66 aniStCreatingMBPCD = "aniStCreatingMBPCD"
67 aniStSettingTconts = "aniStSettingTconts"
68 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
69 aniStCreatingGemIWs = "aniStCreatingGemIWs"
70 aniStSettingPQs = "aniStSettingPQs"
71 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
72 aniStConfigDone = "aniStConfigDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000073 aniStRemovingGemIW = "aniStRemovingGemIW"
74 aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
75 aniStResetTcont = "aniStResetTcont"
76 aniStRemDot1PMapper = "aniStRemDot1PMapper"
77 aniStRemAniBPCD = "aniStRemAniBPCD"
78 aniStRemoveDone = "aniStRemoveDone"
mpagenko1cc3cb42020-07-27 15:24:38 +000079 aniStResetting = "aniStResetting"
80)
81
Girish Gowdra041dcb32020-11-16 16:54:30 -080082const (
83 tpIDOffset = 64
84)
85
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000086type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030087 gemPortID uint16
88 upQueueID uint16
89 downQueueID uint16
90 direction uint8
91 qosPolicy string
92 weight uint8
93 pbitString string
94 isMulticast bool
95 multicastGemID uint16
96 staticACL string
97 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000098}
99
Himani Chawla6d2ae152020-09-02 13:11:20 +0530100//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
101type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000102 pDeviceHandler *deviceHandler
103 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530104 pOmciCC *omciCC
105 pOnuUniPort *onuUniPort
106 pUniTechProf *onuUniTechProf
107 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800108 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000109 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000110 requestEvent OnuDeviceEvent
Himani Chawla4d908332020-08-31 12:30:20 +0530111 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000112 pAdaptFsm *AdapterFsm
113 chSuccess chan<- uint8
114 procStep uint8
115 chanSet bool
116 mapperSP0ID uint16
117 macBPCD0ID uint16
118 tcont0ID uint16
119 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000120 gemPortAttribsSlice []ponAniGemPortAttribs
mpagenko01e726e2020-10-23 09:45:29 +0000121 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000122 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenko3dbcdd22020-07-22 07:38:45 +0000123}
124
Himani Chawla6d2ae152020-09-02 13:11:20 +0530125//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
126func newUniPonAniConfigFsm(apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800127 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000128 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530129 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000130 pDeviceHandler: apDeviceHandler,
131 deviceID: apDeviceHandler.deviceID,
132 pOmciCC: apDevOmciCC,
133 pOnuUniPort: apUniPort,
134 pUniTechProf: apUniTechProf,
135 pOnuDB: apOnuDB,
136 techProfileID: aTechProfileID,
137 requestEvent: aRequestEvent,
138 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000139 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000140 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
141
mpagenko01e726e2020-10-23 09:45:29 +0000142 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000143 if instFsm.pAdaptFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530144 logger.Errorw("uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000145 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000146 return nil
147 }
148
149 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000150 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000151 fsm.Events{
152
mpagenko1cc3cb42020-07-27 15:24:38 +0000153 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000154
155 //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 +0000156 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000157 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000158 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
159 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000160 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000161 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000162 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000163 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000164 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000165 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000166 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000167
mpagenko8b07c1b2020-11-26 10:36:31 +0000168 //for removing Gem related resources
169 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
170 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
171 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
172
173 //for removing TCONT related resources
174 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
175 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
176 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
177 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
178
179 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
180 aniStRemovingGemIW, aniStRemovingGemNCTP,
181 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000182 {Name: aniEvTimeoutMids, Src: []string{
183 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000184
mpagenko1cc3cb42020-07-27 15:24:38 +0000185 // exceptional treatment for all states except aniStResetting
186 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
187 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenko8b07c1b2020-11-26 10:36:31 +0000188 aniStConfigDone, aniStRemovingGemIW, aniStRemovingGemNCTP,
189 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000190 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000191 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000192 },
193
194 fsm.Callbacks{
mpagenko1cc3cb42020-07-27 15:24:38 +0000195 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
196 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(e) },
197 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(e) },
198 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(e) },
199 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(e) },
200 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(e) },
201 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(e) },
202 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(e) },
203 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(e) },
204 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(e) },
mpagenko8b07c1b2020-11-26 10:36:31 +0000205 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(e) },
206 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(e) },
207 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(e) },
208 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(e) },
209 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(e) },
210 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(e) },
mpagenko1cc3cb42020-07-27 15:24:38 +0000211 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(e) },
212 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000213 },
214 )
215 if instFsm.pAdaptFsm.pFsm == nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530216 logger.Errorw("uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000217 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000218 return nil
219 }
220
Holger Hildebrandt80129db2020-11-23 10:49:32 +0000221 logger.Debugw("uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000222 return instFsm
223}
224
Himani Chawla6d2ae152020-09-02 13:11:20 +0530225//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
226func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000227 oFsm.chSuccess = aChSuccess
228 oFsm.procStep = aProcStep
229 oFsm.chanSet = true
230}
231
Himani Chawla6d2ae152020-09-02 13:11:20 +0530232func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530233 if aPAFsm != nil && aPAFsm.pFsm != nil {
234 //stick to pythonAdapter numbering scheme
235 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800236 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
237 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530238
Girish Gowdra041dcb32020-11-16 16:54:30 -0800239 /*
240 // Find a free TCONT Instance ID and use it
241 foundFreeTcontInstID := false
242 */
Himani Chawla6d2ae152020-09-02 13:11:20 +0530243 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800244
245 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
246 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
247 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
248 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
249 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
250 // when the ONU is discovered.
251 /*
252 for _, tcontInstID := range tcontInstKeys {
253 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
254 returnVal := tconInst["AllocId"]
255 if returnVal != nil {
256 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
257 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
258 if allocID == 0xff || allocID == 0xffff {
259 foundFreeTcontInstID = true
260 oFsm.tcont0ID = uint16(tcontInstID)
261 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
262 "device-id": oFsm.deviceID})
263 break
264 }
265 } else {
266 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
267 }
268 } else {
269 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
270 }
271 }
272 */
273
274 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
275 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
276 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
277 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
278 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
279 // TP ID will increment in single digit
280 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
281 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
282 "device-id": oFsm.deviceID})
283 } else {
284 logger.Errorw("tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
285 if oFsm.chanSet {
286 // indicate processing error/abort to the caller
287 oFsm.chSuccess <- 0
288 oFsm.chanSet = false //reset the internal channel state
289 }
290 //reset the state machine to enable usage on subsequent requests
291 _ = aPAFsm.pFsm.Event(aniEvReset)
292 return
293 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530294 } else {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800295 logger.Errorw("No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
296 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530297 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800298 /*
299 if !foundFreeTcontInstID {
300 // This should never happen. If it does, the behavior is unpredictable.
301 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
302 }*/
303
304 // Access critical state with lock
305 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000306 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
307 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800308 oFsm.pUniTechProf.mutexTPState.Unlock()
309
Himani Chawla26e555c2020-08-31 12:30:20 +0530310 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800311 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300312 loGemPortAttribs := ponAniGemPortAttribs{}
313
Himani Chawla26e555c2020-08-31 12:30:20 +0530314 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
315
Himani Chawla6d2ae152020-09-02 13:11:20 +0530316 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530317
318 loGemPortAttribs.gemPortID = gemEntry.gemPortID
319 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
320 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
321 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
322 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
323
324 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
325 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
326 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
327 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
328 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
329 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
330
331 usQueueFound := false
332 dsQueueFound := false
333 for _, mgmtEntityID := range queueInstKeys {
334 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
335 returnVal := meAttributes["RelatedPort"]
336 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530337 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530338 if relatedPort == usQrelPortMask {
339 loGemPortAttribs.upQueueID = mgmtEntityID
340 logger.Debugw("UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000341 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530342 usQueueFound = true
343 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
344 loGemPortAttribs.downQueueID = mgmtEntityID
345 logger.Debugw("DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000346 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530347 dsQueueFound = true
348 }
349 if usQueueFound && dsQueueFound {
350 break
351 }
352 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000353 logger.Warnw("Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530354 }
355 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000356 logger.Warnw("'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530357 }
358 } else {
359 logger.Warnw("No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000360 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530361 }
362 }
363 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000364 logger.Warnw("No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530365 }
366 loGemPortAttribs.direction = gemEntry.direction
367 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
368 loGemPortAttribs.weight = gemEntry.queueWeight
369 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300370 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300371 //TODO this might effectively ignore the for loop starting at line 316
372 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300373 loGemPortAttribs.isMulticast = true
374 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
375 loGemPortAttribs.staticACL = gemEntry.staticACL
376 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530377
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300378 logger.Debugw("Multicast GemPort attributes:", log.Fields{
379 "gemPortID": loGemPortAttribs.gemPortID,
380 "isMulticast": loGemPortAttribs.isMulticast,
381 "multicastGemID": loGemPortAttribs.multicastGemID,
382 "staticACL": loGemPortAttribs.staticACL,
383 "dynamicACL": loGemPortAttribs.dynamicACL,
384 })
385
386 } else {
387 logger.Debugw("Upstream GemPort attributes:", log.Fields{
388 "gemPortID": loGemPortAttribs.gemPortID,
389 "upQueueID": loGemPortAttribs.upQueueID,
390 "downQueueID": loGemPortAttribs.downQueueID,
391 "pbitString": loGemPortAttribs.pbitString,
392 "prioQueueIndex": gemEntry.prioQueueIndex,
393 })
394 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530395
396 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
397 }
398 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
399 }
400}
401
Himani Chawla6d2ae152020-09-02 13:11:20 +0530402func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000403 logger.Debugw("UniPonAniConfigFsm start", log.Fields{
404 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000405 // in case the used channel is not yet defined (can be re-used after restarts)
406 if oFsm.omciMIdsResponseReceived == nil {
407 oFsm.omciMIdsResponseReceived = make(chan bool)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530408 logger.Debug("uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000409 } else {
410 // as we may 're-use' this instance of FSM and the connected channel
411 // make sure there is no 'lingering' request in the already existing channel:
412 // (simple loop sufficient as we are the only receiver)
413 for len(oFsm.omciMIdsResponseReceived) > 0 {
414 <-oFsm.omciMIdsResponseReceived
415 }
416 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000417 //ensure internal slices are empty (which might be set from previous run) - release memory
418 oFsm.gemPortAttribsSlice = nil
419
mpagenko3dbcdd22020-07-22 07:38:45 +0000420 // start go routine for processing of LockState messages
mpagenkodff5dda2020-08-28 11:52:01 +0000421 go oFsm.processOmciAniMessages()
mpagenko3dbcdd22020-07-22 07:38:45 +0000422
423 //let the state machine run forward from here directly
424 pConfigAniStateAFsm := oFsm.pAdaptFsm
425 if pConfigAniStateAFsm != nil {
426 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530427 go oFsm.prepareAndEnterConfigState(pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000428
mpagenko3dbcdd22020-07-22 07:38:45 +0000429 }
430}
431
Himani Chawla6d2ae152020-09-02 13:11:20 +0530432func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(e *fsm.Event) {
433 logger.Debugw("uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000434 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000435 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
436 oFsm.requestEventOffset = 0 //0 offset for last config request activity
mpagenko3dbcdd22020-07-22 07:38:45 +0000437 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
438 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
439 //accept also nil as (error) return value for writing to LastTx
440 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000441 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000442}
443
Himani Chawla6d2ae152020-09-02 13:11:20 +0530444func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(e *fsm.Event) {
445 logger.Debugw("uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000446 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
447 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000448 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000449 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
450 meParams := me.ParamData{
451 EntityID: oFsm.macBPCD0ID,
452 Attributes: me.AttributeValueMap{
453 "BridgeIdPointer": bridgePtr,
454 "PortNum": 0xFF, //fixed unique ANI side indication
455 "TpType": 3, //for .1PMapper
456 "TpPointer": oFsm.mapperSP0ID,
457 },
458 }
459 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
460 oFsm.pAdaptFsm.commChan, meParams)
461 //accept also nil as (error) return value for writing to LastTx
462 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000463 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000464}
465
Himani Chawla6d2ae152020-09-02 13:11:20 +0530466func (oFsm *uniPonAniConfigFsm) enterSettingTconts(e *fsm.Event) {
467 logger.Debugw("uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000468 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
469 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000470 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000471 meParams := me.ParamData{
472 EntityID: oFsm.tcont0ID,
473 Attributes: me.AttributeValueMap{
474 "AllocId": oFsm.alloc0ID,
475 },
476 }
477 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
478 oFsm.pAdaptFsm.commChan, meParams)
479 //accept also nil as (error) return value for writing to LastTx
480 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000481 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000482}
483
Himani Chawla6d2ae152020-09-02 13:11:20 +0530484func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(e *fsm.Event) {
485 logger.Debugw("uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000486 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000487 go oFsm.performCreatingGemNCTPs()
488}
489
Himani Chawla6d2ae152020-09-02 13:11:20 +0530490func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(e *fsm.Event) {
491 logger.Debugw("uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000492 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000493 go oFsm.performCreatingGemIWs()
494}
495
Himani Chawla6d2ae152020-09-02 13:11:20 +0530496func (oFsm *uniPonAniConfigFsm) enterSettingPQs(e *fsm.Event) {
497 logger.Debugw("uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000498 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000499 go oFsm.performSettingPQs()
500}
501
Himani Chawla6d2ae152020-09-02 13:11:20 +0530502func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300503
Himani Chawla6d2ae152020-09-02 13:11:20 +0530504 logger.Debugw("uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000505 "toGemIw": 1024, /* cmp above */
506 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000507
Himani Chawla6d2ae152020-09-02 13:11:20 +0530508 logger.Debugw("uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000509 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000510 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000511
mpagenko3dbcdd22020-07-22 07:38:45 +0000512 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000513 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530514 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000515 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000516
517 //assign the GemPorts according to the configured Prio
518 var loPrioGemPortArray [8]uint16
519 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300520 if gemPortAttribs.isMulticast {
521 logger.Debugw("uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
522 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
523 "prioString": gemPortAttribs.pbitString})
524 continue
525 }
526 if gemPortAttribs.pbitString == "" {
527 logger.Warnw("uniPonAniConfigFsm PrioString empty string error", log.Fields{
528 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
529 "prioString": gemPortAttribs.pbitString})
530 continue
531 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000532 for i := 0; i < 8; i++ {
533 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
534 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
535 if prio == 1 { // Check this p-bit is set
536 if loPrioGemPortArray[i] == 0 {
537 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
538 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530539 logger.Warnw("uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000540 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000541 "SetGemPort": loPrioGemPortArray[i]})
542 }
543 }
544 } else {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530545 logger.Warnw("uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000546 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000547 "prioString": gemPortAttribs.pbitString, "position": i})
548 }
549
550 }
551 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300552
ozgecanetsia4b232302020-11-11 10:58:10 +0300553 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530554 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300555 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530556 if value != 0 {
557 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530558 meParams.Attributes[meAttribute] = value
mpagenko01e726e2020-10-23 09:45:29 +0000559 logger.Debugw("UniPonAniConfigFsm Set::1pMapper", log.Fields{
560 "for Prio": index,
561 "IwPtr": strconv.FormatInt(int64(value), 16),
562 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300563 } else {
564 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
565 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530566 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000567 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300568 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
569 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530570
571 if !foundIwPtr {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300572 logger.Debugw("UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000573 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300574 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
575 // this reset needs to be performed only if the tech profile provides upstream gem ports but no priority is set
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000576 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300577 //pConfigAniStateAFsm := oFsm.pAdaptFsm
578 //if pConfigAniStateAFsm != nil {
579 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
580 // go func(aPAFsm *AdapterFsm) {
581 // if aPAFsm != nil && aPAFsm.pFsm != nil {
582 // _ = aPAFsm.pFsm.Event(aniEvReset)
583 // }
584 // }(pConfigAniStateAFsm)
585 //}
586 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000587 pConfigAniStateAFsm := oFsm.pAdaptFsm
588 if pConfigAniStateAFsm != nil {
589 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530590 go func(aPAFsm *AdapterFsm) {
591 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300592 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000593 }
594 }(pConfigAniStateAFsm)
595 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300596 } else {
597 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), ConstDefaultOmciTimeout, true,
598 oFsm.pAdaptFsm.commChan, meParams)
599 //accept also nil as (error) return value for writing to LastTx
600 // - this avoids misinterpretation of new received OMCI messages
601 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000602 }
603
mpagenko3dbcdd22020-07-22 07:38:45 +0000604}
605
Himani Chawla6d2ae152020-09-02 13:11:20 +0530606func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000607 logger.Debugw("uniPonAniConfigFsm ani config done", log.Fields{
608 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko01e726e2020-10-23 09:45:29 +0000609 //use DeviceHandler event notification directly
mpagenko8b07c1b2020-11-26 10:36:31 +0000610 oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000611 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800612 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000613 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000614 // but only in case the techProfile was configured (not deleted)
615 if oFsm.requestEventOffset == 0 {
616 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(oFsm.pOnuUniPort)
617 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000618
mpagenko01e726e2020-10-23 09:45:29 +0000619 if oFsm.chanSet {
620 // indicate processing done to the caller
621 logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
622 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
623 oFsm.chSuccess <- oFsm.procStep
624 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000625 }
mpagenko01e726e2020-10-23 09:45:29 +0000626
627 //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 +0000628}
629
mpagenko8b07c1b2020-11-26 10:36:31 +0000630func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(e *fsm.Event) {
631 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
632 oFsm.pUniTechProf.mutexTPState.Lock()
633 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
634 oFsm.pUniTechProf.mutexTPState.Unlock()
635 logger.Debugw("uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
636 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
637 "GemIwTp-entity-id": loGemPortID})
638 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
639
640 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
641 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(context.TODO(), ConstDefaultOmciTimeout, true,
642 oFsm.pAdaptFsm.commChan, loGemPortID)
643 oFsm.pLastTxMeInstance = meInstance
644}
645
646func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(e *fsm.Event) {
647 oFsm.pUniTechProf.mutexTPState.Lock()
648 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
649 oFsm.pUniTechProf.mutexTPState.Unlock()
650 logger.Debugw("uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
651 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
652 "GemNCTP-entity-id": loGemPortID})
653 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
654 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(context.TODO(), ConstDefaultOmciTimeout, true,
655 oFsm.pAdaptFsm.commChan, loGemPortID)
656 oFsm.pLastTxMeInstance = meInstance
657}
658
659func (oFsm *uniPonAniConfigFsm) enterResettingTcont(e *fsm.Event) {
660 logger.Debugw("uniPonAniConfigFsm - start resetting the TCont", log.Fields{
661 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
662
663 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
664 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
665 meParams := me.ParamData{
666 EntityID: oFsm.tcont0ID,
667 Attributes: me.AttributeValueMap{
668 "AllocId": unusedTcontAllocID,
669 },
670 }
671 meInstance := oFsm.pOmciCC.sendSetTcontVar(context.TODO(), ConstDefaultOmciTimeout, true,
672 oFsm.pAdaptFsm.commChan, meParams)
673 oFsm.pLastTxMeInstance = meInstance
674}
675
676func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(e *fsm.Event) {
677 logger.Debugw("uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
678 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
679
680 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(context.TODO(), ConstDefaultOmciTimeout, true,
681 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
682 oFsm.pLastTxMeInstance = meInstance
683}
684
685func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(e *fsm.Event) {
686 logger.Debugw("uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
687 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
688
689 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(context.TODO(), ConstDefaultOmciTimeout, true,
690 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
691 oFsm.pLastTxMeInstance = meInstance
692}
693
694func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(e *fsm.Event) {
695 logger.Debugw("uniPonAniConfigFsm ani removal done", log.Fields{
696 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
697 //use DeviceHandler event notification directly
698 oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
699 if oFsm.chanSet {
700 // indicate processing done to the caller
701 logger.Debugw("uniPonAniConfigFsm processingDone on channel", log.Fields{
702 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
703 oFsm.chSuccess <- oFsm.procStep
704 oFsm.chanSet = false //reset the internal channel state
705 }
706
707 //let's reset the state machine in order to release all resources now
708 pConfigAniStateAFsm := oFsm.pAdaptFsm
709 if pConfigAniStateAFsm != nil {
710 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
711 go func(aPAFsm *AdapterFsm) {
712 if aPAFsm != nil && aPAFsm.pFsm != nil {
713 _ = aPAFsm.pFsm.Event(aniEvReset)
714 }
715 }(pConfigAniStateAFsm)
716 }
717}
718
Himani Chawla6d2ae152020-09-02 13:11:20 +0530719func (oFsm *uniPonAniConfigFsm) enterResettingState(e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000720 logger.Debugw("uniPonAniConfigFsm resetting", log.Fields{
721 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000722
mpagenko3dbcdd22020-07-22 07:38:45 +0000723 pConfigAniStateAFsm := oFsm.pAdaptFsm
724 if pConfigAniStateAFsm != nil {
725 // abort running message processing
726 fsmAbortMsg := Message{
727 Type: TestMsg,
728 Data: TestMessage{
729 TestMessageVal: AbortMessageProcessing,
730 },
731 }
732 pConfigAniStateAFsm.commChan <- fsmAbortMsg
733
734 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530735 go func(aPAFsm *AdapterFsm) {
736 if aPAFsm != nil && aPAFsm.pFsm != nil {
737 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000738 }
739 }(pConfigAniStateAFsm)
740 }
741}
742
Himani Chawla6d2ae152020-09-02 13:11:20 +0530743func (oFsm *uniPonAniConfigFsm) enterDisabledState(e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000744 logger.Debugw("uniPonAniConfigFsm enters disabled state", log.Fields{
745 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko01e726e2020-10-23 09:45:29 +0000746 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000747
mpagenko01e726e2020-10-23 09:45:29 +0000748 //remove all TechProf related internal data to allow for new configuration (e.g. with disable/enable procedure)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800749 oFsm.pUniTechProf.clearAniSideConfig(oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000750}
751
Himani Chawla6d2ae152020-09-02 13:11:20 +0530752func (oFsm *uniPonAniConfigFsm) processOmciAniMessages( /*ctx context.Context*/ ) {
mpagenko01e726e2020-10-23 09:45:29 +0000753 logger.Debugw("Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000754loop:
755 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000756 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000757 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000758 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530759 message, ok := <-oFsm.pAdaptFsm.commChan
760 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +0000761 logger.Info("UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530762 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
763 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
764 break loop
765 }
mpagenko01e726e2020-10-23 09:45:29 +0000766 logger.Debugw("UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530767
768 switch message.Type {
769 case TestMsg:
770 msg, _ := message.Data.(TestMessage)
771 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +0000772 logger.Infow("UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000773 break loop
774 }
mpagenko01e726e2020-10-23 09:45:29 +0000775 logger.Warnw("UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530776 case OMCI:
777 msg, _ := message.Data.(OmciMessage)
778 oFsm.handleOmciAniConfigMessage(msg)
779 default:
mpagenko01e726e2020-10-23 09:45:29 +0000780 logger.Warn("UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530781 "message.Type": message.Type})
782 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000783
Himani Chawla4d908332020-08-31 12:30:20 +0530784 }
mpagenko01e726e2020-10-23 09:45:29 +0000785 logger.Infow("End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530786}
787
Himani Chawla6d2ae152020-09-02 13:11:20 +0530788func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530789 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
790 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200791 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000792 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530793 return
794 }
795 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
796 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200797 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000798 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530799 return
800 }
mpagenko01e726e2020-10-23 09:45:29 +0000801 logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000802 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
803 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
804 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
805 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
806 // maybe we can use just the same eventName for different state transitions like "forward"
807 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
808 switch oFsm.pLastTxMeInstance.GetName() {
809 case "Ieee8021PMapperServiceProfile":
810 { // let the FSM proceed ...
811 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
812 }
813 case "MacBridgePortConfigurationData":
814 { // let the FSM proceed ...
815 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
816 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300817 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
mpagenkofc4f56e2020-11-04 17:17:49 +0000818 { // let aniConfig Multi-Id processing proceed by stopping the wait function
819 oFsm.omciMIdsResponseReceived <- true
820 }
821 }
822 }
823 } else {
Himani Chawla4d908332020-08-31 12:30:20 +0530824 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
825 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
826 return
827 }
Himani Chawla4d908332020-08-31 12:30:20 +0530828}
829
Himani Chawla6d2ae152020-09-02 13:11:20 +0530830func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530831 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
832 if msgLayer == nil {
Andrea Campanella6515c582020-10-05 11:25:00 +0200833 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000834 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530835 return
836 }
837 msgObj, msgOk := msgLayer.(*omci.SetResponse)
838 if !msgOk {
Andrea Campanella6515c582020-10-05 11:25:00 +0200839 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000840 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530841 return
842 }
mpagenko01e726e2020-10-23 09:45:29 +0000843 logger.Debugw("UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530844 if msgObj.Result != me.Success {
Andrea Campanella6515c582020-10-05 11:25:00 +0200845 logger.Errorw("UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000846 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530847 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
848 return
849 }
mpagenko01e726e2020-10-23 09:45:29 +0000850 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
851 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530852 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
853 // if, then something like:
854 //oFsm.pOnuDB.StoreMe(msgObj)
855
mpagenko01e726e2020-10-23 09:45:29 +0000856 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530857 case "TCont":
858 { // let the FSM proceed ...
mpagenko8b07c1b2020-11-26 10:36:31 +0000859 if oFsm.requestEventOffset == 0 { //from TCont config request
860 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
861 } else { // from T-Cont reset request
862 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
863 }
Himani Chawla4d908332020-08-31 12:30:20 +0530864 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300865 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
Himani Chawla4d908332020-08-31 12:30:20 +0530866 { // let the PrioQueue init proceed by stopping the wait function
867 oFsm.omciMIdsResponseReceived <- true
868 }
869 case "Ieee8021PMapperServiceProfile":
870 { // let the FSM proceed ...
871 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
872 }
873 }
874 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000875}
876
mpagenko8b07c1b2020-11-26 10:36:31 +0000877func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(msg OmciMessage) {
878 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
879 if msgLayer == nil {
880 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
881 log.Fields{"device-id": oFsm.deviceID})
882 return
883 }
884 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
885 if !msgOk {
886 logger.Errorw("UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
887 log.Fields{"device-id": oFsm.deviceID})
888 return
889 }
890 logger.Debugw("UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
891 if msgObj.Result != me.Success {
892 logger.Errorw("UniPonAniConfigFsm - Omci DeleteResponse Error",
893 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
894 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
895 // store error for mgmt display?
896 return
897 }
898 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
899 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
900 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
901 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
902
903 switch oFsm.pLastTxMeInstance.GetName() {
904 case "GemInterworkingTerminationPoint":
905 { // let the FSM proceed ...
906 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
907 }
908 case "GemPortNetworkCtp":
909 { // let the FSM proceed ...
910 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
911 }
912 case "Ieee8021PMapperServiceProfile":
913 { // let the FSM proceed ...
914 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
915 }
916 case "MacBridgePortConfigurationData":
917 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
918 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
919 }
920 }
921 }
922}
923
Himani Chawla6d2ae152020-09-02 13:11:20 +0530924func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +0000925 logger.Debugw("Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000926 "msgType": msg.OmciMsg.MessageType})
927
928 switch msg.OmciMsg.MessageType {
929 case omci.CreateResponseType:
930 {
Himani Chawla4d908332020-08-31 12:30:20 +0530931 oFsm.handleOmciAniConfigCreateResponseMessage(msg)
932
mpagenko3dbcdd22020-07-22 07:38:45 +0000933 } //CreateResponseType
934 case omci.SetResponseType:
935 {
Himani Chawla4d908332020-08-31 12:30:20 +0530936 oFsm.handleOmciAniConfigSetResponseMessage(msg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000937
mpagenko3dbcdd22020-07-22 07:38:45 +0000938 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +0000939 case omci.DeleteResponseType:
940 {
941 oFsm.handleOmciAniConfigDeleteResponseMessage(msg)
942
943 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +0000944 default:
945 {
Andrea Campanella6515c582020-10-05 11:25:00 +0200946 logger.Errorw("uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +0000947 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000948 return
949 }
950 }
951}
952
Himani Chawla6d2ae152020-09-02 13:11:20 +0530953func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000954 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
955 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530956 logger.Debugw("uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000957 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
958 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000959 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000960 meParams := me.ParamData{
961 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
962 Attributes: me.AttributeValueMap{
963 "PortId": gemPortAttribs.gemPortID,
964 "TContPointer": oFsm.tcont0ID,
965 "Direction": gemPortAttribs.direction,
966 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
967 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
968 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
969 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
970 },
971 }
972 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
973 oFsm.pAdaptFsm.commChan, meParams)
974 //accept also nil as (error) return value for writing to LastTx
975 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000976 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000977
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000978 //verify response
979 err := oFsm.waitforOmciResponse()
980 if err != nil {
981 logger.Errorw("GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000982 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +0530983 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000984 return
985 }
986 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +0000987
988 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +0000989 logger.Debugw("GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530990 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +0000991}
992
Himani Chawla6d2ae152020-09-02 13:11:20 +0530993func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000994 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
995 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530996 logger.Debugw("uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000997 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
998 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000999 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001000
ozgecanetsia4b232302020-11-11 10:58:10 +03001001 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1002 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001003
1004 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001005 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001006 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001007 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001008 "InterworkingOption": 0, // Don't Care
1009 "ServiceProfilePointer": 0, // Don't Care
1010 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001011 },
1012 }
1013 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout,
1014 true, oFsm.pAdaptFsm.commChan, meParams)
1015 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001016 //verify response
1017 err := oFsm.waitforOmciResponse()
1018 if err != nil {
1019 logger.Errorw("GemTP IW multicast create failed, aborting AniConfig FSM!",
1020 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1021 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1022 return
1023 }
1024 ipv4MulticastTable := make([]uint8, 12)
1025 //Gem Port ID
1026 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1027 //Secondary Key
1028 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1029 // Multicast IP range start This is the 224.0.0.1 address
1030 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1031 // MulticastIp range stop
1032 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1033
1034 meIPV4MCTableParams := me.ParamData{
1035 EntityID: gemPortAttribs.multicastGemID,
1036 Attributes: me.AttributeValueMap{
1037 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1038 },
1039 }
1040 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout,
1041 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1042 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
ozgecanetsia4b232302020-11-11 10:58:10 +03001043
1044 } else {
1045 meParams := me.ParamData{
1046 EntityID: gemPortAttribs.gemPortID,
1047 Attributes: me.AttributeValueMap{
1048 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1049 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1050 "ServiceProfilePointer": oFsm.mapperSP0ID,
1051 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1052 "GalProfilePointer": galEthernetEID,
1053 },
1054 }
1055 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), ConstDefaultOmciTimeout, true,
1056 oFsm.pAdaptFsm.commChan, meParams)
1057 //accept also nil as (error) return value for writing to LastTx
1058 // - this avoids misinterpretation of new received OMCI messages
1059 oFsm.pLastTxMeInstance = meInstance
1060 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001061 //verify response
1062 err := oFsm.waitforOmciResponse()
1063 if err != nil {
ozgecanetsia4b232302020-11-11 10:58:10 +03001064 logger.Errorw("GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001065 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301066 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001067 return
1068 }
1069 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001070
1071 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001072 logger.Debugw("GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301073 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001074}
1075
Himani Chawla6d2ae152020-09-02 13:11:20 +05301076func (oFsm *uniPonAniConfigFsm) performSettingPQs() {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001077 const cu16StrictPrioWeight uint16 = 0xFFFF
1078 //find all upstream PrioQueues related to this T-Cont
1079 loQueueMap := ordered_map.NewOrderedMap()
1080 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001081 if gemPortAttribs.isMulticast {
1082 logger.Debugw("uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
1083 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1084 "prioString": gemPortAttribs.pbitString})
1085 continue
1086 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001087 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301088 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001089 //key does not yet exist
1090 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1091 }
1092 } else {
1093 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1094 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001095 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001096
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001097 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1098 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1099 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1100 // or even be finished without correct SP/WRR setting
1101
1102 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1103 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1104 // even though its T-Cont seems to be wrong ...
1105 loTrafficSchedulerEID := 0x8000
1106 //for all found queues
1107 iter := loQueueMap.IterFunc()
1108 for kv, ok := iter(); ok; kv, ok = iter() {
1109 queueIndex := (kv.Key).(uint16)
1110 meParams := me.ParamData{
1111 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301112 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001113 }
1114 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1115 //StrictPrio indication
Himani Chawla6d2ae152020-09-02 13:11:20 +05301116 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001117 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001118 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001119 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1120 } else {
1121 //WRR indication
Himani Chawla6d2ae152020-09-02 13:11:20 +05301122 logger.Debugw("uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001123 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1124 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001125 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001126 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1127 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1128 }
1129 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(context.TODO(), ConstDefaultOmciTimeout, true,
1130 oFsm.pAdaptFsm.commChan, meParams)
1131 //accept also nil as (error) return value for writing to LastTx
1132 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001133 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001134
1135 //verify response
1136 err := oFsm.waitforOmciResponse()
1137 if err != nil {
1138 logger.Errorw("PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001139 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301140 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001141 return
1142 }
1143
1144 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1145 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1146 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1147 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1148
1149 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001150
1151 // if Config has been done for all PrioQueue instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001152 logger.Debugw("PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301153 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001154}
1155
Himani Chawla6d2ae152020-09-02 13:11:20 +05301156func (oFsm *uniPonAniConfigFsm) waitforOmciResponse() error {
mpagenko3dbcdd22020-07-22 07:38:45 +00001157 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301158 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001159 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001160 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001161 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 +00001162 logger.Warnw("UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
1163 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001164 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301165 if success {
Himani Chawla6d2ae152020-09-02 13:11:20 +05301166 logger.Debug("uniPonAniConfigFsm multi entity response received")
mpagenko3dbcdd22020-07-22 07:38:45 +00001167 return nil
1168 }
1169 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +00001170 logger.Warnw("uniPonAniConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
1171 return fmt.Errorf("uniPonAniConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001172 }
1173}