blob: 19167f6af0ac2d1b3c9d98b1bffeb119c0775f9d [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"
mpagenko7d6bb022021-03-11 15:07:55 +000026 "sync"
mpagenko3dbcdd22020-07-22 07:38:45 +000027 "time"
28
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000029 "github.com/cevaris/ordered_map"
mpagenko3dbcdd22020-07-22 07:38:45 +000030 "github.com/looplab/fsm"
mpagenko3dbcdd22020-07-22 07:38:45 +000031 "github.com/opencord/omci-lib-go"
32 me "github.com/opencord/omci-lib-go/generated"
dbainbri4d3a0dc2020-12-02 00:33:42 +000033 "github.com/opencord/voltha-lib-go/v4/pkg/log"
34 //ic "github.com/opencord/voltha-protos/v4/go/inter_container"
35 //"github.com/opencord/voltha-protos/v4/go/openflow_13"
36 //"github.com/opencord/voltha-protos/v4/go/voltha"
mpagenko3dbcdd22020-07-22 07:38:45 +000037)
38
mpagenko1cc3cb42020-07-27 15:24:38 +000039const (
40 // events of config PON ANI port FSM
mpagenko8b07c1b2020-11-26 10:36:31 +000041 aniEvStart = "aniEvStart"
42 aniEvStartConfig = "aniEvStartConfig"
43 aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
44 aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
45 aniEvRxTcontsResp = "aniEvRxTcontsResp"
46 aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
47 aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
48 aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
49 aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
50 aniEvRemGemiw = "aniEvRemGemiw"
Girish Gowdra26a40922021-01-29 17:14:34 -080051 aniEvWaitFlowRem = "aniEvWaitFlowRem"
52 aniEvFlowRemDone = "aniEvFlowRemDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000053 aniEvRxRemGemiwResp = "aniEvRxRemGemiwResp"
54 aniEvRxRemGemntpResp = "aniEvRxRemGemntpResp"
55 aniEvRemTcontPath = "aniEvRemTcontPath"
56 aniEvRxResetTcontResp = "aniEvRxResetTcontResp"
57 aniEvRxRem1pMapperResp = "aniEvRxRem1pMapperResp"
58 aniEvRxRemAniBPCDResp = "aniEvRxRemAniBPCDResp"
59 aniEvTimeoutSimple = "aniEvTimeoutSimple"
60 aniEvTimeoutMids = "aniEvTimeoutMids"
61 aniEvReset = "aniEvReset"
62 aniEvRestart = "aniEvRestart"
mpagenko1cc3cb42020-07-27 15:24:38 +000063)
64const (
65 // states of config PON ANI port FSM
66 aniStDisabled = "aniStDisabled"
67 aniStStarting = "aniStStarting"
68 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
69 aniStCreatingMBPCD = "aniStCreatingMBPCD"
70 aniStSettingTconts = "aniStSettingTconts"
71 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
72 aniStCreatingGemIWs = "aniStCreatingGemIWs"
73 aniStSettingPQs = "aniStSettingPQs"
74 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
75 aniStConfigDone = "aniStConfigDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000076 aniStRemovingGemIW = "aniStRemovingGemIW"
Girish Gowdra26a40922021-01-29 17:14:34 -080077 aniStWaitingFlowRem = "aniStWaitingFlowRem"
mpagenko8b07c1b2020-11-26 10:36:31 +000078 aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
79 aniStResetTcont = "aniStResetTcont"
80 aniStRemDot1PMapper = "aniStRemDot1PMapper"
81 aniStRemAniBPCD = "aniStRemAniBPCD"
82 aniStRemoveDone = "aniStRemoveDone"
mpagenko1cc3cb42020-07-27 15:24:38 +000083 aniStResetting = "aniStResetting"
84)
Holger Hildebrandt10d98192021-01-27 15:29:31 +000085const cAniFsmIdleState = aniStConfigDone
mpagenko1cc3cb42020-07-27 15:24:38 +000086
Girish Gowdra041dcb32020-11-16 16:54:30 -080087const (
88 tpIDOffset = 64
89)
90
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000091type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030092 gemPortID uint16
93 upQueueID uint16
94 downQueueID uint16
95 direction uint8
96 qosPolicy string
97 weight uint8
98 pbitString string
99 isMulticast bool
100 multicastGemID uint16
101 staticACL string
102 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000103}
104
Himani Chawla6d2ae152020-09-02 13:11:20 +0530105//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
106type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000107 pDeviceHandler *deviceHandler
108 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530109 pOmciCC *omciCC
110 pOnuUniPort *onuUniPort
111 pUniTechProf *onuUniTechProf
112 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800113 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000114 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000115 requestEvent OnuDeviceEvent
mpagenko7d6bb022021-03-11 15:07:55 +0000116 mutexIsAwaitingResponse sync.RWMutex
117 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530118 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000119 pAdaptFsm *AdapterFsm
120 chSuccess chan<- uint8
121 procStep uint8
122 chanSet bool
123 mapperSP0ID uint16
124 macBPCD0ID uint16
125 tcont0ID uint16
126 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000127 gemPortAttribsSlice []ponAniGemPortAttribs
mpagenko01e726e2020-10-23 09:45:29 +0000128 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000129 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenko3dbcdd22020-07-22 07:38:45 +0000130}
131
Himani Chawla6d2ae152020-09-02 13:11:20 +0530132//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
dbainbri4d3a0dc2020-12-02 00:33:42 +0000133func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800134 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000135 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530136 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000137 pDeviceHandler: apDeviceHandler,
138 deviceID: apDeviceHandler.deviceID,
139 pOmciCC: apDevOmciCC,
140 pOnuUniPort: apUniPort,
141 pUniTechProf: apUniTechProf,
142 pOnuDB: apOnuDB,
143 techProfileID: aTechProfileID,
144 requestEvent: aRequestEvent,
145 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000146 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000147 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
148
mpagenko01e726e2020-10-23 09:45:29 +0000149 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000150 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000151 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000152 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000153 return nil
154 }
155
156 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000157 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000158 fsm.Events{
159
mpagenko1cc3cb42020-07-27 15:24:38 +0000160 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000161
162 //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 +0000163 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000164 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000165 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
166 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000167 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000168 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000169 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000170 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000171 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000172 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000173 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000174
mpagenko8b07c1b2020-11-26 10:36:31 +0000175 //for removing Gem related resources
176 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800177 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
178 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000179 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
180 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
181
182 //for removing TCONT related resources
183 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
184 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
185 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
186 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
187
188 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
189 aniStRemovingGemIW, aniStRemovingGemNCTP,
190 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000191 {Name: aniEvTimeoutMids, Src: []string{
192 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000193
mpagenko1cc3cb42020-07-27 15:24:38 +0000194 // exceptional treatment for all states except aniStResetting
195 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
196 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenko8b07c1b2020-11-26 10:36:31 +0000197 aniStConfigDone, aniStRemovingGemIW, aniStRemovingGemNCTP,
198 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000199 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000200 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000201 },
202
203 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000204 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
205 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
206 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
207 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
208 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
209 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
210 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
211 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
212 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
213 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
214 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
215 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
216 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
217 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
218 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
219 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
220 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
221 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000222 },
223 )
224 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000225 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000226 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000227 return nil
228 }
229
dbainbri4d3a0dc2020-12-02 00:33:42 +0000230 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000231 return instFsm
232}
233
Himani Chawla6d2ae152020-09-02 13:11:20 +0530234//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
235func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000236 oFsm.chSuccess = aChSuccess
237 oFsm.procStep = aProcStep
238 oFsm.chanSet = true
239}
240
mpagenko7d6bb022021-03-11 15:07:55 +0000241//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000242func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
243 //early indication about started reset processing
244 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000245 //mutex protection is required for possible concurrent access to FSM members
246 oFsm.mutexIsAwaitingResponse.RLock()
247 defer oFsm.mutexIsAwaitingResponse.RUnlock()
248 if oFsm.isAwaitingResponse {
249 //use channel to indicate that the response waiting shall be aborted
250 oFsm.omciMIdsResponseReceived <- false
251 }
252 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
253 pAdaptFsm := oFsm.pAdaptFsm
254 if pAdaptFsm != nil {
255 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
256 go func(aPAFsm *AdapterFsm) {
257 if aPAFsm.pFsm != nil {
258 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
259 }
260 }(pAdaptFsm)
261 }
mpagenko73143992021-04-09 15:17:10 +0000262
263 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
264 // access conflicts on internal data by next needed data clearance
265 //activity should be aborted in short time if running with FSM due to above FSM reset
266 // or finished without FSM dependency in short time
267 oFsm.pUniTechProf.lockTpProcMutex()
268 defer oFsm.pUniTechProf.unlockTpProcMutex()
269 //remove all TechProf related internal data to allow for new configuration
270 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000271}
272
dbainbri4d3a0dc2020-12-02 00:33:42 +0000273func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530274 if aPAFsm != nil && aPAFsm.pFsm != nil {
275 //stick to pythonAdapter numbering scheme
276 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800277 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
278 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530279
Girish Gowdra041dcb32020-11-16 16:54:30 -0800280 /*
281 // Find a free TCONT Instance ID and use it
282 foundFreeTcontInstID := false
283 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000284 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800285
286 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
287 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
288 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
289 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
290 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
291 // when the ONU is discovered.
292 /*
293 for _, tcontInstID := range tcontInstKeys {
294 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
295 returnVal := tconInst["AllocId"]
296 if returnVal != nil {
297 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
298 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
299 if allocID == 0xff || allocID == 0xffff {
300 foundFreeTcontInstID = true
301 oFsm.tcont0ID = uint16(tcontInstID)
302 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
303 "device-id": oFsm.deviceID})
304 break
305 }
306 } else {
307 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
308 }
309 } else {
310 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
311 }
312 }
313 */
314
315 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
316 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
317 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
318 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
319 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
320 // TP ID will increment in single digit
321 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000322 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800323 "device-id": oFsm.deviceID})
324 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000325 logger.Errorw(ctx, "tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800326 if oFsm.chanSet {
327 // indicate processing error/abort to the caller
328 oFsm.chSuccess <- 0
329 oFsm.chanSet = false //reset the internal channel state
330 }
331 //reset the state machine to enable usage on subsequent requests
332 _ = aPAFsm.pFsm.Event(aniEvReset)
333 return
334 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530335 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000336 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800337 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530338 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800339 /*
340 if !foundFreeTcontInstID {
341 // This should never happen. If it does, the behavior is unpredictable.
342 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
343 }*/
344
345 // Access critical state with lock
346 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000347 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
348 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800349 oFsm.pUniTechProf.mutexTPState.Unlock()
350
Himani Chawla26e555c2020-08-31 12:30:20 +0530351 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800352 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300353 loGemPortAttribs := ponAniGemPortAttribs{}
354
Himani Chawla26e555c2020-08-31 12:30:20 +0530355 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
356
dbainbri4d3a0dc2020-12-02 00:33:42 +0000357 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530358
359 loGemPortAttribs.gemPortID = gemEntry.gemPortID
360 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
361 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
362 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
363 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
364
365 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
366 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
367 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
368 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
369 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
370 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
371
372 usQueueFound := false
373 dsQueueFound := false
374 for _, mgmtEntityID := range queueInstKeys {
375 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
376 returnVal := meAttributes["RelatedPort"]
377 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530378 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530379 if relatedPort == usQrelPortMask {
380 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000381 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000382 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530383 usQueueFound = true
384 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
385 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000386 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000387 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530388 dsQueueFound = true
389 }
390 if usQueueFound && dsQueueFound {
391 break
392 }
393 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000394 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530395 }
396 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000397 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530398 }
399 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000400 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000401 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530402 }
403 }
404 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000405 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530406 }
407 loGemPortAttribs.direction = gemEntry.direction
408 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
409 loGemPortAttribs.weight = gemEntry.queueWeight
410 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300411 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300412 //TODO this might effectively ignore the for loop starting at line 316
413 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300414 loGemPortAttribs.isMulticast = true
415 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
416 loGemPortAttribs.staticACL = gemEntry.staticACL
417 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530418
dbainbri4d3a0dc2020-12-02 00:33:42 +0000419 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300420 "gemPortID": loGemPortAttribs.gemPortID,
421 "isMulticast": loGemPortAttribs.isMulticast,
422 "multicastGemID": loGemPortAttribs.multicastGemID,
423 "staticACL": loGemPortAttribs.staticACL,
424 "dynamicACL": loGemPortAttribs.dynamicACL,
425 })
426
427 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000428 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300429 "gemPortID": loGemPortAttribs.gemPortID,
430 "upQueueID": loGemPortAttribs.upQueueID,
431 "downQueueID": loGemPortAttribs.downQueueID,
432 "pbitString": loGemPortAttribs.pbitString,
433 "prioQueueIndex": gemEntry.prioQueueIndex,
434 })
435 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530436
437 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
438 }
439 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
440 }
441}
442
dbainbri4d3a0dc2020-12-02 00:33:42 +0000443func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
444 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000445 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000446 // in case the used channel is not yet defined (can be re-used after restarts)
447 if oFsm.omciMIdsResponseReceived == nil {
448 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000449 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000450 } else {
451 // as we may 're-use' this instance of FSM and the connected channel
452 // make sure there is no 'lingering' request in the already existing channel:
453 // (simple loop sufficient as we are the only receiver)
454 for len(oFsm.omciMIdsResponseReceived) > 0 {
455 <-oFsm.omciMIdsResponseReceived
456 }
457 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000458 //ensure internal slices are empty (which might be set from previous run) - release memory
459 oFsm.gemPortAttribsSlice = nil
460
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000461 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000462 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000463
464 //let the state machine run forward from here directly
465 pConfigAniStateAFsm := oFsm.pAdaptFsm
466 if pConfigAniStateAFsm != nil {
467 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000468 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000469
mpagenko3dbcdd22020-07-22 07:38:45 +0000470 }
471}
472
dbainbri4d3a0dc2020-12-02 00:33:42 +0000473func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
474 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000475 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000476 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
477 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Girish Gowdra0b235842021-03-09 13:06:46 -0800478 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000479 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
480 //accept also nil as (error) return value for writing to LastTx
481 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000482 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000483}
484
dbainbri4d3a0dc2020-12-02 00:33:42 +0000485func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
486 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000487 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
488 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000489 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000490 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
491 meParams := me.ParamData{
492 EntityID: oFsm.macBPCD0ID,
493 Attributes: me.AttributeValueMap{
494 "BridgeIdPointer": bridgePtr,
495 "PortNum": 0xFF, //fixed unique ANI side indication
496 "TpType": 3, //for .1PMapper
497 "TpPointer": oFsm.mapperSP0ID,
498 },
499 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800500 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000501 oFsm.pAdaptFsm.commChan, meParams)
502 //accept also nil as (error) return value for writing to LastTx
503 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000504 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000505}
506
dbainbri4d3a0dc2020-12-02 00:33:42 +0000507func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
508 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000509 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
510 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000511 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000512 meParams := me.ParamData{
513 EntityID: oFsm.tcont0ID,
514 Attributes: me.AttributeValueMap{
515 "AllocId": oFsm.alloc0ID,
516 },
517 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800518 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000519 oFsm.pAdaptFsm.commChan, meParams)
520 //accept also nil as (error) return value for writing to LastTx
521 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000522 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000523}
524
dbainbri4d3a0dc2020-12-02 00:33:42 +0000525func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
526 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000527 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000528 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000529}
530
dbainbri4d3a0dc2020-12-02 00:33:42 +0000531func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
532 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000533 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000534 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000535}
536
dbainbri4d3a0dc2020-12-02 00:33:42 +0000537func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
538 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000539 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000540 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000541}
542
dbainbri4d3a0dc2020-12-02 00:33:42 +0000543func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300544
dbainbri4d3a0dc2020-12-02 00:33:42 +0000545 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000546 "toGemIw": 1024, /* cmp above */
547 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000548
dbainbri4d3a0dc2020-12-02 00:33:42 +0000549 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000550 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000551 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000552
mpagenko3dbcdd22020-07-22 07:38:45 +0000553 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000554 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530555 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000556 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000557
558 //assign the GemPorts according to the configured Prio
559 var loPrioGemPortArray [8]uint16
560 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300561 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000562 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300563 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
564 "prioString": gemPortAttribs.pbitString})
565 continue
566 }
567 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000568 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300569 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
570 "prioString": gemPortAttribs.pbitString})
571 continue
572 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000573 for i := 0; i < 8; i++ {
574 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
575 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
576 if prio == 1 { // Check this p-bit is set
577 if loPrioGemPortArray[i] == 0 {
578 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
579 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000580 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000581 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000582 "SetGemPort": loPrioGemPortArray[i]})
583 }
584 }
585 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000586 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000587 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000588 "prioString": gemPortAttribs.pbitString, "position": i})
589 }
590
591 }
592 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300593
ozgecanetsia4b232302020-11-11 10:58:10 +0300594 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530595 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300596 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530597 if value != 0 {
598 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530599 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000600 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000601 "for Prio": index,
602 "IwPtr": strconv.FormatInt(int64(value), 16),
603 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300604 } else {
605 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000606 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
607 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300608 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530609 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000610 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300611 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000612 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
613 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300614 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530615
616 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000617 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000618 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300619 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
620 // 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 +0000621 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300622 //pConfigAniStateAFsm := oFsm.pAdaptFsm
623 //if pConfigAniStateAFsm != nil {
624 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
625 // go func(aPAFsm *AdapterFsm) {
626 // if aPAFsm != nil && aPAFsm.pFsm != nil {
627 // _ = aPAFsm.pFsm.Event(aniEvReset)
628 // }
629 // }(pConfigAniStateAFsm)
630 //}
631 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000632 pConfigAniStateAFsm := oFsm.pAdaptFsm
633 if pConfigAniStateAFsm != nil {
634 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530635 go func(aPAFsm *AdapterFsm) {
636 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300637 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000638 }
639 }(pConfigAniStateAFsm)
640 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300641 } else {
Girish Gowdra0b235842021-03-09 13:06:46 -0800642 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300643 oFsm.pAdaptFsm.commChan, meParams)
644 //accept also nil as (error) return value for writing to LastTx
645 // - this avoids misinterpretation of new received OMCI messages
646 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000647 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000648}
649
dbainbri4d3a0dc2020-12-02 00:33:42 +0000650func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
651 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000652 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000653 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000654 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000655 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800656 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000657 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000658 // but only in case the techProfile was configured (not deleted)
659 if oFsm.requestEventOffset == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000660 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000661 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000662
mpagenko01e726e2020-10-23 09:45:29 +0000663 if oFsm.chanSet {
664 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000665 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000666 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
667 oFsm.chSuccess <- oFsm.procStep
668 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000669 }
mpagenko01e726e2020-10-23 09:45:29 +0000670
671 //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 +0000672}
673
dbainbri4d3a0dc2020-12-02 00:33:42 +0000674func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
Girish Gowdra26a40922021-01-29 17:14:34 -0800675
mpagenkoa23a6292021-02-23 10:40:10 +0000676 oFsm.pUniTechProf.mutexTPState.Lock()
Girish Gowdra9085bca2021-03-08 12:57:48 -0800677 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending() {
mpagenkoa23a6292021-02-23 10:40:10 +0000678 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800679 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
680 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
681 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
682 pConfigAniStateAFsm := oFsm.pAdaptFsm
683 if pConfigAniStateAFsm != nil {
684 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
685 go func(aPAFsm *AdapterFsm) {
686 if aPAFsm != nil && aPAFsm.pFsm != nil {
687 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
688 }
689 }(pConfigAniStateAFsm)
690 } else {
691 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
692 }
693 return
694 }
695
mpagenko8b07c1b2020-11-26 10:36:31 +0000696 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000697 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
698 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000699 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000700 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
701 "GemIwTp-entity-id": loGemPortID})
702 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
703
704 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800705 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000706 oFsm.pAdaptFsm.commChan, loGemPortID)
707 oFsm.pLastTxMeInstance = meInstance
708}
709
dbainbri4d3a0dc2020-12-02 00:33:42 +0000710func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000711 oFsm.pUniTechProf.mutexTPState.Lock()
712 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
713 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000714 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000715 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
716 "GemNCTP-entity-id": loGemPortID})
717 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800718 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000719 oFsm.pAdaptFsm.commChan, loGemPortID)
720 oFsm.pLastTxMeInstance = meInstance
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800721 // Mark the gem port to be removed for Performance History monitoring
722 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
723 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
724 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000725}
726
dbainbri4d3a0dc2020-12-02 00:33:42 +0000727func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
728 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000729 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
730
731 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
732 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
733 meParams := me.ParamData{
734 EntityID: oFsm.tcont0ID,
735 Attributes: me.AttributeValueMap{
736 "AllocId": unusedTcontAllocID,
737 },
738 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800739 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000740 oFsm.pAdaptFsm.commChan, meParams)
741 oFsm.pLastTxMeInstance = meInstance
742}
743
dbainbri4d3a0dc2020-12-02 00:33:42 +0000744func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
745 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000746 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
747
Girish Gowdra0b235842021-03-09 13:06:46 -0800748 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000749 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
750 oFsm.pLastTxMeInstance = meInstance
751}
752
dbainbri4d3a0dc2020-12-02 00:33:42 +0000753func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
754 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000755 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
756
Girish Gowdra0b235842021-03-09 13:06:46 -0800757 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000758 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
759 oFsm.pLastTxMeInstance = meInstance
760}
761
dbainbri4d3a0dc2020-12-02 00:33:42 +0000762func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
763 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000764 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
765 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000766 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000767 if oFsm.chanSet {
768 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000769 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000770 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
771 oFsm.chSuccess <- oFsm.procStep
772 oFsm.chanSet = false //reset the internal channel state
773 }
774
775 //let's reset the state machine in order to release all resources now
776 pConfigAniStateAFsm := oFsm.pAdaptFsm
777 if pConfigAniStateAFsm != nil {
778 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
779 go func(aPAFsm *AdapterFsm) {
780 if aPAFsm != nil && aPAFsm.pFsm != nil {
781 _ = aPAFsm.pFsm.Event(aniEvReset)
782 }
783 }(pConfigAniStateAFsm)
784 }
785}
786
dbainbri4d3a0dc2020-12-02 00:33:42 +0000787func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
788 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000789 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000790
mpagenko3dbcdd22020-07-22 07:38:45 +0000791 pConfigAniStateAFsm := oFsm.pAdaptFsm
792 if pConfigAniStateAFsm != nil {
793 // abort running message processing
794 fsmAbortMsg := Message{
795 Type: TestMsg,
796 Data: TestMessage{
797 TestMessageVal: AbortMessageProcessing,
798 },
799 }
800 pConfigAniStateAFsm.commChan <- fsmAbortMsg
801
802 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530803 go func(aPAFsm *AdapterFsm) {
804 if aPAFsm != nil && aPAFsm.pFsm != nil {
805 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000806 }
807 }(pConfigAniStateAFsm)
808 }
809}
810
dbainbri4d3a0dc2020-12-02 00:33:42 +0000811func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
812 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000813 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko01e726e2020-10-23 09:45:29 +0000814 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000815}
816
dbainbri4d3a0dc2020-12-02 00:33:42 +0000817func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
818 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000819loop:
820 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000821 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000822 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000823 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530824 message, ok := <-oFsm.pAdaptFsm.commChan
825 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000826 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530827 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
828 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
829 break loop
830 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000831 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530832
833 switch message.Type {
834 case TestMsg:
835 msg, _ := message.Data.(TestMessage)
836 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000837 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000838 break loop
839 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000840 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530841 case OMCI:
842 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000843 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530844 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000845 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530846 "message.Type": message.Type})
847 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000848
Himani Chawla4d908332020-08-31 12:30:20 +0530849 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000850 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530851}
852
dbainbri4d3a0dc2020-12-02 00:33:42 +0000853func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530854 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
855 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000856 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000857 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530858 return
859 }
860 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
861 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000862 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000863 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530864 return
865 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000866 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000867 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
868 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
869 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
870 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
871 // maybe we can use just the same eventName for different state transitions like "forward"
872 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
873 switch oFsm.pLastTxMeInstance.GetName() {
874 case "Ieee8021PMapperServiceProfile":
875 { // let the FSM proceed ...
876 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
877 }
878 case "MacBridgePortConfigurationData":
879 { // let the FSM proceed ...
880 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
881 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300882 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
mpagenkofc4f56e2020-11-04 17:17:49 +0000883 { // let aniConfig Multi-Id processing proceed by stopping the wait function
884 oFsm.omciMIdsResponseReceived <- true
885 }
886 }
887 }
888 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000889 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530890 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
891 return
892 }
Himani Chawla4d908332020-08-31 12:30:20 +0530893}
894
dbainbri4d3a0dc2020-12-02 00:33:42 +0000895func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530896 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
897 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000898 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000899 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530900 return
901 }
902 msgObj, msgOk := msgLayer.(*omci.SetResponse)
903 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000904 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000905 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530906 return
907 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000908 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530909 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000910 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000911 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530912 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
913 return
914 }
mpagenko01e726e2020-10-23 09:45:29 +0000915 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
916 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530917 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
918 // if, then something like:
919 //oFsm.pOnuDB.StoreMe(msgObj)
920
mpagenko01e726e2020-10-23 09:45:29 +0000921 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530922 case "TCont":
923 { // let the FSM proceed ...
mpagenko8b07c1b2020-11-26 10:36:31 +0000924 if oFsm.requestEventOffset == 0 { //from TCont config request
925 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
926 } else { // from T-Cont reset request
927 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
928 }
Himani Chawla4d908332020-08-31 12:30:20 +0530929 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300930 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
Himani Chawla4d908332020-08-31 12:30:20 +0530931 { // let the PrioQueue init proceed by stopping the wait function
932 oFsm.omciMIdsResponseReceived <- true
933 }
934 case "Ieee8021PMapperServiceProfile":
935 { // let the FSM proceed ...
936 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
937 }
938 }
939 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000940}
941
dbainbri4d3a0dc2020-12-02 00:33:42 +0000942func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000943 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
944 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000945 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +0000946 log.Fields{"device-id": oFsm.deviceID})
947 return
948 }
949 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
950 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000951 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +0000952 log.Fields{"device-id": oFsm.deviceID})
953 return
954 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000955 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +0000956 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000957 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +0000958 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
959 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
960 // store error for mgmt display?
961 return
962 }
963 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
964 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
965 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
966 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
967
968 switch oFsm.pLastTxMeInstance.GetName() {
969 case "GemInterworkingTerminationPoint":
970 { // let the FSM proceed ...
971 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
972 }
973 case "GemPortNetworkCtp":
974 { // let the FSM proceed ...
975 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
976 }
977 case "Ieee8021PMapperServiceProfile":
978 { // let the FSM proceed ...
979 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
980 }
981 case "MacBridgePortConfigurationData":
982 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
983 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
984 }
985 }
986 }
987}
988
dbainbri4d3a0dc2020-12-02 00:33:42 +0000989func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
990 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000991 "msgType": msg.OmciMsg.MessageType})
992
993 switch msg.OmciMsg.MessageType {
994 case omci.CreateResponseType:
995 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000996 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530997
mpagenko3dbcdd22020-07-22 07:38:45 +0000998 } //CreateResponseType
999 case omci.SetResponseType:
1000 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001001 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001002
mpagenko3dbcdd22020-07-22 07:38:45 +00001003 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001004 case omci.DeleteResponseType:
1005 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001006 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001007
1008 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001009 default:
1010 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001011 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001012 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001013 return
1014 }
1015 }
1016}
1017
dbainbri4d3a0dc2020-12-02 00:33:42 +00001018func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001019 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1020 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001021 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001022 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1023 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001024 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001025 meParams := me.ParamData{
1026 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1027 Attributes: me.AttributeValueMap{
1028 "PortId": gemPortAttribs.gemPortID,
1029 "TContPointer": oFsm.tcont0ID,
1030 "Direction": gemPortAttribs.direction,
1031 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1032 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1033 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1034 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1035 },
1036 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001037 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001038 oFsm.pAdaptFsm.commChan, meParams)
1039 //accept also nil as (error) return value for writing to LastTx
1040 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001041 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +00001042
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001043 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001044 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001045 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001046 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001047 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301048 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001049 return
1050 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001051 // Mark the gem port to be removed for Performance History monitoring
1052 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
1053 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(gemPortAttribs.gemPortID)
1054 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001055 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001056
1057 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001058 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301059 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001060}
1061
dbainbri4d3a0dc2020-12-02 00:33:42 +00001062func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001063 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1064 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001065 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001066 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1067 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001068 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001069
ozgecanetsia4b232302020-11-11 10:58:10 +03001070 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1071 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001072
1073 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001074 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001075 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001076 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001077 "InterworkingOption": 0, // Don't Care
1078 "ServiceProfilePointer": 0, // Don't Care
1079 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001080 },
1081 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001082 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001083 true, oFsm.pAdaptFsm.commChan, meParams)
1084 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001085 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001086 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001087 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001088 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001089 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1090 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1091 return
1092 }
1093 ipv4MulticastTable := make([]uint8, 12)
1094 //Gem Port ID
1095 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1096 //Secondary Key
1097 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1098 // Multicast IP range start This is the 224.0.0.1 address
1099 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1100 // MulticastIp range stop
1101 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1102
1103 meIPV4MCTableParams := me.ParamData{
1104 EntityID: gemPortAttribs.multicastGemID,
1105 Attributes: me.AttributeValueMap{
1106 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1107 },
1108 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001109 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001110 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1111 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
ozgecanetsia4b232302020-11-11 10:58:10 +03001112
1113 } else {
1114 meParams := me.ParamData{
1115 EntityID: gemPortAttribs.gemPortID,
1116 Attributes: me.AttributeValueMap{
1117 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1118 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1119 "ServiceProfilePointer": oFsm.mapperSP0ID,
1120 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1121 "GalProfilePointer": galEthernetEID,
1122 },
1123 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001124 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001125 oFsm.pAdaptFsm.commChan, meParams)
1126 //accept also nil as (error) return value for writing to LastTx
1127 // - this avoids misinterpretation of new received OMCI messages
1128 oFsm.pLastTxMeInstance = meInstance
1129 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001130 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001131 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001132 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001133 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001134 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301135 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001136 return
1137 }
1138 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001139
1140 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001141 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301142 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001143}
1144
dbainbri4d3a0dc2020-12-02 00:33:42 +00001145func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001146 const cu16StrictPrioWeight uint16 = 0xFFFF
1147 //find all upstream PrioQueues related to this T-Cont
1148 loQueueMap := ordered_map.NewOrderedMap()
1149 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001150 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001151 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001152 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1153 "prioString": gemPortAttribs.pbitString})
1154 continue
1155 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001156 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301157 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001158 //key does not yet exist
1159 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1160 }
1161 } else {
1162 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1163 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001164 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001165
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001166 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1167 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1168 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1169 // or even be finished without correct SP/WRR setting
1170
1171 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1172 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1173 // even though its T-Cont seems to be wrong ...
1174 loTrafficSchedulerEID := 0x8000
1175 //for all found queues
1176 iter := loQueueMap.IterFunc()
1177 for kv, ok := iter(); ok; kv, ok = iter() {
1178 queueIndex := (kv.Key).(uint16)
1179 meParams := me.ParamData{
1180 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301181 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001182 }
1183 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1184 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001185 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001186 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001187 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001188 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1189 } else {
1190 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001191 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001192 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1193 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001194 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001195 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1196 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1197 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001198 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001199 oFsm.pAdaptFsm.commChan, meParams)
1200 //accept also nil as (error) return value for writing to LastTx
1201 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001202 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001203
1204 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001205 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001206 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001207 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001208 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301209 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001210 return
1211 }
1212
1213 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1214 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1215 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1216 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1217
1218 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001219
1220 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001221 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301222 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001223}
1224
dbainbri4d3a0dc2020-12-02 00:33:42 +00001225func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001226 oFsm.mutexIsAwaitingResponse.Lock()
1227 oFsm.isAwaitingResponse = true
1228 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001229 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301230 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001231 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001232 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001233 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
dbainbri4d3a0dc2020-12-02 00:33:42 +00001234 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001235 oFsm.mutexIsAwaitingResponse.Lock()
1236 oFsm.isAwaitingResponse = false
1237 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001238 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001239 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301240 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001241 logger.Debug(ctx, "uniPonAniConfigFsm multi entity response received")
mpagenko7d6bb022021-03-11 15:07:55 +00001242 oFsm.mutexIsAwaitingResponse.Lock()
1243 oFsm.isAwaitingResponse = false
1244 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001245 return nil
1246 }
mpagenko7d6bb022021-03-11 15:07:55 +00001247 // waiting was aborted (probably on external request)
1248 logger.Debugw(ctx, "uniPonAniConfigFsm wait for multi entity response aborted", log.Fields{"for device-id": oFsm.deviceID})
1249 oFsm.mutexIsAwaitingResponse.Lock()
1250 oFsm.isAwaitingResponse = false
1251 oFsm.mutexIsAwaitingResponse.Unlock()
1252 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001253 }
1254}