blob: 01b2f347353eb75b90a6aaa75c5725464a918343 [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
242func (oFsm *uniPonAniConfigFsm) CancelProcessing() {
243 //mutex protection is required for possible concurrent access to FSM members
244 oFsm.mutexIsAwaitingResponse.RLock()
245 defer oFsm.mutexIsAwaitingResponse.RUnlock()
246 if oFsm.isAwaitingResponse {
247 //use channel to indicate that the response waiting shall be aborted
248 oFsm.omciMIdsResponseReceived <- false
249 }
250 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
251 pAdaptFsm := oFsm.pAdaptFsm
252 if pAdaptFsm != nil {
253 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
254 go func(aPAFsm *AdapterFsm) {
255 if aPAFsm.pFsm != nil {
256 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
257 }
258 }(pAdaptFsm)
259 }
260}
261
dbainbri4d3a0dc2020-12-02 00:33:42 +0000262func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530263 if aPAFsm != nil && aPAFsm.pFsm != nil {
264 //stick to pythonAdapter numbering scheme
265 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800266 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
267 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530268
Girish Gowdra041dcb32020-11-16 16:54:30 -0800269 /*
270 // Find a free TCONT Instance ID and use it
271 foundFreeTcontInstID := false
272 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000273 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800274
275 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
276 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
277 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
278 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
279 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
280 // when the ONU is discovered.
281 /*
282 for _, tcontInstID := range tcontInstKeys {
283 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
284 returnVal := tconInst["AllocId"]
285 if returnVal != nil {
286 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
287 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
288 if allocID == 0xff || allocID == 0xffff {
289 foundFreeTcontInstID = true
290 oFsm.tcont0ID = uint16(tcontInstID)
291 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
292 "device-id": oFsm.deviceID})
293 break
294 }
295 } else {
296 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
297 }
298 } else {
299 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
300 }
301 }
302 */
303
304 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
305 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
306 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
307 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
308 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
309 // TP ID will increment in single digit
310 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000311 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800312 "device-id": oFsm.deviceID})
313 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000314 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 -0800315 if oFsm.chanSet {
316 // indicate processing error/abort to the caller
317 oFsm.chSuccess <- 0
318 oFsm.chanSet = false //reset the internal channel state
319 }
320 //reset the state machine to enable usage on subsequent requests
321 _ = aPAFsm.pFsm.Event(aniEvReset)
322 return
323 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530324 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000325 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800326 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530327 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800328 /*
329 if !foundFreeTcontInstID {
330 // This should never happen. If it does, the behavior is unpredictable.
331 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
332 }*/
333
334 // Access critical state with lock
335 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000336 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
337 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800338 oFsm.pUniTechProf.mutexTPState.Unlock()
339
Himani Chawla26e555c2020-08-31 12:30:20 +0530340 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800341 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300342 loGemPortAttribs := ponAniGemPortAttribs{}
343
Himani Chawla26e555c2020-08-31 12:30:20 +0530344 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
345
dbainbri4d3a0dc2020-12-02 00:33:42 +0000346 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530347
348 loGemPortAttribs.gemPortID = gemEntry.gemPortID
349 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
350 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
351 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
352 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
353
354 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
355 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
356 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
357 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
358 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
359 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
360
361 usQueueFound := false
362 dsQueueFound := false
363 for _, mgmtEntityID := range queueInstKeys {
364 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
365 returnVal := meAttributes["RelatedPort"]
366 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530367 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530368 if relatedPort == usQrelPortMask {
369 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000370 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000371 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530372 usQueueFound = true
373 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
374 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000375 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000376 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530377 dsQueueFound = true
378 }
379 if usQueueFound && dsQueueFound {
380 break
381 }
382 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000383 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530384 }
385 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000386 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530387 }
388 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000389 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000390 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530391 }
392 }
393 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000394 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530395 }
396 loGemPortAttribs.direction = gemEntry.direction
397 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
398 loGemPortAttribs.weight = gemEntry.queueWeight
399 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300400 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300401 //TODO this might effectively ignore the for loop starting at line 316
402 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300403 loGemPortAttribs.isMulticast = true
404 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
405 loGemPortAttribs.staticACL = gemEntry.staticACL
406 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530407
dbainbri4d3a0dc2020-12-02 00:33:42 +0000408 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300409 "gemPortID": loGemPortAttribs.gemPortID,
410 "isMulticast": loGemPortAttribs.isMulticast,
411 "multicastGemID": loGemPortAttribs.multicastGemID,
412 "staticACL": loGemPortAttribs.staticACL,
413 "dynamicACL": loGemPortAttribs.dynamicACL,
414 })
415
416 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000417 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300418 "gemPortID": loGemPortAttribs.gemPortID,
419 "upQueueID": loGemPortAttribs.upQueueID,
420 "downQueueID": loGemPortAttribs.downQueueID,
421 "pbitString": loGemPortAttribs.pbitString,
422 "prioQueueIndex": gemEntry.prioQueueIndex,
423 })
424 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530425
426 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
427 }
428 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
429 }
430}
431
dbainbri4d3a0dc2020-12-02 00:33:42 +0000432func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
433 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000434 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000435 // in case the used channel is not yet defined (can be re-used after restarts)
436 if oFsm.omciMIdsResponseReceived == nil {
437 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000438 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000439 } else {
440 // as we may 're-use' this instance of FSM and the connected channel
441 // make sure there is no 'lingering' request in the already existing channel:
442 // (simple loop sufficient as we are the only receiver)
443 for len(oFsm.omciMIdsResponseReceived) > 0 {
444 <-oFsm.omciMIdsResponseReceived
445 }
446 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000447 //ensure internal slices are empty (which might be set from previous run) - release memory
448 oFsm.gemPortAttribsSlice = nil
449
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000450 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000451 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000452
453 //let the state machine run forward from here directly
454 pConfigAniStateAFsm := oFsm.pAdaptFsm
455 if pConfigAniStateAFsm != nil {
456 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000457 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000458
mpagenko3dbcdd22020-07-22 07:38:45 +0000459 }
460}
461
dbainbri4d3a0dc2020-12-02 00:33:42 +0000462func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
463 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000464 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000465 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
466 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Girish Gowdra0b235842021-03-09 13:06:46 -0800467 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000468 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
469 //accept also nil as (error) return value for writing to LastTx
470 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000471 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000472}
473
dbainbri4d3a0dc2020-12-02 00:33:42 +0000474func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
475 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000476 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
477 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000478 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000479 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
480 meParams := me.ParamData{
481 EntityID: oFsm.macBPCD0ID,
482 Attributes: me.AttributeValueMap{
483 "BridgeIdPointer": bridgePtr,
484 "PortNum": 0xFF, //fixed unique ANI side indication
485 "TpType": 3, //for .1PMapper
486 "TpPointer": oFsm.mapperSP0ID,
487 },
488 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800489 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000490 oFsm.pAdaptFsm.commChan, meParams)
491 //accept also nil as (error) return value for writing to LastTx
492 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000493 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000494}
495
dbainbri4d3a0dc2020-12-02 00:33:42 +0000496func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
497 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000498 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
499 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000500 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000501 meParams := me.ParamData{
502 EntityID: oFsm.tcont0ID,
503 Attributes: me.AttributeValueMap{
504 "AllocId": oFsm.alloc0ID,
505 },
506 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800507 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000508 oFsm.pAdaptFsm.commChan, meParams)
509 //accept also nil as (error) return value for writing to LastTx
510 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000511 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000512}
513
dbainbri4d3a0dc2020-12-02 00:33:42 +0000514func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
515 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000516 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000517 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000518}
519
dbainbri4d3a0dc2020-12-02 00:33:42 +0000520func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
521 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000522 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000523 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000524}
525
dbainbri4d3a0dc2020-12-02 00:33:42 +0000526func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
527 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000528 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000529 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000530}
531
dbainbri4d3a0dc2020-12-02 00:33:42 +0000532func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300533
dbainbri4d3a0dc2020-12-02 00:33:42 +0000534 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000535 "toGemIw": 1024, /* cmp above */
536 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000537
dbainbri4d3a0dc2020-12-02 00:33:42 +0000538 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000539 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000540 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000541
mpagenko3dbcdd22020-07-22 07:38:45 +0000542 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000543 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530544 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000545 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000546
547 //assign the GemPorts according to the configured Prio
548 var loPrioGemPortArray [8]uint16
549 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300550 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000551 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300552 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
553 "prioString": gemPortAttribs.pbitString})
554 continue
555 }
556 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000557 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300558 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
559 "prioString": gemPortAttribs.pbitString})
560 continue
561 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000562 for i := 0; i < 8; i++ {
563 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
564 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
565 if prio == 1 { // Check this p-bit is set
566 if loPrioGemPortArray[i] == 0 {
567 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
568 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000569 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000570 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000571 "SetGemPort": loPrioGemPortArray[i]})
572 }
573 }
574 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000575 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000576 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000577 "prioString": gemPortAttribs.pbitString, "position": i})
578 }
579
580 }
581 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300582
ozgecanetsia4b232302020-11-11 10:58:10 +0300583 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530584 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300585 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530586 if value != 0 {
587 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530588 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000589 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000590 "for Prio": index,
591 "IwPtr": strconv.FormatInt(int64(value), 16),
592 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300593 } else {
594 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000595 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
596 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300597 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530598 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000599 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300600 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000601 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
602 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300603 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530604
605 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000606 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000607 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300608 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
609 // 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 +0000610 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300611 //pConfigAniStateAFsm := oFsm.pAdaptFsm
612 //if pConfigAniStateAFsm != nil {
613 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
614 // go func(aPAFsm *AdapterFsm) {
615 // if aPAFsm != nil && aPAFsm.pFsm != nil {
616 // _ = aPAFsm.pFsm.Event(aniEvReset)
617 // }
618 // }(pConfigAniStateAFsm)
619 //}
620 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000621 pConfigAniStateAFsm := oFsm.pAdaptFsm
622 if pConfigAniStateAFsm != nil {
623 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530624 go func(aPAFsm *AdapterFsm) {
625 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300626 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000627 }
628 }(pConfigAniStateAFsm)
629 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300630 } else {
Girish Gowdra0b235842021-03-09 13:06:46 -0800631 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300632 oFsm.pAdaptFsm.commChan, meParams)
633 //accept also nil as (error) return value for writing to LastTx
634 // - this avoids misinterpretation of new received OMCI messages
635 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000636 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000637}
638
dbainbri4d3a0dc2020-12-02 00:33:42 +0000639func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
640 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000641 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000642 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000643 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000644 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800645 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000646 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000647 // but only in case the techProfile was configured (not deleted)
648 if oFsm.requestEventOffset == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000649 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000650 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000651
mpagenko01e726e2020-10-23 09:45:29 +0000652 if oFsm.chanSet {
653 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000654 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000655 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
656 oFsm.chSuccess <- oFsm.procStep
657 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000658 }
mpagenko01e726e2020-10-23 09:45:29 +0000659
660 //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 +0000661}
662
dbainbri4d3a0dc2020-12-02 00:33:42 +0000663func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
Girish Gowdra26a40922021-01-29 17:14:34 -0800664
mpagenkoa23a6292021-02-23 10:40:10 +0000665 oFsm.pUniTechProf.mutexTPState.Lock()
Girish Gowdra9085bca2021-03-08 12:57:48 -0800666 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending() {
mpagenkoa23a6292021-02-23 10:40:10 +0000667 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800668 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
669 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
670 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
671 pConfigAniStateAFsm := oFsm.pAdaptFsm
672 if pConfigAniStateAFsm != nil {
673 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
674 go func(aPAFsm *AdapterFsm) {
675 if aPAFsm != nil && aPAFsm.pFsm != nil {
676 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
677 }
678 }(pConfigAniStateAFsm)
679 } else {
680 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
681 }
682 return
683 }
684
mpagenko8b07c1b2020-11-26 10:36:31 +0000685 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000686 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
687 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000688 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000689 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
690 "GemIwTp-entity-id": loGemPortID})
691 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
692
693 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800694 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000695 oFsm.pAdaptFsm.commChan, loGemPortID)
696 oFsm.pLastTxMeInstance = meInstance
697}
698
dbainbri4d3a0dc2020-12-02 00:33:42 +0000699func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000700 oFsm.pUniTechProf.mutexTPState.Lock()
701 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
702 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000703 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000704 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
705 "GemNCTP-entity-id": loGemPortID})
706 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800707 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000708 oFsm.pAdaptFsm.commChan, loGemPortID)
709 oFsm.pLastTxMeInstance = meInstance
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800710 // Mark the gem port to be removed for Performance History monitoring
711 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
712 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
713 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000714}
715
dbainbri4d3a0dc2020-12-02 00:33:42 +0000716func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
717 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000718 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
719
720 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
721 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
722 meParams := me.ParamData{
723 EntityID: oFsm.tcont0ID,
724 Attributes: me.AttributeValueMap{
725 "AllocId": unusedTcontAllocID,
726 },
727 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800728 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000729 oFsm.pAdaptFsm.commChan, meParams)
730 oFsm.pLastTxMeInstance = meInstance
731}
732
dbainbri4d3a0dc2020-12-02 00:33:42 +0000733func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
734 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000735 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
736
Girish Gowdra0b235842021-03-09 13:06:46 -0800737 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000738 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
739 oFsm.pLastTxMeInstance = meInstance
740}
741
dbainbri4d3a0dc2020-12-02 00:33:42 +0000742func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
743 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000744 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
745
Girish Gowdra0b235842021-03-09 13:06:46 -0800746 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000747 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
748 oFsm.pLastTxMeInstance = meInstance
749}
750
dbainbri4d3a0dc2020-12-02 00:33:42 +0000751func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
752 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000753 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
754 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000755 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000756 if oFsm.chanSet {
757 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000758 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000759 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
760 oFsm.chSuccess <- oFsm.procStep
761 oFsm.chanSet = false //reset the internal channel state
762 }
763
764 //let's reset the state machine in order to release all resources now
765 pConfigAniStateAFsm := oFsm.pAdaptFsm
766 if pConfigAniStateAFsm != nil {
767 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
768 go func(aPAFsm *AdapterFsm) {
769 if aPAFsm != nil && aPAFsm.pFsm != nil {
770 _ = aPAFsm.pFsm.Event(aniEvReset)
771 }
772 }(pConfigAniStateAFsm)
773 }
774}
775
dbainbri4d3a0dc2020-12-02 00:33:42 +0000776func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
777 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000778 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000779
mpagenko3dbcdd22020-07-22 07:38:45 +0000780 pConfigAniStateAFsm := oFsm.pAdaptFsm
781 if pConfigAniStateAFsm != nil {
782 // abort running message processing
783 fsmAbortMsg := Message{
784 Type: TestMsg,
785 Data: TestMessage{
786 TestMessageVal: AbortMessageProcessing,
787 },
788 }
789 pConfigAniStateAFsm.commChan <- fsmAbortMsg
790
791 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530792 go func(aPAFsm *AdapterFsm) {
793 if aPAFsm != nil && aPAFsm.pFsm != nil {
794 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000795 }
796 }(pConfigAniStateAFsm)
797 }
798}
799
dbainbri4d3a0dc2020-12-02 00:33:42 +0000800func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
801 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000802 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko01e726e2020-10-23 09:45:29 +0000803 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000804
mpagenko01e726e2020-10-23 09:45:29 +0000805 //remove all TechProf related internal data to allow for new configuration (e.g. with disable/enable procedure)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000806 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko1cc3cb42020-07-27 15:24:38 +0000807}
808
dbainbri4d3a0dc2020-12-02 00:33:42 +0000809func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
810 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000811loop:
812 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000813 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000814 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000815 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530816 message, ok := <-oFsm.pAdaptFsm.commChan
817 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000818 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530819 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
820 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
821 break loop
822 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000823 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530824
825 switch message.Type {
826 case TestMsg:
827 msg, _ := message.Data.(TestMessage)
828 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000829 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000830 break loop
831 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000832 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530833 case OMCI:
834 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000835 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530836 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000837 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530838 "message.Type": message.Type})
839 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000840
Himani Chawla4d908332020-08-31 12:30:20 +0530841 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000842 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530843}
844
dbainbri4d3a0dc2020-12-02 00:33:42 +0000845func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530846 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
847 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000848 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000849 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530850 return
851 }
852 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
853 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000854 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000855 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530856 return
857 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000858 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000859 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
860 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
861 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
862 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
863 // maybe we can use just the same eventName for different state transitions like "forward"
864 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
865 switch oFsm.pLastTxMeInstance.GetName() {
866 case "Ieee8021PMapperServiceProfile":
867 { // let the FSM proceed ...
868 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
869 }
870 case "MacBridgePortConfigurationData":
871 { // let the FSM proceed ...
872 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
873 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300874 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
mpagenkofc4f56e2020-11-04 17:17:49 +0000875 { // let aniConfig Multi-Id processing proceed by stopping the wait function
876 oFsm.omciMIdsResponseReceived <- true
877 }
878 }
879 }
880 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000881 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530882 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
883 return
884 }
Himani Chawla4d908332020-08-31 12:30:20 +0530885}
886
dbainbri4d3a0dc2020-12-02 00:33:42 +0000887func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530888 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
889 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000890 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000891 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530892 return
893 }
894 msgObj, msgOk := msgLayer.(*omci.SetResponse)
895 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000896 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000897 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530898 return
899 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000900 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530901 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000902 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000903 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530904 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
905 return
906 }
mpagenko01e726e2020-10-23 09:45:29 +0000907 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
908 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +0530909 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
910 // if, then something like:
911 //oFsm.pOnuDB.StoreMe(msgObj)
912
mpagenko01e726e2020-10-23 09:45:29 +0000913 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +0530914 case "TCont":
915 { // let the FSM proceed ...
mpagenko8b07c1b2020-11-26 10:36:31 +0000916 if oFsm.requestEventOffset == 0 { //from TCont config request
917 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
918 } else { // from T-Cont reset request
919 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
920 }
Himani Chawla4d908332020-08-31 12:30:20 +0530921 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300922 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
Himani Chawla4d908332020-08-31 12:30:20 +0530923 { // let the PrioQueue init proceed by stopping the wait function
924 oFsm.omciMIdsResponseReceived <- true
925 }
926 case "Ieee8021PMapperServiceProfile":
927 { // let the FSM proceed ...
928 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
929 }
930 }
931 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000932}
933
dbainbri4d3a0dc2020-12-02 00:33:42 +0000934func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000935 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
936 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000937 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +0000938 log.Fields{"device-id": oFsm.deviceID})
939 return
940 }
941 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
942 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000943 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +0000944 log.Fields{"device-id": oFsm.deviceID})
945 return
946 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000947 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +0000948 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000949 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +0000950 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
951 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
952 // store error for mgmt display?
953 return
954 }
955 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
956 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
957 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
958 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
959
960 switch oFsm.pLastTxMeInstance.GetName() {
961 case "GemInterworkingTerminationPoint":
962 { // let the FSM proceed ...
963 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
964 }
965 case "GemPortNetworkCtp":
966 { // let the FSM proceed ...
967 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
968 }
969 case "Ieee8021PMapperServiceProfile":
970 { // let the FSM proceed ...
971 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
972 }
973 case "MacBridgePortConfigurationData":
974 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
975 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
976 }
977 }
978 }
979}
980
dbainbri4d3a0dc2020-12-02 00:33:42 +0000981func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
982 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +0000983 "msgType": msg.OmciMsg.MessageType})
984
985 switch msg.OmciMsg.MessageType {
986 case omci.CreateResponseType:
987 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000988 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530989
mpagenko3dbcdd22020-07-22 07:38:45 +0000990 } //CreateResponseType
991 case omci.SetResponseType:
992 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000993 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +0000994
mpagenko3dbcdd22020-07-22 07:38:45 +0000995 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +0000996 case omci.DeleteResponseType:
997 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000998 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +0000999
1000 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001001 default:
1002 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001003 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001004 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001005 return
1006 }
1007 }
1008}
1009
dbainbri4d3a0dc2020-12-02 00:33:42 +00001010func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001011 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1012 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001013 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001014 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1015 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001016 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001017 meParams := me.ParamData{
1018 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1019 Attributes: me.AttributeValueMap{
1020 "PortId": gemPortAttribs.gemPortID,
1021 "TContPointer": oFsm.tcont0ID,
1022 "Direction": gemPortAttribs.direction,
1023 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1024 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1025 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1026 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1027 },
1028 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001029 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001030 oFsm.pAdaptFsm.commChan, meParams)
1031 //accept also nil as (error) return value for writing to LastTx
1032 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001033 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +00001034
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001035 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001036 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001037 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001038 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001039 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301040 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001041 return
1042 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001043 // Mark the gem port to be removed for Performance History monitoring
1044 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
1045 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(gemPortAttribs.gemPortID)
1046 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001047 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001048
1049 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001050 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301051 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001052}
1053
dbainbri4d3a0dc2020-12-02 00:33:42 +00001054func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001055 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1056 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001057 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001058 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1059 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001060 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001061
ozgecanetsia4b232302020-11-11 10:58:10 +03001062 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1063 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001064
1065 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001066 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001067 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001068 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001069 "InterworkingOption": 0, // Don't Care
1070 "ServiceProfilePointer": 0, // Don't Care
1071 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001072 },
1073 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001074 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001075 true, oFsm.pAdaptFsm.commChan, meParams)
1076 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001077 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001078 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001079 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001080 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001081 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1082 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1083 return
1084 }
1085 ipv4MulticastTable := make([]uint8, 12)
1086 //Gem Port ID
1087 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1088 //Secondary Key
1089 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1090 // Multicast IP range start This is the 224.0.0.1 address
1091 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1092 // MulticastIp range stop
1093 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1094
1095 meIPV4MCTableParams := me.ParamData{
1096 EntityID: gemPortAttribs.multicastGemID,
1097 Attributes: me.AttributeValueMap{
1098 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1099 },
1100 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001101 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001102 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1103 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
ozgecanetsia4b232302020-11-11 10:58:10 +03001104
1105 } else {
1106 meParams := me.ParamData{
1107 EntityID: gemPortAttribs.gemPortID,
1108 Attributes: me.AttributeValueMap{
1109 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1110 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1111 "ServiceProfilePointer": oFsm.mapperSP0ID,
1112 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1113 "GalProfilePointer": galEthernetEID,
1114 },
1115 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001116 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001117 oFsm.pAdaptFsm.commChan, meParams)
1118 //accept also nil as (error) return value for writing to LastTx
1119 // - this avoids misinterpretation of new received OMCI messages
1120 oFsm.pLastTxMeInstance = meInstance
1121 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001122 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001123 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001124 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001125 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001126 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301127 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001128 return
1129 }
1130 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001131
1132 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001133 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301134 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001135}
1136
dbainbri4d3a0dc2020-12-02 00:33:42 +00001137func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001138 const cu16StrictPrioWeight uint16 = 0xFFFF
1139 //find all upstream PrioQueues related to this T-Cont
1140 loQueueMap := ordered_map.NewOrderedMap()
1141 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001142 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001143 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001144 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1145 "prioString": gemPortAttribs.pbitString})
1146 continue
1147 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001148 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301149 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001150 //key does not yet exist
1151 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1152 }
1153 } else {
1154 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1155 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001156 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001157
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001158 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1159 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1160 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1161 // or even be finished without correct SP/WRR setting
1162
1163 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1164 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1165 // even though its T-Cont seems to be wrong ...
1166 loTrafficSchedulerEID := 0x8000
1167 //for all found queues
1168 iter := loQueueMap.IterFunc()
1169 for kv, ok := iter(); ok; kv, ok = iter() {
1170 queueIndex := (kv.Key).(uint16)
1171 meParams := me.ParamData{
1172 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301173 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001174 }
1175 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1176 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001177 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001178 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001179 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001180 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1181 } else {
1182 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001183 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001184 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1185 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001186 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001187 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1188 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1189 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001190 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001191 oFsm.pAdaptFsm.commChan, meParams)
1192 //accept also nil as (error) return value for writing to LastTx
1193 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001194 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001195
1196 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001197 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001198 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001199 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001200 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301201 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001202 return
1203 }
1204
1205 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1206 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1207 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1208 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1209
1210 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001211
1212 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001213 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301214 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001215}
1216
dbainbri4d3a0dc2020-12-02 00:33:42 +00001217func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001218 oFsm.mutexIsAwaitingResponse.Lock()
1219 oFsm.isAwaitingResponse = true
1220 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001221 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301222 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001223 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001224 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001225 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 +00001226 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001227 oFsm.mutexIsAwaitingResponse.Lock()
1228 oFsm.isAwaitingResponse = false
1229 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001230 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001231 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301232 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001233 logger.Debug(ctx, "uniPonAniConfigFsm multi entity response received")
mpagenko7d6bb022021-03-11 15:07:55 +00001234 oFsm.mutexIsAwaitingResponse.Lock()
1235 oFsm.isAwaitingResponse = false
1236 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001237 return nil
1238 }
mpagenko7d6bb022021-03-11 15:07:55 +00001239 // waiting was aborted (probably on external request)
1240 logger.Debugw(ctx, "uniPonAniConfigFsm wait for multi entity response aborted", log.Fields{"for device-id": oFsm.deviceID})
1241 oFsm.mutexIsAwaitingResponse.Lock()
1242 oFsm.isAwaitingResponse = false
1243 oFsm.mutexIsAwaitingResponse.Unlock()
1244 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001245 }
1246}