blob: 87d520797d7f7b742b01bd11575cf77fddfe9726 [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
mpagenkocf48e452021-04-23 09:23:00 +0000117 isCanceled bool
mpagenko7d6bb022021-03-11 15:07:55 +0000118 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530119 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000120 pAdaptFsm *AdapterFsm
121 chSuccess chan<- uint8
122 procStep uint8
123 chanSet bool
124 mapperSP0ID uint16
125 macBPCD0ID uint16
126 tcont0ID uint16
127 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000128 gemPortAttribsSlice []ponAniGemPortAttribs
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000129 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000130 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000131 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000132 isWaitingForFlowDelete bool
133 waitFlowDeleteChannel chan bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000134}
135
Himani Chawla6d2ae152020-09-02 13:11:20 +0530136//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 +0000137func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800138 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000139 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530140 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000141 pDeviceHandler: apDeviceHandler,
142 deviceID: apDeviceHandler.deviceID,
143 pOmciCC: apDevOmciCC,
144 pOnuUniPort: apUniPort,
145 pUniTechProf: apUniTechProf,
146 pOnuDB: apOnuDB,
147 techProfileID: aTechProfileID,
148 requestEvent: aRequestEvent,
149 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000150 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000151 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000152 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000153
mpagenko01e726e2020-10-23 09:45:29 +0000154 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000155 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000156 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000157 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000158 return nil
159 }
160
161 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000162 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000163 fsm.Events{
164
mpagenko1cc3cb42020-07-27 15:24:38 +0000165 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000166
167 //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 +0000168 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000169 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000170 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
171 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000172 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000173 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000174 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000175 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000176 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000177 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000178 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000179
mpagenko8b07c1b2020-11-26 10:36:31 +0000180 //for removing Gem related resources
181 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800182 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
183 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000184 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
185 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
186
187 //for removing TCONT related resources
188 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
189 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
190 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
191 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
192
193 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
194 aniStRemovingGemIW, aniStRemovingGemNCTP,
195 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000196 {Name: aniEvTimeoutMids, Src: []string{
197 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000198
mpagenko1cc3cb42020-07-27 15:24:38 +0000199 // exceptional treatment for all states except aniStResetting
200 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
201 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000202 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000203 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000204 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000205 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000206 },
207
208 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000209 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
210 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
211 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
212 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
213 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
214 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
215 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
216 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
217 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
218 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
219 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000220 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000221 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
222 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
223 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
224 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
225 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
226 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
227 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000228 },
229 )
230 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000231 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000232 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000233 return nil
234 }
235
dbainbri4d3a0dc2020-12-02 00:33:42 +0000236 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000237 return instFsm
238}
239
Himani Chawla6d2ae152020-09-02 13:11:20 +0530240//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
241func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000242 oFsm.chSuccess = aChSuccess
243 oFsm.procStep = aProcStep
244 oFsm.chanSet = true
245}
246
mpagenko7d6bb022021-03-11 15:07:55 +0000247//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000248func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
249 //early indication about started reset processing
250 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000251 //mutex protection is required for possible concurrent access to FSM members
mpagenkocf48e452021-04-23 09:23:00 +0000252 oFsm.mutexIsAwaitingResponse.Lock()
253 oFsm.isCanceled = true
mpagenko7d6bb022021-03-11 15:07:55 +0000254 if oFsm.isAwaitingResponse {
mpagenkocf48e452021-04-23 09:23:00 +0000255 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
256 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
257 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000258 //use channel to indicate that the response waiting shall be aborted
259 oFsm.omciMIdsResponseReceived <- false
mpagenkocf48e452021-04-23 09:23:00 +0000260 } else {
261 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000262 }
mpagenkocf48e452021-04-23 09:23:00 +0000263
264 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000265 if oFsm.isWaitingForFlowDelete {
mpagenkocf48e452021-04-23 09:23:00 +0000266 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000267 //use channel to indicate that the response waiting shall be aborted
268 oFsm.waitFlowDeleteChannel <- false
mpagenkocf48e452021-04-23 09:23:00 +0000269 } else {
270 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000271 }
mpagenkocf48e452021-04-23 09:23:00 +0000272
mpagenko7d6bb022021-03-11 15:07:55 +0000273 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
274 pAdaptFsm := oFsm.pAdaptFsm
275 if pAdaptFsm != nil {
276 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
277 go func(aPAFsm *AdapterFsm) {
278 if aPAFsm.pFsm != nil {
279 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
280 }
281 }(pAdaptFsm)
282 }
mpagenko73143992021-04-09 15:17:10 +0000283
284 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
285 // access conflicts on internal data by next needed data clearance
286 //activity should be aborted in short time if running with FSM due to above FSM reset
287 // or finished without FSM dependency in short time
288 oFsm.pUniTechProf.lockTpProcMutex()
289 defer oFsm.pUniTechProf.unlockTpProcMutex()
290 //remove all TechProf related internal data to allow for new configuration
291 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000292}
293
dbainbri4d3a0dc2020-12-02 00:33:42 +0000294func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530295 if aPAFsm != nil && aPAFsm.pFsm != nil {
296 //stick to pythonAdapter numbering scheme
297 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800298 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
299 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530300
Girish Gowdra041dcb32020-11-16 16:54:30 -0800301 /*
302 // Find a free TCONT Instance ID and use it
303 foundFreeTcontInstID := false
304 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000305 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800306
307 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
308 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
309 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
310 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
311 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
312 // when the ONU is discovered.
313 /*
314 for _, tcontInstID := range tcontInstKeys {
315 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
316 returnVal := tconInst["AllocId"]
317 if returnVal != nil {
318 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
319 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
320 if allocID == 0xff || allocID == 0xffff {
321 foundFreeTcontInstID = true
322 oFsm.tcont0ID = uint16(tcontInstID)
323 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
324 "device-id": oFsm.deviceID})
325 break
326 }
327 } else {
328 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
329 }
330 } else {
331 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
332 }
333 }
334 */
335
336 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
337 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
338 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
339 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
340 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
341 // TP ID will increment in single digit
342 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000343 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800344 "device-id": oFsm.deviceID})
345 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000346 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 -0800347 if oFsm.chanSet {
348 // indicate processing error/abort to the caller
349 oFsm.chSuccess <- 0
350 oFsm.chanSet = false //reset the internal channel state
351 }
352 //reset the state machine to enable usage on subsequent requests
353 _ = aPAFsm.pFsm.Event(aniEvReset)
354 return
355 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530356 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000357 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800358 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530359 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800360 /*
361 if !foundFreeTcontInstID {
362 // This should never happen. If it does, the behavior is unpredictable.
363 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
364 }*/
365
366 // Access critical state with lock
367 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000368 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
369 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800370 oFsm.pUniTechProf.mutexTPState.Unlock()
371
Himani Chawla26e555c2020-08-31 12:30:20 +0530372 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800373 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300374 loGemPortAttribs := ponAniGemPortAttribs{}
375
Himani Chawla26e555c2020-08-31 12:30:20 +0530376 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
377
dbainbri4d3a0dc2020-12-02 00:33:42 +0000378 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530379
380 loGemPortAttribs.gemPortID = gemEntry.gemPortID
381 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
382 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
383 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
384 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
385
386 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
387 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
388 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
389 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
390 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
391 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
392
393 usQueueFound := false
394 dsQueueFound := false
395 for _, mgmtEntityID := range queueInstKeys {
396 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
397 returnVal := meAttributes["RelatedPort"]
398 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530399 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530400 if relatedPort == usQrelPortMask {
401 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000402 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000403 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530404 usQueueFound = true
405 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
406 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000407 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000408 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530409 dsQueueFound = true
410 }
411 if usQueueFound && dsQueueFound {
412 break
413 }
414 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000415 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530416 }
417 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000418 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530419 }
420 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000421 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000422 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530423 }
424 }
425 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000426 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530427 }
428 loGemPortAttribs.direction = gemEntry.direction
429 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
430 loGemPortAttribs.weight = gemEntry.queueWeight
431 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300432 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300433 //TODO this might effectively ignore the for loop starting at line 316
434 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300435 loGemPortAttribs.isMulticast = true
436 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
437 loGemPortAttribs.staticACL = gemEntry.staticACL
438 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530439
dbainbri4d3a0dc2020-12-02 00:33:42 +0000440 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300441 "gemPortID": loGemPortAttribs.gemPortID,
442 "isMulticast": loGemPortAttribs.isMulticast,
443 "multicastGemID": loGemPortAttribs.multicastGemID,
444 "staticACL": loGemPortAttribs.staticACL,
445 "dynamicACL": loGemPortAttribs.dynamicACL,
446 })
447
448 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000449 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300450 "gemPortID": loGemPortAttribs.gemPortID,
451 "upQueueID": loGemPortAttribs.upQueueID,
452 "downQueueID": loGemPortAttribs.downQueueID,
453 "pbitString": loGemPortAttribs.pbitString,
454 "prioQueueIndex": gemEntry.prioQueueIndex,
455 })
456 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530457
458 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
459 }
460 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
461 }
462}
463
dbainbri4d3a0dc2020-12-02 00:33:42 +0000464func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
465 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000466 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000467 // in case the used channel is not yet defined (can be re-used after restarts)
468 if oFsm.omciMIdsResponseReceived == nil {
469 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000470 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000471 } else {
472 // as we may 're-use' this instance of FSM and the connected channel
473 // make sure there is no 'lingering' request in the already existing channel:
474 // (simple loop sufficient as we are the only receiver)
475 for len(oFsm.omciMIdsResponseReceived) > 0 {
476 <-oFsm.omciMIdsResponseReceived
477 }
478 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000479 //ensure internal slices are empty (which might be set from previous run) - release memory
480 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000481 oFsm.mutexIsAwaitingResponse.Lock()
482 //reset the canceled state possibly existing from previous reset
483 oFsm.isCanceled = false
484 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000485
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000486 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000487 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000488
489 //let the state machine run forward from here directly
490 pConfigAniStateAFsm := oFsm.pAdaptFsm
491 if pConfigAniStateAFsm != nil {
492 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000493 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000494
mpagenko3dbcdd22020-07-22 07:38:45 +0000495 }
496}
497
dbainbri4d3a0dc2020-12-02 00:33:42 +0000498func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
499 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000500 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000501 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
502 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000503 oFsm.mutexPLastTxMeInstance.Lock()
504 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800505 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000506 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
507 //accept also nil as (error) return value for writing to LastTx
508 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000509 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000510}
511
dbainbri4d3a0dc2020-12-02 00:33:42 +0000512func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
513 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000514 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
515 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000516 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000517 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
518 meParams := me.ParamData{
519 EntityID: oFsm.macBPCD0ID,
520 Attributes: me.AttributeValueMap{
521 "BridgeIdPointer": bridgePtr,
522 "PortNum": 0xFF, //fixed unique ANI side indication
523 "TpType": 3, //for .1PMapper
524 "TpPointer": oFsm.mapperSP0ID,
525 },
526 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000527 oFsm.mutexPLastTxMeInstance.Lock()
528 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800529 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000530 oFsm.pAdaptFsm.commChan, meParams)
531 //accept also nil as (error) return value for writing to LastTx
532 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000533 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000534}
535
dbainbri4d3a0dc2020-12-02 00:33:42 +0000536func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
537 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000538 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
539 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000540 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000541 meParams := me.ParamData{
542 EntityID: oFsm.tcont0ID,
543 Attributes: me.AttributeValueMap{
544 "AllocId": oFsm.alloc0ID,
545 },
546 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000547 oFsm.mutexPLastTxMeInstance.Lock()
548 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800549 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000550 oFsm.pAdaptFsm.commChan, meParams)
551 //accept also nil as (error) return value for writing to LastTx
552 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000553 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000554}
555
dbainbri4d3a0dc2020-12-02 00:33:42 +0000556func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
557 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000558 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000559 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000560}
561
dbainbri4d3a0dc2020-12-02 00:33:42 +0000562func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
563 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000564 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000565 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000566}
567
dbainbri4d3a0dc2020-12-02 00:33:42 +0000568func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
569 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000570 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000571 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000572}
573
dbainbri4d3a0dc2020-12-02 00:33:42 +0000574func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300575
dbainbri4d3a0dc2020-12-02 00:33:42 +0000576 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000577 "toGemIw": 1024, /* cmp above */
578 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000579
dbainbri4d3a0dc2020-12-02 00:33:42 +0000580 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000581 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000582 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000583
mpagenko3dbcdd22020-07-22 07:38:45 +0000584 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000585 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530586 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000587 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000588
589 //assign the GemPorts according to the configured Prio
590 var loPrioGemPortArray [8]uint16
591 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300592 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000593 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300594 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
595 "prioString": gemPortAttribs.pbitString})
596 continue
597 }
598 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000599 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300600 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
601 "prioString": gemPortAttribs.pbitString})
602 continue
603 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000604 for i := 0; i < 8; i++ {
605 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
606 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
607 if prio == 1 { // Check this p-bit is set
608 if loPrioGemPortArray[i] == 0 {
609 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
610 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000611 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000612 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000613 "SetGemPort": loPrioGemPortArray[i]})
614 }
615 }
616 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000617 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000618 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000619 "prioString": gemPortAttribs.pbitString, "position": i})
620 }
621
622 }
623 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300624
ozgecanetsia4b232302020-11-11 10:58:10 +0300625 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530626 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300627 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530628 if value != 0 {
629 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530630 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000631 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000632 "for Prio": index,
633 "IwPtr": strconv.FormatInt(int64(value), 16),
634 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300635 } else {
636 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000637 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
638 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300639 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530640 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000641 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300642 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000643 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
644 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300645 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530646
647 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000648 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000649 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300650 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
651 // 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 +0000652 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300653 //pConfigAniStateAFsm := oFsm.pAdaptFsm
654 //if pConfigAniStateAFsm != nil {
655 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
656 // go func(aPAFsm *AdapterFsm) {
657 // if aPAFsm != nil && aPAFsm.pFsm != nil {
658 // _ = aPAFsm.pFsm.Event(aniEvReset)
659 // }
660 // }(pConfigAniStateAFsm)
661 //}
662 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000663 pConfigAniStateAFsm := oFsm.pAdaptFsm
664 if pConfigAniStateAFsm != nil {
665 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530666 go func(aPAFsm *AdapterFsm) {
667 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300668 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000669 }
670 }(pConfigAniStateAFsm)
671 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300672 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000673 oFsm.mutexPLastTxMeInstance.Lock()
674 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800675 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300676 oFsm.pAdaptFsm.commChan, meParams)
677 //accept also nil as (error) return value for writing to LastTx
678 // - this avoids misinterpretation of new received OMCI messages
679 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000680 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000681}
682
dbainbri4d3a0dc2020-12-02 00:33:42 +0000683func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
684 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000685 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000686 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000687 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000688 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800689 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000690 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000691 // but only in case the techProfile was configured (not deleted)
692 if oFsm.requestEventOffset == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000693 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000694 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000695
mpagenko01e726e2020-10-23 09:45:29 +0000696 if oFsm.chanSet {
697 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000698 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000699 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
700 oFsm.chSuccess <- oFsm.procStep
701 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000702 }
mpagenko01e726e2020-10-23 09:45:29 +0000703
704 //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 +0000705}
706
dbainbri4d3a0dc2020-12-02 00:33:42 +0000707func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000708 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000709 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
710 select {
711 case <-oFsm.waitFlowDeleteChannel:
712 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
713 default:
714 }
715 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
mpagenkoa23a6292021-02-23 10:40:10 +0000716 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800717 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
718 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
719 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
720 pConfigAniStateAFsm := oFsm.pAdaptFsm
721 if pConfigAniStateAFsm != nil {
722 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
723 go func(aPAFsm *AdapterFsm) {
724 if aPAFsm != nil && aPAFsm.pFsm != nil {
725 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
726 }
727 }(pConfigAniStateAFsm)
728 } else {
729 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
730 }
731 return
732 }
733
mpagenko8b07c1b2020-11-26 10:36:31 +0000734 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000735 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
736 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000737 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000738 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
739 "GemIwTp-entity-id": loGemPortID})
740 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
741
742 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000743 oFsm.mutexPLastTxMeInstance.Lock()
744 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800745 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000746 oFsm.pAdaptFsm.commChan, loGemPortID)
747 oFsm.pLastTxMeInstance = meInstance
748}
749
mpagenkobb47bc22021-04-20 13:29:09 +0000750func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
751 oFsm.mutexIsAwaitingResponse.Lock()
752 oFsm.isWaitingForFlowDelete = true
753 oFsm.mutexIsAwaitingResponse.Unlock()
754 select {
755 // maybe be also some outside cancel (but no context modeled for the moment ...)
756 // case <-ctx.Done():
757 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
758 case <-time.After(10 * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
759 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
760 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
761 oFsm.mutexIsAwaitingResponse.Lock()
762 oFsm.isWaitingForFlowDelete = false
763 oFsm.mutexIsAwaitingResponse.Unlock()
764 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
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 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
771 }
772 }(pConfigAniStateAFsm)
773 } else {
774 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
775 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
776 }
777 return
778
779 case success := <-oFsm.waitFlowDeleteChannel:
780 if success {
781 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
782 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
783 oFsm.mutexIsAwaitingResponse.Lock()
784 oFsm.isWaitingForFlowDelete = false
785 oFsm.mutexIsAwaitingResponse.Unlock()
786 pConfigAniStateAFsm := oFsm.pAdaptFsm
787 if pConfigAniStateAFsm != nil {
788 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
789 go func(aPAFsm *AdapterFsm) {
790 if aPAFsm != nil && aPAFsm.pFsm != nil {
791 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
792 }
793 }(pConfigAniStateAFsm)
794 } else {
795 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
796 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
797 }
798 return
799 }
800 // waiting was aborted (probably on external request)
801 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
802 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
803 oFsm.mutexIsAwaitingResponse.Lock()
804 oFsm.isWaitingForFlowDelete = false
805 oFsm.mutexIsAwaitingResponse.Unlock()
806 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
807 pConfigAniStateAFsm := oFsm.pAdaptFsm
808 if pConfigAniStateAFsm != nil {
809 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
810 go func(aPAFsm *AdapterFsm) {
811 if aPAFsm != nil && aPAFsm.pFsm != nil {
812 _ = aPAFsm.pFsm.Event(aniEvReset)
813 }
814 }(pConfigAniStateAFsm)
815 }
816 return
817 }
818}
819
dbainbri4d3a0dc2020-12-02 00:33:42 +0000820func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000821 oFsm.pUniTechProf.mutexTPState.Lock()
822 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
823 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000824 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000825 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
826 "GemNCTP-entity-id": loGemPortID})
827 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000828 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800829 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000830 oFsm.pAdaptFsm.commChan, loGemPortID)
831 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000832 oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800833 // Mark the gem port to be removed for Performance History monitoring
834 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
835 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
836 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000837}
838
dbainbri4d3a0dc2020-12-02 00:33:42 +0000839func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
840 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000841 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
842
843 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
844 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
845 meParams := me.ParamData{
846 EntityID: oFsm.tcont0ID,
847 Attributes: me.AttributeValueMap{
848 "AllocId": unusedTcontAllocID,
849 },
850 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000851 oFsm.mutexPLastTxMeInstance.Lock()
852 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800853 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000854 oFsm.pAdaptFsm.commChan, meParams)
855 oFsm.pLastTxMeInstance = meInstance
856}
857
dbainbri4d3a0dc2020-12-02 00:33:42 +0000858func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
859 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000860 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
861
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000862 oFsm.mutexPLastTxMeInstance.Lock()
863 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800864 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000865 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
866 oFsm.pLastTxMeInstance = meInstance
867}
868
dbainbri4d3a0dc2020-12-02 00:33:42 +0000869func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
870 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000871 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
872
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000873 oFsm.mutexPLastTxMeInstance.Lock()
874 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800875 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000876 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
877 oFsm.pLastTxMeInstance = meInstance
878}
879
dbainbri4d3a0dc2020-12-02 00:33:42 +0000880func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
881 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000882 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
883 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000884 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000885 if oFsm.chanSet {
886 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000887 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000888 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
889 oFsm.chSuccess <- oFsm.procStep
890 oFsm.chanSet = false //reset the internal channel state
891 }
892
893 //let's reset the state machine in order to release all resources now
894 pConfigAniStateAFsm := oFsm.pAdaptFsm
895 if pConfigAniStateAFsm != nil {
896 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
897 go func(aPAFsm *AdapterFsm) {
898 if aPAFsm != nil && aPAFsm.pFsm != nil {
899 _ = aPAFsm.pFsm.Event(aniEvReset)
900 }
901 }(pConfigAniStateAFsm)
902 }
903}
904
dbainbri4d3a0dc2020-12-02 00:33:42 +0000905func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
906 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000907 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000908
mpagenko3dbcdd22020-07-22 07:38:45 +0000909 pConfigAniStateAFsm := oFsm.pAdaptFsm
910 if pConfigAniStateAFsm != nil {
911 // abort running message processing
912 fsmAbortMsg := Message{
913 Type: TestMsg,
914 Data: TestMessage{
915 TestMessageVal: AbortMessageProcessing,
916 },
917 }
918 pConfigAniStateAFsm.commChan <- fsmAbortMsg
919
920 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530921 go func(aPAFsm *AdapterFsm) {
922 if aPAFsm != nil && aPAFsm.pFsm != nil {
923 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000924 }
925 }(pConfigAniStateAFsm)
926 }
927}
928
dbainbri4d3a0dc2020-12-02 00:33:42 +0000929func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
930 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000931 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000932 oFsm.mutexPLastTxMeInstance.Lock()
933 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000934 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000935}
936
dbainbri4d3a0dc2020-12-02 00:33:42 +0000937func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
938 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000939loop:
940 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000941 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000942 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000943 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530944 message, ok := <-oFsm.pAdaptFsm.commChan
945 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000946 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530947 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
948 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
949 break loop
950 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000951 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530952
953 switch message.Type {
954 case TestMsg:
955 msg, _ := message.Data.(TestMessage)
956 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000957 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000958 break loop
959 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000960 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530961 case OMCI:
962 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000963 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530964 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000965 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530966 "message.Type": message.Type})
967 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000968
Himani Chawla4d908332020-08-31 12:30:20 +0530969 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000970 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530971}
972
dbainbri4d3a0dc2020-12-02 00:33:42 +0000973func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530974 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
975 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000976 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000977 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530978 return
979 }
980 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
981 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000982 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000983 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530984 return
985 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000986 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000987 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
988 //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 +0000989 oFsm.mutexPLastTxMeInstance.RLock()
990 if oFsm.pLastTxMeInstance != nil {
991 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
992 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
993 // maybe we can use just the same eventName for different state transitions like "forward"
994 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
995 switch oFsm.pLastTxMeInstance.GetName() {
996 case "Ieee8021PMapperServiceProfile":
997 { // let the FSM proceed ...
998 oFsm.mutexPLastTxMeInstance.RUnlock()
999 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1000 }
1001 case "MacBridgePortConfigurationData":
1002 { // let the FSM proceed ...
1003 oFsm.mutexPLastTxMeInstance.RUnlock()
1004 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1005 }
1006 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1007 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1008 oFsm.mutexPLastTxMeInstance.RUnlock()
1009 oFsm.omciMIdsResponseReceived <- true
1010 }
1011 default:
1012 {
1013 oFsm.mutexPLastTxMeInstance.RUnlock()
1014 logger.Warnw(ctx, "Unsupported ME name received!",
1015 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1016 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001017 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001018 } else {
1019 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001020 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001021 } else {
1022 oFsm.mutexPLastTxMeInstance.RUnlock()
1023 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001024 }
1025 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001026 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1027 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301028 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1029 return
1030 }
Himani Chawla4d908332020-08-31 12:30:20 +05301031}
1032
dbainbri4d3a0dc2020-12-02 00:33:42 +00001033func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301034 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1035 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001036 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001037 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301038 return
1039 }
1040 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1041 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001042 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001043 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301044 return
1045 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001046 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301047 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001048 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001049 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301050 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1051 return
1052 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001053 oFsm.mutexPLastTxMeInstance.RLock()
1054 if oFsm.pLastTxMeInstance != nil {
1055 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1056 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1057 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1058 // if, then something like:
1059 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301060
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001061 switch oFsm.pLastTxMeInstance.GetName() {
1062 case "TCont":
1063 { // let the FSM proceed ...
1064 oFsm.mutexPLastTxMeInstance.RUnlock()
1065 if oFsm.requestEventOffset == 0 { //from TCont config request
1066 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1067 } else { // from T-Cont reset request
1068 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1069 }
1070 }
1071 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1072 { // let the PrioQueue init proceed by stopping the wait function
1073 oFsm.mutexPLastTxMeInstance.RUnlock()
1074 oFsm.omciMIdsResponseReceived <- true
1075 }
1076 case "Ieee8021PMapperServiceProfile":
1077 { // let the FSM proceed ...
1078 oFsm.mutexPLastTxMeInstance.RUnlock()
1079 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1080 }
1081 default:
1082 {
1083 oFsm.mutexPLastTxMeInstance.RUnlock()
1084 logger.Warnw(ctx, "Unsupported ME name received!",
1085 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001086 }
Himani Chawla4d908332020-08-31 12:30:20 +05301087 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001088 } else {
1089 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301090 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001091 } else {
1092 oFsm.mutexPLastTxMeInstance.RUnlock()
1093 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301094 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001095}
1096
dbainbri4d3a0dc2020-12-02 00:33:42 +00001097func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001098 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1099 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001100 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001101 log.Fields{"device-id": oFsm.deviceID})
1102 return
1103 }
1104 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1105 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001106 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001107 log.Fields{"device-id": oFsm.deviceID})
1108 return
1109 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001110 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001111 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001112 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001113 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1114 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1115 // store error for mgmt display?
1116 return
1117 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001118 oFsm.mutexPLastTxMeInstance.RLock()
1119 if oFsm.pLastTxMeInstance != nil {
1120 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1121 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1122 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1123 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001124
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001125 switch oFsm.pLastTxMeInstance.GetName() {
1126 case "GemInterworkingTerminationPoint":
1127 { // let the FSM proceed ...
1128 oFsm.mutexPLastTxMeInstance.RUnlock()
1129 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1130 }
1131 case "GemPortNetworkCtp":
1132 { // let the FSM proceed ...
1133 oFsm.mutexPLastTxMeInstance.RUnlock()
1134 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1135 }
1136 case "Ieee8021PMapperServiceProfile":
1137 { // let the FSM proceed ...
1138 oFsm.mutexPLastTxMeInstance.RUnlock()
1139 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1140 }
1141 case "MacBridgePortConfigurationData":
1142 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1143 oFsm.mutexPLastTxMeInstance.RUnlock()
1144 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1145 }
1146 default:
1147 {
1148 oFsm.mutexPLastTxMeInstance.RUnlock()
1149 logger.Warnw(ctx, "Unsupported ME name received!",
1150 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1151 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001152 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001153 } else {
1154 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001155 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001156 } else {
1157 oFsm.mutexPLastTxMeInstance.RUnlock()
1158 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001159 }
1160}
1161
dbainbri4d3a0dc2020-12-02 00:33:42 +00001162func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1163 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001164 "msgType": msg.OmciMsg.MessageType})
1165
1166 switch msg.OmciMsg.MessageType {
1167 case omci.CreateResponseType:
1168 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001169 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301170
mpagenko3dbcdd22020-07-22 07:38:45 +00001171 } //CreateResponseType
1172 case omci.SetResponseType:
1173 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001174 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001175
mpagenko3dbcdd22020-07-22 07:38:45 +00001176 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001177 case omci.DeleteResponseType:
1178 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001179 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001180
1181 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001182 default:
1183 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001184 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001185 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001186 return
1187 }
1188 }
1189}
1190
dbainbri4d3a0dc2020-12-02 00:33:42 +00001191func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001192 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1193 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001194 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001195 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1196 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001197 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001198 meParams := me.ParamData{
1199 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1200 Attributes: me.AttributeValueMap{
1201 "PortId": gemPortAttribs.gemPortID,
1202 "TContPointer": oFsm.tcont0ID,
1203 "Direction": gemPortAttribs.direction,
1204 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1205 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1206 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1207 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1208 },
1209 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001210 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001211 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001212 oFsm.pAdaptFsm.commChan, meParams)
1213 //accept also nil as (error) return value for writing to LastTx
1214 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001215 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001216 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001217
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001218 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001219 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001220 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001221 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001222 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301223 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001224 return
1225 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001226 // Mark the gem port to be removed for Performance History monitoring
1227 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
1228 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(gemPortAttribs.gemPortID)
1229 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001230 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001231
1232 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001233 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301234 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001235}
1236
dbainbri4d3a0dc2020-12-02 00:33:42 +00001237func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001238 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1239 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001240 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001241 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1242 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001243 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001244
ozgecanetsia4b232302020-11-11 10:58:10 +03001245 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1246 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001247
1248 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001249 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001250 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001251 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001252 "InterworkingOption": 0, // Don't Care
1253 "ServiceProfilePointer": 0, // Don't Care
1254 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001255 },
1256 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001257 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001258 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001259 true, oFsm.pAdaptFsm.commChan, meParams)
1260 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001261 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001262 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001263 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001264 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001265 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001266 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1267 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1268 return
1269 }
1270 ipv4MulticastTable := make([]uint8, 12)
1271 //Gem Port ID
1272 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1273 //Secondary Key
1274 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1275 // Multicast IP range start This is the 224.0.0.1 address
1276 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1277 // MulticastIp range stop
1278 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1279
1280 meIPV4MCTableParams := me.ParamData{
1281 EntityID: gemPortAttribs.multicastGemID,
1282 Attributes: me.AttributeValueMap{
1283 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1284 },
1285 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001286 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001287 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001288 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1289 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001290 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001291
1292 } else {
1293 meParams := me.ParamData{
1294 EntityID: gemPortAttribs.gemPortID,
1295 Attributes: me.AttributeValueMap{
1296 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1297 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1298 "ServiceProfilePointer": oFsm.mapperSP0ID,
1299 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1300 "GalProfilePointer": galEthernetEID,
1301 },
1302 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001303 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001304 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001305 oFsm.pAdaptFsm.commChan, meParams)
1306 //accept also nil as (error) return value for writing to LastTx
1307 // - this avoids misinterpretation of new received OMCI messages
1308 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001309 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001310 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001311 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001312 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001313 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001314 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001315 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301316 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001317 return
1318 }
1319 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001320
1321 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001322 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301323 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001324}
1325
dbainbri4d3a0dc2020-12-02 00:33:42 +00001326func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001327 const cu16StrictPrioWeight uint16 = 0xFFFF
1328 //find all upstream PrioQueues related to this T-Cont
1329 loQueueMap := ordered_map.NewOrderedMap()
1330 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001331 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001332 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001333 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1334 "prioString": gemPortAttribs.pbitString})
1335 continue
1336 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001337 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301338 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001339 //key does not yet exist
1340 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1341 }
1342 } else {
1343 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1344 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001345 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001346
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001347 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1348 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1349 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1350 // or even be finished without correct SP/WRR setting
1351
1352 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1353 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1354 // even though its T-Cont seems to be wrong ...
1355 loTrafficSchedulerEID := 0x8000
1356 //for all found queues
1357 iter := loQueueMap.IterFunc()
1358 for kv, ok := iter(); ok; kv, ok = iter() {
1359 queueIndex := (kv.Key).(uint16)
1360 meParams := me.ParamData{
1361 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301362 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001363 }
1364 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1365 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001366 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001367 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001368 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001369 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1370 } else {
1371 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001372 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001373 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1374 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001375 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001376 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1377 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1378 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001379 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001380 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001381 oFsm.pAdaptFsm.commChan, meParams)
1382 //accept also nil as (error) return value for writing to LastTx
1383 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001384 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001385 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001386
1387 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001388 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001389 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001390 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001391 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301392 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001393 return
1394 }
1395
1396 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1397 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1398 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1399 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1400
1401 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001402
1403 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001404 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301405 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001406}
1407
dbainbri4d3a0dc2020-12-02 00:33:42 +00001408func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001409 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001410 if oFsm.isCanceled {
1411 // FSM already canceled before entering wait
1412 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1413 oFsm.mutexIsAwaitingResponse.Unlock()
1414 return fmt.Errorf(cErrWaitAborted)
1415 }
mpagenko7d6bb022021-03-11 15:07:55 +00001416 oFsm.isAwaitingResponse = true
1417 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001418 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301419 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001420 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001421 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001422 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 +00001423 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001424 oFsm.mutexIsAwaitingResponse.Lock()
1425 oFsm.isAwaitingResponse = false
1426 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001427 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001428 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301429 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001430 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001431 oFsm.mutexIsAwaitingResponse.Lock()
1432 oFsm.isAwaitingResponse = false
1433 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001434 return nil
1435 }
mpagenko7d6bb022021-03-11 15:07:55 +00001436 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001437 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001438 oFsm.mutexIsAwaitingResponse.Lock()
1439 oFsm.isAwaitingResponse = false
1440 oFsm.mutexIsAwaitingResponse.Unlock()
1441 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001442 }
1443}