blob: 423db394da95f4d739f288c0fd8866ca281fb860 [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
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000128 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000129 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000130 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000131 isWaitingForFlowDelete bool
132 waitFlowDeleteChannel chan bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000133}
134
Himani Chawla6d2ae152020-09-02 13:11:20 +0530135//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 +0000136func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800137 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000138 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530139 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000140 pDeviceHandler: apDeviceHandler,
141 deviceID: apDeviceHandler.deviceID,
142 pOmciCC: apDevOmciCC,
143 pOnuUniPort: apUniPort,
144 pUniTechProf: apUniTechProf,
145 pOnuDB: apOnuDB,
146 techProfileID: aTechProfileID,
147 requestEvent: aRequestEvent,
148 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000149 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000150 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000151 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000152
mpagenko01e726e2020-10-23 09:45:29 +0000153 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000154 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000155 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000156 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000157 return nil
158 }
159
160 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000161 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000162 fsm.Events{
163
mpagenko1cc3cb42020-07-27 15:24:38 +0000164 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000165
166 //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 +0000167 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000168 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000169 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
170 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000171 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000172 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000173 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000174 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000175 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000176 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000177 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000178
mpagenko8b07c1b2020-11-26 10:36:31 +0000179 //for removing Gem related resources
180 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800181 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
182 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000183 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
184 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
185
186 //for removing TCONT related resources
187 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
188 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
189 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
190 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
191
192 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
193 aniStRemovingGemIW, aniStRemovingGemNCTP,
194 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000195 {Name: aniEvTimeoutMids, Src: []string{
196 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000197
mpagenko1cc3cb42020-07-27 15:24:38 +0000198 // exceptional treatment for all states except aniStResetting
199 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
200 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000201 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000202 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000203 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000204 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000205 },
206
207 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000208 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
209 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
210 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
211 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
212 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
213 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
214 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
215 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
216 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
217 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
218 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000219 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000220 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
221 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
222 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
223 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
224 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
225 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
226 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000227 },
228 )
229 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000230 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000231 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000232 return nil
233 }
234
dbainbri4d3a0dc2020-12-02 00:33:42 +0000235 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000236 return instFsm
237}
238
Himani Chawla6d2ae152020-09-02 13:11:20 +0530239//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
240func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000241 oFsm.chSuccess = aChSuccess
242 oFsm.procStep = aProcStep
243 oFsm.chanSet = true
244}
245
mpagenko7d6bb022021-03-11 15:07:55 +0000246//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000247func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
248 //early indication about started reset processing
249 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000250 //mutex protection is required for possible concurrent access to FSM members
251 oFsm.mutexIsAwaitingResponse.RLock()
252 defer oFsm.mutexIsAwaitingResponse.RUnlock()
253 if oFsm.isAwaitingResponse {
254 //use channel to indicate that the response waiting shall be aborted
255 oFsm.omciMIdsResponseReceived <- false
256 }
mpagenkobb47bc22021-04-20 13:29:09 +0000257 if oFsm.isWaitingForFlowDelete {
258 //use channel to indicate that the response waiting shall be aborted
259 oFsm.waitFlowDeleteChannel <- false
260 }
mpagenko7d6bb022021-03-11 15:07:55 +0000261 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
262 pAdaptFsm := oFsm.pAdaptFsm
263 if pAdaptFsm != nil {
264 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
265 go func(aPAFsm *AdapterFsm) {
266 if aPAFsm.pFsm != nil {
267 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
268 }
269 }(pAdaptFsm)
270 }
mpagenko73143992021-04-09 15:17:10 +0000271
272 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
273 // access conflicts on internal data by next needed data clearance
274 //activity should be aborted in short time if running with FSM due to above FSM reset
275 // or finished without FSM dependency in short time
276 oFsm.pUniTechProf.lockTpProcMutex()
277 defer oFsm.pUniTechProf.unlockTpProcMutex()
278 //remove all TechProf related internal data to allow for new configuration
279 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000280}
281
dbainbri4d3a0dc2020-12-02 00:33:42 +0000282func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530283 if aPAFsm != nil && aPAFsm.pFsm != nil {
284 //stick to pythonAdapter numbering scheme
285 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800286 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
287 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530288
Girish Gowdra041dcb32020-11-16 16:54:30 -0800289 /*
290 // Find a free TCONT Instance ID and use it
291 foundFreeTcontInstID := false
292 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000293 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800294
295 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
296 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
297 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
298 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
299 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
300 // when the ONU is discovered.
301 /*
302 for _, tcontInstID := range tcontInstKeys {
303 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
304 returnVal := tconInst["AllocId"]
305 if returnVal != nil {
306 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
307 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
308 if allocID == 0xff || allocID == 0xffff {
309 foundFreeTcontInstID = true
310 oFsm.tcont0ID = uint16(tcontInstID)
311 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
312 "device-id": oFsm.deviceID})
313 break
314 }
315 } else {
316 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
317 }
318 } else {
319 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
320 }
321 }
322 */
323
324 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
325 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
326 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
327 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
328 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
329 // TP ID will increment in single digit
330 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000331 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800332 "device-id": oFsm.deviceID})
333 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000334 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 -0800335 if oFsm.chanSet {
336 // indicate processing error/abort to the caller
337 oFsm.chSuccess <- 0
338 oFsm.chanSet = false //reset the internal channel state
339 }
340 //reset the state machine to enable usage on subsequent requests
341 _ = aPAFsm.pFsm.Event(aniEvReset)
342 return
343 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530344 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000345 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800346 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530347 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800348 /*
349 if !foundFreeTcontInstID {
350 // This should never happen. If it does, the behavior is unpredictable.
351 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
352 }*/
353
354 // Access critical state with lock
355 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000356 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
357 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800358 oFsm.pUniTechProf.mutexTPState.Unlock()
359
Himani Chawla26e555c2020-08-31 12:30:20 +0530360 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800361 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300362 loGemPortAttribs := ponAniGemPortAttribs{}
363
Himani Chawla26e555c2020-08-31 12:30:20 +0530364 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
365
dbainbri4d3a0dc2020-12-02 00:33:42 +0000366 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530367
368 loGemPortAttribs.gemPortID = gemEntry.gemPortID
369 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
370 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
371 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
372 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
373
374 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
375 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
376 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
377 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
378 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
379 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
380
381 usQueueFound := false
382 dsQueueFound := false
383 for _, mgmtEntityID := range queueInstKeys {
384 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
385 returnVal := meAttributes["RelatedPort"]
386 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530387 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530388 if relatedPort == usQrelPortMask {
389 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000390 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000391 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530392 usQueueFound = true
393 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
394 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000395 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000396 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530397 dsQueueFound = true
398 }
399 if usQueueFound && dsQueueFound {
400 break
401 }
402 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000403 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530404 }
405 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000406 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530407 }
408 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000409 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000410 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530411 }
412 }
413 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000414 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530415 }
416 loGemPortAttribs.direction = gemEntry.direction
417 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
418 loGemPortAttribs.weight = gemEntry.queueWeight
419 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300420 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300421 //TODO this might effectively ignore the for loop starting at line 316
422 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300423 loGemPortAttribs.isMulticast = true
424 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
425 loGemPortAttribs.staticACL = gemEntry.staticACL
426 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530427
dbainbri4d3a0dc2020-12-02 00:33:42 +0000428 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300429 "gemPortID": loGemPortAttribs.gemPortID,
430 "isMulticast": loGemPortAttribs.isMulticast,
431 "multicastGemID": loGemPortAttribs.multicastGemID,
432 "staticACL": loGemPortAttribs.staticACL,
433 "dynamicACL": loGemPortAttribs.dynamicACL,
434 })
435
436 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000437 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300438 "gemPortID": loGemPortAttribs.gemPortID,
439 "upQueueID": loGemPortAttribs.upQueueID,
440 "downQueueID": loGemPortAttribs.downQueueID,
441 "pbitString": loGemPortAttribs.pbitString,
442 "prioQueueIndex": gemEntry.prioQueueIndex,
443 })
444 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530445
446 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
447 }
448 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
449 }
450}
451
dbainbri4d3a0dc2020-12-02 00:33:42 +0000452func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
453 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000454 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000455 // in case the used channel is not yet defined (can be re-used after restarts)
456 if oFsm.omciMIdsResponseReceived == nil {
457 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000458 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000459 } else {
460 // as we may 're-use' this instance of FSM and the connected channel
461 // make sure there is no 'lingering' request in the already existing channel:
462 // (simple loop sufficient as we are the only receiver)
463 for len(oFsm.omciMIdsResponseReceived) > 0 {
464 <-oFsm.omciMIdsResponseReceived
465 }
466 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000467 //ensure internal slices are empty (which might be set from previous run) - release memory
468 oFsm.gemPortAttribsSlice = nil
469
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000470 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000471 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000472
473 //let the state machine run forward from here directly
474 pConfigAniStateAFsm := oFsm.pAdaptFsm
475 if pConfigAniStateAFsm != nil {
476 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000477 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000478
mpagenko3dbcdd22020-07-22 07:38:45 +0000479 }
480}
481
dbainbri4d3a0dc2020-12-02 00:33:42 +0000482func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
483 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000484 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000485 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
486 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000487 oFsm.mutexPLastTxMeInstance.Lock()
488 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800489 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000490 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
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) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
497 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000498 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
499 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000500 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000501 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
502 meParams := me.ParamData{
503 EntityID: oFsm.macBPCD0ID,
504 Attributes: me.AttributeValueMap{
505 "BridgeIdPointer": bridgePtr,
506 "PortNum": 0xFF, //fixed unique ANI side indication
507 "TpType": 3, //for .1PMapper
508 "TpPointer": oFsm.mapperSP0ID,
509 },
510 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000511 oFsm.mutexPLastTxMeInstance.Lock()
512 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800513 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000514 oFsm.pAdaptFsm.commChan, meParams)
515 //accept also nil as (error) return value for writing to LastTx
516 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000517 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000518}
519
dbainbri4d3a0dc2020-12-02 00:33:42 +0000520func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
521 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000522 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
523 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000524 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000525 meParams := me.ParamData{
526 EntityID: oFsm.tcont0ID,
527 Attributes: me.AttributeValueMap{
528 "AllocId": oFsm.alloc0ID,
529 },
530 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000531 oFsm.mutexPLastTxMeInstance.Lock()
532 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800533 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000534 oFsm.pAdaptFsm.commChan, meParams)
535 //accept also nil as (error) return value for writing to LastTx
536 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000537 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000538}
539
dbainbri4d3a0dc2020-12-02 00:33:42 +0000540func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
541 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000542 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000543 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000544}
545
dbainbri4d3a0dc2020-12-02 00:33:42 +0000546func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
547 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000548 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000549 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000550}
551
dbainbri4d3a0dc2020-12-02 00:33:42 +0000552func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
553 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000554 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000555 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000556}
557
dbainbri4d3a0dc2020-12-02 00:33:42 +0000558func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300559
dbainbri4d3a0dc2020-12-02 00:33:42 +0000560 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000561 "toGemIw": 1024, /* cmp above */
562 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000563
dbainbri4d3a0dc2020-12-02 00:33:42 +0000564 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000565 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000566 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000567
mpagenko3dbcdd22020-07-22 07:38:45 +0000568 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000569 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530570 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000571 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000572
573 //assign the GemPorts according to the configured Prio
574 var loPrioGemPortArray [8]uint16
575 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300576 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000577 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300578 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
579 "prioString": gemPortAttribs.pbitString})
580 continue
581 }
582 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000583 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300584 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
585 "prioString": gemPortAttribs.pbitString})
586 continue
587 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000588 for i := 0; i < 8; i++ {
589 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
590 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
591 if prio == 1 { // Check this p-bit is set
592 if loPrioGemPortArray[i] == 0 {
593 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
594 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000595 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000596 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000597 "SetGemPort": loPrioGemPortArray[i]})
598 }
599 }
600 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000601 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000602 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000603 "prioString": gemPortAttribs.pbitString, "position": i})
604 }
605
606 }
607 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300608
ozgecanetsia4b232302020-11-11 10:58:10 +0300609 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530610 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300611 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530612 if value != 0 {
613 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530614 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000615 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000616 "for Prio": index,
617 "IwPtr": strconv.FormatInt(int64(value), 16),
618 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300619 } else {
620 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000621 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
622 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300623 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530624 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000625 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300626 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000627 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
628 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300629 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530630
631 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000632 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000633 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300634 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
635 // 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 +0000636 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300637 //pConfigAniStateAFsm := oFsm.pAdaptFsm
638 //if pConfigAniStateAFsm != nil {
639 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
640 // go func(aPAFsm *AdapterFsm) {
641 // if aPAFsm != nil && aPAFsm.pFsm != nil {
642 // _ = aPAFsm.pFsm.Event(aniEvReset)
643 // }
644 // }(pConfigAniStateAFsm)
645 //}
646 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000647 pConfigAniStateAFsm := oFsm.pAdaptFsm
648 if pConfigAniStateAFsm != nil {
649 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530650 go func(aPAFsm *AdapterFsm) {
651 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300652 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000653 }
654 }(pConfigAniStateAFsm)
655 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300656 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000657 oFsm.mutexPLastTxMeInstance.Lock()
658 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800659 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300660 oFsm.pAdaptFsm.commChan, meParams)
661 //accept also nil as (error) return value for writing to LastTx
662 // - this avoids misinterpretation of new received OMCI messages
663 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000664 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000665}
666
dbainbri4d3a0dc2020-12-02 00:33:42 +0000667func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
668 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000669 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000670 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000671 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000672 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800673 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000674 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000675 // but only in case the techProfile was configured (not deleted)
676 if oFsm.requestEventOffset == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000677 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000678 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000679
mpagenko01e726e2020-10-23 09:45:29 +0000680 if oFsm.chanSet {
681 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000682 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000683 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
684 oFsm.chSuccess <- oFsm.procStep
685 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000686 }
mpagenko01e726e2020-10-23 09:45:29 +0000687
688 //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 +0000689}
690
dbainbri4d3a0dc2020-12-02 00:33:42 +0000691func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000692 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000693 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
694 select {
695 case <-oFsm.waitFlowDeleteChannel:
696 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
697 default:
698 }
699 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
mpagenkoa23a6292021-02-23 10:40:10 +0000700 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800701 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
702 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
703 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
704 pConfigAniStateAFsm := oFsm.pAdaptFsm
705 if pConfigAniStateAFsm != nil {
706 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
707 go func(aPAFsm *AdapterFsm) {
708 if aPAFsm != nil && aPAFsm.pFsm != nil {
709 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
710 }
711 }(pConfigAniStateAFsm)
712 } else {
713 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
714 }
715 return
716 }
717
mpagenko8b07c1b2020-11-26 10:36:31 +0000718 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000719 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
720 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000721 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000722 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
723 "GemIwTp-entity-id": loGemPortID})
724 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
725
726 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000727 oFsm.mutexPLastTxMeInstance.Lock()
728 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800729 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000730 oFsm.pAdaptFsm.commChan, loGemPortID)
731 oFsm.pLastTxMeInstance = meInstance
732}
733
mpagenkobb47bc22021-04-20 13:29:09 +0000734func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
735 oFsm.mutexIsAwaitingResponse.Lock()
736 oFsm.isWaitingForFlowDelete = true
737 oFsm.mutexIsAwaitingResponse.Unlock()
738 select {
739 // maybe be also some outside cancel (but no context modeled for the moment ...)
740 // case <-ctx.Done():
741 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
742 case <-time.After(10 * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
743 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
744 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
745 oFsm.mutexIsAwaitingResponse.Lock()
746 oFsm.isWaitingForFlowDelete = false
747 oFsm.mutexIsAwaitingResponse.Unlock()
748 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
749 pConfigAniStateAFsm := oFsm.pAdaptFsm
750 if pConfigAniStateAFsm != nil {
751 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
752 go func(aPAFsm *AdapterFsm) {
753 if aPAFsm != nil && aPAFsm.pFsm != nil {
754 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
755 }
756 }(pConfigAniStateAFsm)
757 } else {
758 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
759 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
760 }
761 return
762
763 case success := <-oFsm.waitFlowDeleteChannel:
764 if success {
765 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
766 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
767 oFsm.mutexIsAwaitingResponse.Lock()
768 oFsm.isWaitingForFlowDelete = false
769 oFsm.mutexIsAwaitingResponse.Unlock()
770 pConfigAniStateAFsm := oFsm.pAdaptFsm
771 if pConfigAniStateAFsm != nil {
772 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
773 go func(aPAFsm *AdapterFsm) {
774 if aPAFsm != nil && aPAFsm.pFsm != nil {
775 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
776 }
777 }(pConfigAniStateAFsm)
778 } else {
779 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
780 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
781 }
782 return
783 }
784 // waiting was aborted (probably on external request)
785 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
786 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
787 oFsm.mutexIsAwaitingResponse.Lock()
788 oFsm.isWaitingForFlowDelete = false
789 oFsm.mutexIsAwaitingResponse.Unlock()
790 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
791 pConfigAniStateAFsm := oFsm.pAdaptFsm
792 if pConfigAniStateAFsm != nil {
793 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
794 go func(aPAFsm *AdapterFsm) {
795 if aPAFsm != nil && aPAFsm.pFsm != nil {
796 _ = aPAFsm.pFsm.Event(aniEvReset)
797 }
798 }(pConfigAniStateAFsm)
799 }
800 return
801 }
802}
803
dbainbri4d3a0dc2020-12-02 00:33:42 +0000804func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000805 oFsm.pUniTechProf.mutexTPState.Lock()
806 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
807 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000808 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000809 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
810 "GemNCTP-entity-id": loGemPortID})
811 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000812 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800813 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000814 oFsm.pAdaptFsm.commChan, loGemPortID)
815 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000816 oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800817 // Mark the gem port to be removed for Performance History monitoring
818 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
819 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
820 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000821}
822
dbainbri4d3a0dc2020-12-02 00:33:42 +0000823func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
824 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000825 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
826
827 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
828 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
829 meParams := me.ParamData{
830 EntityID: oFsm.tcont0ID,
831 Attributes: me.AttributeValueMap{
832 "AllocId": unusedTcontAllocID,
833 },
834 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000835 oFsm.mutexPLastTxMeInstance.Lock()
836 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800837 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000838 oFsm.pAdaptFsm.commChan, meParams)
839 oFsm.pLastTxMeInstance = meInstance
840}
841
dbainbri4d3a0dc2020-12-02 00:33:42 +0000842func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
843 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000844 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
845
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000846 oFsm.mutexPLastTxMeInstance.Lock()
847 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800848 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000849 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
850 oFsm.pLastTxMeInstance = meInstance
851}
852
dbainbri4d3a0dc2020-12-02 00:33:42 +0000853func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
854 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000855 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
856
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000857 oFsm.mutexPLastTxMeInstance.Lock()
858 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800859 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000860 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
861 oFsm.pLastTxMeInstance = meInstance
862}
863
dbainbri4d3a0dc2020-12-02 00:33:42 +0000864func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
865 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000866 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
867 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000868 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000869 if oFsm.chanSet {
870 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000871 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000872 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
873 oFsm.chSuccess <- oFsm.procStep
874 oFsm.chanSet = false //reset the internal channel state
875 }
876
877 //let's reset the state machine in order to release all resources now
878 pConfigAniStateAFsm := oFsm.pAdaptFsm
879 if pConfigAniStateAFsm != nil {
880 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
881 go func(aPAFsm *AdapterFsm) {
882 if aPAFsm != nil && aPAFsm.pFsm != nil {
883 _ = aPAFsm.pFsm.Event(aniEvReset)
884 }
885 }(pConfigAniStateAFsm)
886 }
887}
888
dbainbri4d3a0dc2020-12-02 00:33:42 +0000889func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
890 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000891 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000892
mpagenko3dbcdd22020-07-22 07:38:45 +0000893 pConfigAniStateAFsm := oFsm.pAdaptFsm
894 if pConfigAniStateAFsm != nil {
895 // abort running message processing
896 fsmAbortMsg := Message{
897 Type: TestMsg,
898 Data: TestMessage{
899 TestMessageVal: AbortMessageProcessing,
900 },
901 }
902 pConfigAniStateAFsm.commChan <- fsmAbortMsg
903
904 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530905 go func(aPAFsm *AdapterFsm) {
906 if aPAFsm != nil && aPAFsm.pFsm != nil {
907 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000908 }
909 }(pConfigAniStateAFsm)
910 }
911}
912
dbainbri4d3a0dc2020-12-02 00:33:42 +0000913func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
914 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000915 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000916 oFsm.mutexPLastTxMeInstance.Lock()
917 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000918 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000919}
920
dbainbri4d3a0dc2020-12-02 00:33:42 +0000921func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
922 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000923loop:
924 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000925 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000926 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000927 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530928 message, ok := <-oFsm.pAdaptFsm.commChan
929 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000930 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530931 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
932 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
933 break loop
934 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000935 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530936
937 switch message.Type {
938 case TestMsg:
939 msg, _ := message.Data.(TestMessage)
940 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000941 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000942 break loop
943 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000944 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530945 case OMCI:
946 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000947 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530948 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000949 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530950 "message.Type": message.Type})
951 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000952
Himani Chawla4d908332020-08-31 12:30:20 +0530953 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000954 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530955}
956
dbainbri4d3a0dc2020-12-02 00:33:42 +0000957func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530958 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
959 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000960 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000961 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530962 return
963 }
964 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
965 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000966 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000967 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530968 return
969 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000970 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000971 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
972 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000973 oFsm.mutexPLastTxMeInstance.RLock()
974 if oFsm.pLastTxMeInstance != nil {
975 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
976 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
977 // maybe we can use just the same eventName for different state transitions like "forward"
978 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
979 switch oFsm.pLastTxMeInstance.GetName() {
980 case "Ieee8021PMapperServiceProfile":
981 { // let the FSM proceed ...
982 oFsm.mutexPLastTxMeInstance.RUnlock()
983 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
984 }
985 case "MacBridgePortConfigurationData":
986 { // let the FSM proceed ...
987 oFsm.mutexPLastTxMeInstance.RUnlock()
988 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
989 }
990 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
991 { // let aniConfig Multi-Id processing proceed by stopping the wait function
992 oFsm.mutexPLastTxMeInstance.RUnlock()
993 oFsm.omciMIdsResponseReceived <- true
994 }
995 default:
996 {
997 oFsm.mutexPLastTxMeInstance.RUnlock()
998 logger.Warnw(ctx, "Unsupported ME name received!",
999 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1000 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001001 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001002 } else {
1003 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001004 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001005 } else {
1006 oFsm.mutexPLastTxMeInstance.RUnlock()
1007 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001008 }
1009 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001010 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1011 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301012 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1013 return
1014 }
Himani Chawla4d908332020-08-31 12:30:20 +05301015}
1016
dbainbri4d3a0dc2020-12-02 00:33:42 +00001017func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301018 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1019 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001020 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001021 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301022 return
1023 }
1024 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1025 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001026 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001027 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301028 return
1029 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001030 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301031 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001032 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001033 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301034 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1035 return
1036 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001037 oFsm.mutexPLastTxMeInstance.RLock()
1038 if oFsm.pLastTxMeInstance != nil {
1039 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1040 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1041 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1042 // if, then something like:
1043 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301044
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001045 switch oFsm.pLastTxMeInstance.GetName() {
1046 case "TCont":
1047 { // let the FSM proceed ...
1048 oFsm.mutexPLastTxMeInstance.RUnlock()
1049 if oFsm.requestEventOffset == 0 { //from TCont config request
1050 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1051 } else { // from T-Cont reset request
1052 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1053 }
1054 }
1055 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1056 { // let the PrioQueue init proceed by stopping the wait function
1057 oFsm.mutexPLastTxMeInstance.RUnlock()
1058 oFsm.omciMIdsResponseReceived <- true
1059 }
1060 case "Ieee8021PMapperServiceProfile":
1061 { // let the FSM proceed ...
1062 oFsm.mutexPLastTxMeInstance.RUnlock()
1063 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1064 }
1065 default:
1066 {
1067 oFsm.mutexPLastTxMeInstance.RUnlock()
1068 logger.Warnw(ctx, "Unsupported ME name received!",
1069 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001070 }
Himani Chawla4d908332020-08-31 12:30:20 +05301071 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001072 } else {
1073 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301074 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001075 } else {
1076 oFsm.mutexPLastTxMeInstance.RUnlock()
1077 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301078 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001079}
1080
dbainbri4d3a0dc2020-12-02 00:33:42 +00001081func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001082 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1083 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001084 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001085 log.Fields{"device-id": oFsm.deviceID})
1086 return
1087 }
1088 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1089 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001090 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001091 log.Fields{"device-id": oFsm.deviceID})
1092 return
1093 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001094 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001095 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001096 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001097 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1098 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1099 // store error for mgmt display?
1100 return
1101 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001102 oFsm.mutexPLastTxMeInstance.RLock()
1103 if oFsm.pLastTxMeInstance != nil {
1104 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1105 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1106 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1107 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001108
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001109 switch oFsm.pLastTxMeInstance.GetName() {
1110 case "GemInterworkingTerminationPoint":
1111 { // let the FSM proceed ...
1112 oFsm.mutexPLastTxMeInstance.RUnlock()
1113 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1114 }
1115 case "GemPortNetworkCtp":
1116 { // let the FSM proceed ...
1117 oFsm.mutexPLastTxMeInstance.RUnlock()
1118 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1119 }
1120 case "Ieee8021PMapperServiceProfile":
1121 { // let the FSM proceed ...
1122 oFsm.mutexPLastTxMeInstance.RUnlock()
1123 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1124 }
1125 case "MacBridgePortConfigurationData":
1126 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1127 oFsm.mutexPLastTxMeInstance.RUnlock()
1128 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1129 }
1130 default:
1131 {
1132 oFsm.mutexPLastTxMeInstance.RUnlock()
1133 logger.Warnw(ctx, "Unsupported ME name received!",
1134 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1135 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001136 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001137 } else {
1138 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001139 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001140 } else {
1141 oFsm.mutexPLastTxMeInstance.RUnlock()
1142 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001143 }
1144}
1145
dbainbri4d3a0dc2020-12-02 00:33:42 +00001146func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1147 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001148 "msgType": msg.OmciMsg.MessageType})
1149
1150 switch msg.OmciMsg.MessageType {
1151 case omci.CreateResponseType:
1152 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001153 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301154
mpagenko3dbcdd22020-07-22 07:38:45 +00001155 } //CreateResponseType
1156 case omci.SetResponseType:
1157 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001158 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001159
mpagenko3dbcdd22020-07-22 07:38:45 +00001160 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001161 case omci.DeleteResponseType:
1162 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001163 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001164
1165 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001166 default:
1167 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001168 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001169 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001170 return
1171 }
1172 }
1173}
1174
dbainbri4d3a0dc2020-12-02 00:33:42 +00001175func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001176 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1177 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001178 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001179 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1180 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001181 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001182 meParams := me.ParamData{
1183 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1184 Attributes: me.AttributeValueMap{
1185 "PortId": gemPortAttribs.gemPortID,
1186 "TContPointer": oFsm.tcont0ID,
1187 "Direction": gemPortAttribs.direction,
1188 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1189 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1190 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1191 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1192 },
1193 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001194 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001195 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001196 oFsm.pAdaptFsm.commChan, meParams)
1197 //accept also nil as (error) return value for writing to LastTx
1198 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001199 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001200 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001201
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001202 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001203 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001204 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001205 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001206 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301207 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001208 return
1209 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001210 // Mark the gem port to be removed for Performance History monitoring
1211 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
1212 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(gemPortAttribs.gemPortID)
1213 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001214 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001215
1216 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001217 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301218 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001219}
1220
dbainbri4d3a0dc2020-12-02 00:33:42 +00001221func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001222 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1223 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001224 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001225 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1226 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001227 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001228
ozgecanetsia4b232302020-11-11 10:58:10 +03001229 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1230 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001231
1232 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001233 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001234 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001235 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001236 "InterworkingOption": 0, // Don't Care
1237 "ServiceProfilePointer": 0, // Don't Care
1238 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001239 },
1240 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001241 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001242 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001243 true, oFsm.pAdaptFsm.commChan, meParams)
1244 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001245 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001246 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001247 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001248 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001249 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001250 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1251 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1252 return
1253 }
1254 ipv4MulticastTable := make([]uint8, 12)
1255 //Gem Port ID
1256 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1257 //Secondary Key
1258 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1259 // Multicast IP range start This is the 224.0.0.1 address
1260 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1261 // MulticastIp range stop
1262 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1263
1264 meIPV4MCTableParams := me.ParamData{
1265 EntityID: gemPortAttribs.multicastGemID,
1266 Attributes: me.AttributeValueMap{
1267 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1268 },
1269 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001270 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001271 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001272 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1273 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001274 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001275
1276 } else {
1277 meParams := me.ParamData{
1278 EntityID: gemPortAttribs.gemPortID,
1279 Attributes: me.AttributeValueMap{
1280 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1281 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1282 "ServiceProfilePointer": oFsm.mapperSP0ID,
1283 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1284 "GalProfilePointer": galEthernetEID,
1285 },
1286 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001287 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001288 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001289 oFsm.pAdaptFsm.commChan, meParams)
1290 //accept also nil as (error) return value for writing to LastTx
1291 // - this avoids misinterpretation of new received OMCI messages
1292 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001293 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001294 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001295 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001296 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001297 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001298 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001299 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301300 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001301 return
1302 }
1303 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001304
1305 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001306 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301307 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001308}
1309
dbainbri4d3a0dc2020-12-02 00:33:42 +00001310func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001311 const cu16StrictPrioWeight uint16 = 0xFFFF
1312 //find all upstream PrioQueues related to this T-Cont
1313 loQueueMap := ordered_map.NewOrderedMap()
1314 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001315 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001316 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001317 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1318 "prioString": gemPortAttribs.pbitString})
1319 continue
1320 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001321 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301322 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001323 //key does not yet exist
1324 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1325 }
1326 } else {
1327 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1328 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001329 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001330
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001331 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1332 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1333 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1334 // or even be finished without correct SP/WRR setting
1335
1336 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1337 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1338 // even though its T-Cont seems to be wrong ...
1339 loTrafficSchedulerEID := 0x8000
1340 //for all found queues
1341 iter := loQueueMap.IterFunc()
1342 for kv, ok := iter(); ok; kv, ok = iter() {
1343 queueIndex := (kv.Key).(uint16)
1344 meParams := me.ParamData{
1345 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301346 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001347 }
1348 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1349 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001350 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001351 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001352 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001353 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1354 } else {
1355 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001356 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001357 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1358 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001359 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001360 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1361 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1362 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001363 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001364 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001365 oFsm.pAdaptFsm.commChan, meParams)
1366 //accept also nil as (error) return value for writing to LastTx
1367 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001368 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001369 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001370
1371 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001372 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001373 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001374 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001375 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301376 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001377 return
1378 }
1379
1380 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1381 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1382 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1383 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1384
1385 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001386
1387 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001388 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301389 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001390}
1391
dbainbri4d3a0dc2020-12-02 00:33:42 +00001392func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001393 oFsm.mutexIsAwaitingResponse.Lock()
1394 oFsm.isAwaitingResponse = true
1395 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001396 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301397 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001398 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001399 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001400 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 +00001401 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001402 oFsm.mutexIsAwaitingResponse.Lock()
1403 oFsm.isAwaitingResponse = false
1404 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001405 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001406 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301407 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001408 logger.Debug(ctx, "uniPonAniConfigFsm multi entity response received")
mpagenko7d6bb022021-03-11 15:07:55 +00001409 oFsm.mutexIsAwaitingResponse.Lock()
1410 oFsm.isAwaitingResponse = false
1411 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001412 return nil
1413 }
mpagenko7d6bb022021-03-11 15:07:55 +00001414 // waiting was aborted (probably on external request)
1415 logger.Debugw(ctx, "uniPonAniConfigFsm wait for multi entity response aborted", log.Fields{"for device-id": oFsm.deviceID})
1416 oFsm.mutexIsAwaitingResponse.Lock()
1417 oFsm.isAwaitingResponse = false
1418 oFsm.mutexIsAwaitingResponse.Unlock()
1419 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001420 }
1421}