blob: 296977d3858bf69d2191d54e3de8fc3be55a7b8f [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"
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +000063 aniEvSkipOmciConfig = "aniEvSkipOmciConfig"
mpagenko1cc3cb42020-07-27 15:24:38 +000064)
65const (
66 // states of config PON ANI port FSM
67 aniStDisabled = "aniStDisabled"
68 aniStStarting = "aniStStarting"
69 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
70 aniStCreatingMBPCD = "aniStCreatingMBPCD"
71 aniStSettingTconts = "aniStSettingTconts"
72 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
73 aniStCreatingGemIWs = "aniStCreatingGemIWs"
74 aniStSettingPQs = "aniStSettingPQs"
75 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
76 aniStConfigDone = "aniStConfigDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000077 aniStRemovingGemIW = "aniStRemovingGemIW"
Girish Gowdra26a40922021-01-29 17:14:34 -080078 aniStWaitingFlowRem = "aniStWaitingFlowRem"
mpagenko8b07c1b2020-11-26 10:36:31 +000079 aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
80 aniStResetTcont = "aniStResetTcont"
81 aniStRemDot1PMapper = "aniStRemDot1PMapper"
82 aniStRemAniBPCD = "aniStRemAniBPCD"
83 aniStRemoveDone = "aniStRemoveDone"
mpagenko1cc3cb42020-07-27 15:24:38 +000084 aniStResetting = "aniStResetting"
85)
Holger Hildebrandt10d98192021-01-27 15:29:31 +000086const cAniFsmIdleState = aniStConfigDone
mpagenko1cc3cb42020-07-27 15:24:38 +000087
Girish Gowdra041dcb32020-11-16 16:54:30 -080088const (
89 tpIDOffset = 64
90)
91
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000092type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030093 gemPortID uint16
94 upQueueID uint16
95 downQueueID uint16
96 direction uint8
97 qosPolicy string
98 weight uint8
99 pbitString string
100 isMulticast bool
101 multicastGemID uint16
102 staticACL string
103 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000104}
105
Himani Chawla6d2ae152020-09-02 13:11:20 +0530106//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
107type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000108 pDeviceHandler *deviceHandler
109 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530110 pOmciCC *omciCC
111 pOnuUniPort *onuUniPort
112 pUniTechProf *onuUniTechProf
113 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800114 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000115 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000116 requestEvent OnuDeviceEvent
mpagenko7d6bb022021-03-11 15:07:55 +0000117 mutexIsAwaitingResponse sync.RWMutex
mpagenkocf48e452021-04-23 09:23:00 +0000118 isCanceled bool
mpagenko7d6bb022021-03-11 15:07:55 +0000119 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530120 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000121 pAdaptFsm *AdapterFsm
122 chSuccess chan<- uint8
123 procStep uint8
124 chanSet bool
125 mapperSP0ID uint16
126 macBPCD0ID uint16
127 tcont0ID uint16
128 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000129 gemPortAttribsSlice []ponAniGemPortAttribs
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000130 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000131 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000132 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000133 isWaitingForFlowDelete bool
134 waitFlowDeleteChannel chan bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000135}
136
Himani Chawla6d2ae152020-09-02 13:11:20 +0530137//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 +0000138func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800139 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000140 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530141 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000142 pDeviceHandler: apDeviceHandler,
143 deviceID: apDeviceHandler.deviceID,
144 pOmciCC: apDevOmciCC,
145 pOnuUniPort: apUniPort,
146 pUniTechProf: apUniTechProf,
147 pOnuDB: apOnuDB,
148 techProfileID: aTechProfileID,
149 requestEvent: aRequestEvent,
150 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000151 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000152 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000153 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000154
mpagenko01e726e2020-10-23 09:45:29 +0000155 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000156 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000157 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000158 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000159 return nil
160 }
161
162 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000163 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000164 fsm.Events{
165
mpagenko1cc3cb42020-07-27 15:24:38 +0000166 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000167
168 //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 +0000169 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000170 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000171 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
172 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000173 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000174 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000175 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000176 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000177 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000178 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000179 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000180
mpagenko8b07c1b2020-11-26 10:36:31 +0000181 //for removing Gem related resources
182 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800183 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
184 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000185 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
186 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
187
188 //for removing TCONT related resources
189 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
190 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
191 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
192 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
193
194 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
195 aniStRemovingGemIW, aniStRemovingGemNCTP,
196 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000197 {Name: aniEvTimeoutMids, Src: []string{
198 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000199
mpagenko1cc3cb42020-07-27 15:24:38 +0000200 // exceptional treatment for all states except aniStResetting
201 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
202 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000203 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000204 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000205 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000206 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000207 {Name: aniEvSkipOmciConfig, Src: []string{aniStStarting}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000208 },
209
210 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000211 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
212 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
213 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
214 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
215 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
216 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
217 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
218 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
219 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
220 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
221 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000222 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000223 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
224 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
225 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
226 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
227 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
228 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
229 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000230 },
231 )
232 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000233 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000234 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000235 return nil
236 }
237
dbainbri4d3a0dc2020-12-02 00:33:42 +0000238 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000239 return instFsm
240}
241
Himani Chawla6d2ae152020-09-02 13:11:20 +0530242//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
243func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000244 oFsm.chSuccess = aChSuccess
245 oFsm.procStep = aProcStep
246 oFsm.chanSet = true
247}
248
mpagenko7d6bb022021-03-11 15:07:55 +0000249//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000250func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
251 //early indication about started reset processing
252 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000253 //mutex protection is required for possible concurrent access to FSM members
mpagenkocf48e452021-04-23 09:23:00 +0000254 oFsm.mutexIsAwaitingResponse.Lock()
255 oFsm.isCanceled = true
mpagenko7d6bb022021-03-11 15:07:55 +0000256 if oFsm.isAwaitingResponse {
mpagenkocf48e452021-04-23 09:23:00 +0000257 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
258 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
259 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000260 //use channel to indicate that the response waiting shall be aborted
261 oFsm.omciMIdsResponseReceived <- false
mpagenkocf48e452021-04-23 09:23:00 +0000262 } else {
263 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000264 }
mpagenkocf48e452021-04-23 09:23:00 +0000265
266 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000267 if oFsm.isWaitingForFlowDelete {
mpagenkocf48e452021-04-23 09:23:00 +0000268 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000269 //use channel to indicate that the response waiting shall be aborted
270 oFsm.waitFlowDeleteChannel <- false
mpagenkocf48e452021-04-23 09:23:00 +0000271 } else {
272 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000273 }
mpagenkocf48e452021-04-23 09:23:00 +0000274
mpagenko7d6bb022021-03-11 15:07:55 +0000275 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
276 pAdaptFsm := oFsm.pAdaptFsm
277 if pAdaptFsm != nil {
278 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
279 go func(aPAFsm *AdapterFsm) {
280 if aPAFsm.pFsm != nil {
281 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
282 }
283 }(pAdaptFsm)
284 }
mpagenko73143992021-04-09 15:17:10 +0000285
286 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
287 // access conflicts on internal data by next needed data clearance
288 //activity should be aborted in short time if running with FSM due to above FSM reset
289 // or finished without FSM dependency in short time
290 oFsm.pUniTechProf.lockTpProcMutex()
291 defer oFsm.pUniTechProf.unlockTpProcMutex()
292 //remove all TechProf related internal data to allow for new configuration
293 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000294}
295
dbainbri4d3a0dc2020-12-02 00:33:42 +0000296func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530297 if aPAFsm != nil && aPAFsm.pFsm != nil {
298 //stick to pythonAdapter numbering scheme
299 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800300 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
301 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530302
Girish Gowdra041dcb32020-11-16 16:54:30 -0800303 /*
304 // Find a free TCONT Instance ID and use it
305 foundFreeTcontInstID := false
306 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000307 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800308
309 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
310 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
311 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
312 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
313 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
314 // when the ONU is discovered.
315 /*
316 for _, tcontInstID := range tcontInstKeys {
317 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
318 returnVal := tconInst["AllocId"]
319 if returnVal != nil {
320 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
321 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
322 if allocID == 0xff || allocID == 0xffff {
323 foundFreeTcontInstID = true
324 oFsm.tcont0ID = uint16(tcontInstID)
325 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
326 "device-id": oFsm.deviceID})
327 break
328 }
329 } else {
330 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
331 }
332 } else {
333 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
334 }
335 }
336 */
337
338 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
339 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
340 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
341 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
342 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
343 // TP ID will increment in single digit
344 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000345 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800346 "device-id": oFsm.deviceID})
347 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000348 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 -0800349 if oFsm.chanSet {
350 // indicate processing error/abort to the caller
351 oFsm.chSuccess <- 0
352 oFsm.chanSet = false //reset the internal channel state
353 }
354 //reset the state machine to enable usage on subsequent requests
355 _ = aPAFsm.pFsm.Event(aniEvReset)
356 return
357 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530358 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000359 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800360 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530361 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800362 /*
363 if !foundFreeTcontInstID {
364 // This should never happen. If it does, the behavior is unpredictable.
365 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
366 }*/
367
368 // Access critical state with lock
369 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000370 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
371 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800372 oFsm.pUniTechProf.mutexTPState.Unlock()
373
Himani Chawla26e555c2020-08-31 12:30:20 +0530374 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800375 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300376 loGemPortAttribs := ponAniGemPortAttribs{}
377
Himani Chawla26e555c2020-08-31 12:30:20 +0530378 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
379
dbainbri4d3a0dc2020-12-02 00:33:42 +0000380 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530381
382 loGemPortAttribs.gemPortID = gemEntry.gemPortID
383 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
384 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
385 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
386 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
387
388 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
389 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
390 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
391 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
392 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
393 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
394
395 usQueueFound := false
396 dsQueueFound := false
397 for _, mgmtEntityID := range queueInstKeys {
398 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
399 returnVal := meAttributes["RelatedPort"]
400 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530401 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530402 if relatedPort == usQrelPortMask {
403 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000404 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000405 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530406 usQueueFound = true
407 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
408 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000409 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000410 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530411 dsQueueFound = true
412 }
413 if usQueueFound && dsQueueFound {
414 break
415 }
416 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000417 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530418 }
419 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000420 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530421 }
422 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000423 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000424 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530425 }
426 }
427 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000428 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530429 }
430 loGemPortAttribs.direction = gemEntry.direction
431 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
432 loGemPortAttribs.weight = gemEntry.queueWeight
433 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300434 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300435 //TODO this might effectively ignore the for loop starting at line 316
436 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300437 loGemPortAttribs.isMulticast = true
438 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
439 loGemPortAttribs.staticACL = gemEntry.staticACL
440 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530441
dbainbri4d3a0dc2020-12-02 00:33:42 +0000442 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300443 "gemPortID": loGemPortAttribs.gemPortID,
444 "isMulticast": loGemPortAttribs.isMulticast,
445 "multicastGemID": loGemPortAttribs.multicastGemID,
446 "staticACL": loGemPortAttribs.staticACL,
447 "dynamicACL": loGemPortAttribs.dynamicACL,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000448 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300449 })
450
451 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000452 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300453 "gemPortID": loGemPortAttribs.gemPortID,
454 "upQueueID": loGemPortAttribs.upQueueID,
455 "downQueueID": loGemPortAttribs.downQueueID,
456 "pbitString": loGemPortAttribs.pbitString,
457 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000458 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300459 })
460 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530461
462 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
463 }
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000464 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
465 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
466 } else {
467 logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"device-id": oFsm.deviceID})
468 _ = aPAFsm.pFsm.Event(aniEvSkipOmciConfig)
469 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530470 }
471}
472
dbainbri4d3a0dc2020-12-02 00:33:42 +0000473func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
474 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000475 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000476 // in case the used channel is not yet defined (can be re-used after restarts)
477 if oFsm.omciMIdsResponseReceived == nil {
478 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000479 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000480 } else {
481 // as we may 're-use' this instance of FSM and the connected channel
482 // make sure there is no 'lingering' request in the already existing channel:
483 // (simple loop sufficient as we are the only receiver)
484 for len(oFsm.omciMIdsResponseReceived) > 0 {
485 <-oFsm.omciMIdsResponseReceived
486 }
487 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000488 //ensure internal slices are empty (which might be set from previous run) - release memory
489 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000490 oFsm.mutexIsAwaitingResponse.Lock()
491 //reset the canceled state possibly existing from previous reset
492 oFsm.isCanceled = false
493 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000494
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000495 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000496 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000497
498 //let the state machine run forward from here directly
499 pConfigAniStateAFsm := oFsm.pAdaptFsm
500 if pConfigAniStateAFsm != nil {
501 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000502 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000503
mpagenko3dbcdd22020-07-22 07:38:45 +0000504 }
505}
506
dbainbri4d3a0dc2020-12-02 00:33:42 +0000507func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
508 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000509 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000510 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
511 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000512 oFsm.mutexPLastTxMeInstance.Lock()
513 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800514 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000515 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
516 //accept also nil as (error) return value for writing to LastTx
517 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000518 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000519}
520
dbainbri4d3a0dc2020-12-02 00:33:42 +0000521func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
522 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000523 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
524 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000525 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000526 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
527 meParams := me.ParamData{
528 EntityID: oFsm.macBPCD0ID,
529 Attributes: me.AttributeValueMap{
530 "BridgeIdPointer": bridgePtr,
531 "PortNum": 0xFF, //fixed unique ANI side indication
532 "TpType": 3, //for .1PMapper
533 "TpPointer": oFsm.mapperSP0ID,
534 },
535 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000536 oFsm.mutexPLastTxMeInstance.Lock()
537 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800538 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000539 oFsm.pAdaptFsm.commChan, meParams)
540 //accept also nil as (error) return value for writing to LastTx
541 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000542 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000543}
544
dbainbri4d3a0dc2020-12-02 00:33:42 +0000545func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
546 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000547 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
548 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000549 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000550 meParams := me.ParamData{
551 EntityID: oFsm.tcont0ID,
552 Attributes: me.AttributeValueMap{
553 "AllocId": oFsm.alloc0ID,
554 },
555 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000556 oFsm.mutexPLastTxMeInstance.Lock()
557 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800558 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000559 oFsm.pAdaptFsm.commChan, meParams)
560 //accept also nil as (error) return value for writing to LastTx
561 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000562 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000563}
564
dbainbri4d3a0dc2020-12-02 00:33:42 +0000565func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
566 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000567 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000568 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000569}
570
dbainbri4d3a0dc2020-12-02 00:33:42 +0000571func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
572 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000573 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000574 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000575}
576
dbainbri4d3a0dc2020-12-02 00:33:42 +0000577func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
578 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000579 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000580 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000581}
582
dbainbri4d3a0dc2020-12-02 00:33:42 +0000583func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300584
dbainbri4d3a0dc2020-12-02 00:33:42 +0000585 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000586 "toGemIw": 1024, /* cmp above */
587 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000588
dbainbri4d3a0dc2020-12-02 00:33:42 +0000589 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000590 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000591 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000592
mpagenko3dbcdd22020-07-22 07:38:45 +0000593 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000594 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530595 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000596 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000597
598 //assign the GemPorts according to the configured Prio
599 var loPrioGemPortArray [8]uint16
600 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300601 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000602 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300603 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
604 "prioString": gemPortAttribs.pbitString})
605 continue
606 }
607 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000608 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300609 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
610 "prioString": gemPortAttribs.pbitString})
611 continue
612 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000613 for i := 0; i < 8; i++ {
614 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
615 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
616 if prio == 1 { // Check this p-bit is set
617 if loPrioGemPortArray[i] == 0 {
618 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
619 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000620 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000621 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000622 "SetGemPort": loPrioGemPortArray[i]})
623 }
624 }
625 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000626 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000627 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000628 "prioString": gemPortAttribs.pbitString, "position": i})
629 }
630
631 }
632 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300633
ozgecanetsia4b232302020-11-11 10:58:10 +0300634 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530635 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300636 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530637 if value != 0 {
638 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530639 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000640 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000641 "for Prio": index,
642 "IwPtr": strconv.FormatInt(int64(value), 16),
643 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300644 } else {
645 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000646 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
647 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300648 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530649 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000650 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300651 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000652 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
653 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300654 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530655
656 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000657 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000658 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300659 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
660 // 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 +0000661 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300662 //pConfigAniStateAFsm := oFsm.pAdaptFsm
663 //if pConfigAniStateAFsm != nil {
664 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
665 // go func(aPAFsm *AdapterFsm) {
666 // if aPAFsm != nil && aPAFsm.pFsm != nil {
667 // _ = aPAFsm.pFsm.Event(aniEvReset)
668 // }
669 // }(pConfigAniStateAFsm)
670 //}
671 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000672 pConfigAniStateAFsm := oFsm.pAdaptFsm
673 if pConfigAniStateAFsm != nil {
674 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530675 go func(aPAFsm *AdapterFsm) {
676 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300677 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000678 }
679 }(pConfigAniStateAFsm)
680 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300681 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000682 oFsm.mutexPLastTxMeInstance.Lock()
683 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800684 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300685 oFsm.pAdaptFsm.commChan, meParams)
686 //accept also nil as (error) return value for writing to LastTx
687 // - this avoids misinterpretation of new received OMCI messages
688 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000689 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000690}
691
dbainbri4d3a0dc2020-12-02 00:33:42 +0000692func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
693 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000694 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000695 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800696 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000697 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
698 //use DeviceHandler event notification directly
699 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
700 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
701 // but only in case the techProfile was configured (not deleted)
702 if oFsm.requestEventOffset == 0 {
703 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
704 }
705 } else {
706 logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000707 }
mpagenko01e726e2020-10-23 09:45:29 +0000708 if oFsm.chanSet {
709 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000710 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000711 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
712 oFsm.chSuccess <- oFsm.procStep
713 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000714 }
mpagenko01e726e2020-10-23 09:45:29 +0000715
716 //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 +0000717}
718
dbainbri4d3a0dc2020-12-02 00:33:42 +0000719func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000720 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000721 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
722 select {
723 case <-oFsm.waitFlowDeleteChannel:
724 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
725 default:
726 }
727 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
mpagenkoa23a6292021-02-23 10:40:10 +0000728 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800729 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
730 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
731 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
732 pConfigAniStateAFsm := oFsm.pAdaptFsm
733 if pConfigAniStateAFsm != nil {
734 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
735 go func(aPAFsm *AdapterFsm) {
736 if aPAFsm != nil && aPAFsm.pFsm != nil {
737 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
738 }
739 }(pConfigAniStateAFsm)
740 } else {
741 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
742 }
743 return
744 }
745
mpagenko8b07c1b2020-11-26 10:36:31 +0000746 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000747 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
748 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000749 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000750 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
751 "GemIwTp-entity-id": loGemPortID})
752 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
753
754 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000755 oFsm.mutexPLastTxMeInstance.Lock()
756 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800757 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000758 oFsm.pAdaptFsm.commChan, loGemPortID)
759 oFsm.pLastTxMeInstance = meInstance
760}
761
mpagenkobb47bc22021-04-20 13:29:09 +0000762func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
763 oFsm.mutexIsAwaitingResponse.Lock()
764 oFsm.isWaitingForFlowDelete = true
765 oFsm.mutexIsAwaitingResponse.Unlock()
766 select {
767 // maybe be also some outside cancel (but no context modeled for the moment ...)
768 // case <-ctx.Done():
769 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
770 case <-time.After(10 * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
771 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
772 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
773 oFsm.mutexIsAwaitingResponse.Lock()
774 oFsm.isWaitingForFlowDelete = false
775 oFsm.mutexIsAwaitingResponse.Unlock()
776 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
777 pConfigAniStateAFsm := oFsm.pAdaptFsm
778 if pConfigAniStateAFsm != nil {
779 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
780 go func(aPAFsm *AdapterFsm) {
781 if aPAFsm != nil && aPAFsm.pFsm != nil {
782 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
783 }
784 }(pConfigAniStateAFsm)
785 } else {
786 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
787 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
788 }
789 return
790
791 case success := <-oFsm.waitFlowDeleteChannel:
792 if success {
793 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
794 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
795 oFsm.mutexIsAwaitingResponse.Lock()
796 oFsm.isWaitingForFlowDelete = false
797 oFsm.mutexIsAwaitingResponse.Unlock()
798 pConfigAniStateAFsm := oFsm.pAdaptFsm
799 if pConfigAniStateAFsm != nil {
800 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
801 go func(aPAFsm *AdapterFsm) {
802 if aPAFsm != nil && aPAFsm.pFsm != nil {
803 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
804 }
805 }(pConfigAniStateAFsm)
806 } else {
807 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
808 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
809 }
810 return
811 }
812 // waiting was aborted (probably on external request)
813 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
814 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
815 oFsm.mutexIsAwaitingResponse.Lock()
816 oFsm.isWaitingForFlowDelete = false
817 oFsm.mutexIsAwaitingResponse.Unlock()
818 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
819 pConfigAniStateAFsm := oFsm.pAdaptFsm
820 if pConfigAniStateAFsm != nil {
821 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
822 go func(aPAFsm *AdapterFsm) {
823 if aPAFsm != nil && aPAFsm.pFsm != nil {
824 _ = aPAFsm.pFsm.Event(aniEvReset)
825 }
826 }(pConfigAniStateAFsm)
827 }
828 return
829 }
830}
831
dbainbri4d3a0dc2020-12-02 00:33:42 +0000832func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000833 oFsm.pUniTechProf.mutexTPState.Lock()
834 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
835 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000836 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000837 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
838 "GemNCTP-entity-id": loGemPortID})
839 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000840 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800841 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000842 oFsm.pAdaptFsm.commChan, loGemPortID)
843 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000844 oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800845 // Mark the gem port to be removed for Performance History monitoring
846 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700847 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800848 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000849}
850
dbainbri4d3a0dc2020-12-02 00:33:42 +0000851func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
852 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000853 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
854
855 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
856 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
857 meParams := me.ParamData{
858 EntityID: oFsm.tcont0ID,
859 Attributes: me.AttributeValueMap{
860 "AllocId": unusedTcontAllocID,
861 },
862 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000863 oFsm.mutexPLastTxMeInstance.Lock()
864 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800865 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000866 oFsm.pAdaptFsm.commChan, meParams)
867 oFsm.pLastTxMeInstance = meInstance
868}
869
dbainbri4d3a0dc2020-12-02 00:33:42 +0000870func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
871 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000872 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
873
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000874 oFsm.mutexPLastTxMeInstance.Lock()
875 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800876 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000877 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
878 oFsm.pLastTxMeInstance = meInstance
879}
880
dbainbri4d3a0dc2020-12-02 00:33:42 +0000881func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
882 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000883 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
884
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000885 oFsm.mutexPLastTxMeInstance.Lock()
886 defer oFsm.mutexPLastTxMeInstance.Unlock()
Girish Gowdra0b235842021-03-09 13:06:46 -0800887 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000888 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
889 oFsm.pLastTxMeInstance = meInstance
890}
891
dbainbri4d3a0dc2020-12-02 00:33:42 +0000892func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
893 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000894 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
895 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000896 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000897 if oFsm.chanSet {
898 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000899 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000900 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
901 oFsm.chSuccess <- oFsm.procStep
902 oFsm.chanSet = false //reset the internal channel state
903 }
904
905 //let's reset the state machine in order to release all resources now
906 pConfigAniStateAFsm := oFsm.pAdaptFsm
907 if pConfigAniStateAFsm != nil {
908 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
909 go func(aPAFsm *AdapterFsm) {
910 if aPAFsm != nil && aPAFsm.pFsm != nil {
911 _ = aPAFsm.pFsm.Event(aniEvReset)
912 }
913 }(pConfigAniStateAFsm)
914 }
915}
916
dbainbri4d3a0dc2020-12-02 00:33:42 +0000917func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
918 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000919 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000920
mpagenko3dbcdd22020-07-22 07:38:45 +0000921 pConfigAniStateAFsm := oFsm.pAdaptFsm
922 if pConfigAniStateAFsm != nil {
923 // abort running message processing
924 fsmAbortMsg := Message{
925 Type: TestMsg,
926 Data: TestMessage{
927 TestMessageVal: AbortMessageProcessing,
928 },
929 }
930 pConfigAniStateAFsm.commChan <- fsmAbortMsg
931
932 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530933 go func(aPAFsm *AdapterFsm) {
934 if aPAFsm != nil && aPAFsm.pFsm != nil {
935 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000936 }
937 }(pConfigAniStateAFsm)
938 }
939}
940
dbainbri4d3a0dc2020-12-02 00:33:42 +0000941func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
942 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000943 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000944 oFsm.mutexPLastTxMeInstance.Lock()
945 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000946 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000947}
948
dbainbri4d3a0dc2020-12-02 00:33:42 +0000949func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
950 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000951loop:
952 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000953 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000954 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000955 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530956 message, ok := <-oFsm.pAdaptFsm.commChan
957 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000958 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530959 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
960 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
961 break loop
962 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000963 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530964
965 switch message.Type {
966 case TestMsg:
967 msg, _ := message.Data.(TestMessage)
968 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000969 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000970 break loop
971 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000972 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530973 case OMCI:
974 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000975 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530976 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000977 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530978 "message.Type": message.Type})
979 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000980
Himani Chawla4d908332020-08-31 12:30:20 +0530981 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000982 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530983}
984
dbainbri4d3a0dc2020-12-02 00:33:42 +0000985func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530986 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
987 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000988 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000989 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530990 return
991 }
992 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
993 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000994 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000995 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530996 return
997 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000998 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000999 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1000 //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 +00001001 oFsm.mutexPLastTxMeInstance.RLock()
1002 if oFsm.pLastTxMeInstance != nil {
1003 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1004 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1005 // maybe we can use just the same eventName for different state transitions like "forward"
1006 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1007 switch oFsm.pLastTxMeInstance.GetName() {
1008 case "Ieee8021PMapperServiceProfile":
1009 { // let the FSM proceed ...
1010 oFsm.mutexPLastTxMeInstance.RUnlock()
1011 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1012 }
1013 case "MacBridgePortConfigurationData":
1014 { // let the FSM proceed ...
1015 oFsm.mutexPLastTxMeInstance.RUnlock()
1016 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1017 }
1018 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1019 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1020 oFsm.mutexPLastTxMeInstance.RUnlock()
1021 oFsm.omciMIdsResponseReceived <- true
1022 }
1023 default:
1024 {
1025 oFsm.mutexPLastTxMeInstance.RUnlock()
1026 logger.Warnw(ctx, "Unsupported ME name received!",
1027 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1028 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001029 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001030 } else {
1031 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001032 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001033 } else {
1034 oFsm.mutexPLastTxMeInstance.RUnlock()
1035 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001036 }
1037 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001038 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1039 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301040 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1041 return
1042 }
Himani Chawla4d908332020-08-31 12:30:20 +05301043}
1044
dbainbri4d3a0dc2020-12-02 00:33:42 +00001045func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301046 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1047 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001048 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001049 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301050 return
1051 }
1052 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1053 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001054 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001055 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301056 return
1057 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001058 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301059 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001060 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001061 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301062 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1063 return
1064 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001065 oFsm.mutexPLastTxMeInstance.RLock()
1066 if oFsm.pLastTxMeInstance != nil {
1067 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1068 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1069 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1070 // if, then something like:
1071 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301072
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001073 switch oFsm.pLastTxMeInstance.GetName() {
1074 case "TCont":
1075 { // let the FSM proceed ...
1076 oFsm.mutexPLastTxMeInstance.RUnlock()
1077 if oFsm.requestEventOffset == 0 { //from TCont config request
1078 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1079 } else { // from T-Cont reset request
1080 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1081 }
1082 }
1083 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1084 { // let the PrioQueue init proceed by stopping the wait function
1085 oFsm.mutexPLastTxMeInstance.RUnlock()
1086 oFsm.omciMIdsResponseReceived <- true
1087 }
1088 case "Ieee8021PMapperServiceProfile":
1089 { // let the FSM proceed ...
1090 oFsm.mutexPLastTxMeInstance.RUnlock()
1091 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1092 }
1093 default:
1094 {
1095 oFsm.mutexPLastTxMeInstance.RUnlock()
1096 logger.Warnw(ctx, "Unsupported ME name received!",
1097 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001098 }
Himani Chawla4d908332020-08-31 12:30:20 +05301099 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001100 } else {
1101 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301102 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001103 } else {
1104 oFsm.mutexPLastTxMeInstance.RUnlock()
1105 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301106 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001107}
1108
dbainbri4d3a0dc2020-12-02 00:33:42 +00001109func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001110 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1111 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001112 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001113 log.Fields{"device-id": oFsm.deviceID})
1114 return
1115 }
1116 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1117 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001118 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001119 log.Fields{"device-id": oFsm.deviceID})
1120 return
1121 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001122 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001123 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001124 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001125 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1126 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1127 // store error for mgmt display?
1128 return
1129 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001130 oFsm.mutexPLastTxMeInstance.RLock()
1131 if oFsm.pLastTxMeInstance != nil {
1132 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1133 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1134 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1135 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001136
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001137 switch oFsm.pLastTxMeInstance.GetName() {
1138 case "GemInterworkingTerminationPoint":
1139 { // let the FSM proceed ...
1140 oFsm.mutexPLastTxMeInstance.RUnlock()
1141 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1142 }
1143 case "GemPortNetworkCtp":
1144 { // let the FSM proceed ...
1145 oFsm.mutexPLastTxMeInstance.RUnlock()
1146 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1147 }
1148 case "Ieee8021PMapperServiceProfile":
1149 { // let the FSM proceed ...
1150 oFsm.mutexPLastTxMeInstance.RUnlock()
1151 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1152 }
1153 case "MacBridgePortConfigurationData":
1154 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1155 oFsm.mutexPLastTxMeInstance.RUnlock()
1156 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1157 }
1158 default:
1159 {
1160 oFsm.mutexPLastTxMeInstance.RUnlock()
1161 logger.Warnw(ctx, "Unsupported ME name received!",
1162 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1163 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001164 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001165 } else {
1166 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001167 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001168 } else {
1169 oFsm.mutexPLastTxMeInstance.RUnlock()
1170 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001171 }
1172}
1173
dbainbri4d3a0dc2020-12-02 00:33:42 +00001174func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1175 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001176 "msgType": msg.OmciMsg.MessageType})
1177
1178 switch msg.OmciMsg.MessageType {
1179 case omci.CreateResponseType:
1180 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001181 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301182
mpagenko3dbcdd22020-07-22 07:38:45 +00001183 } //CreateResponseType
1184 case omci.SetResponseType:
1185 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001186 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001187
mpagenko3dbcdd22020-07-22 07:38:45 +00001188 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001189 case omci.DeleteResponseType:
1190 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001191 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001192
1193 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001194 default:
1195 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001196 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001197 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001198 return
1199 }
1200 }
1201}
1202
dbainbri4d3a0dc2020-12-02 00:33:42 +00001203func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001204 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1205 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001206 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001207 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1208 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001209 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001210 meParams := me.ParamData{
1211 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1212 Attributes: me.AttributeValueMap{
1213 "PortId": gemPortAttribs.gemPortID,
1214 "TContPointer": oFsm.tcont0ID,
1215 "Direction": gemPortAttribs.direction,
1216 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1217 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1218 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1219 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1220 },
1221 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001222 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001223 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001224 oFsm.pAdaptFsm.commChan, meParams)
1225 //accept also nil as (error) return value for writing to LastTx
1226 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001227 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001228 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001229
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001230 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001231 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001232 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001233 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001234 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301235 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001236 return
1237 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001238 // Mark the gem port to be removed for Performance History monitoring
1239 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001240 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001241 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001242 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001243
1244 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001245 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301246 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001247}
1248
dbainbri4d3a0dc2020-12-02 00:33:42 +00001249func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001250 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1251 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001252 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001253 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1254 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001255 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001256
ozgecanetsia4b232302020-11-11 10:58:10 +03001257 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1258 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001259
1260 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001261 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001262 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001263 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001264 "InterworkingOption": 0, // Don't Care
1265 "ServiceProfilePointer": 0, // Don't Care
1266 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001267 },
1268 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001269 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001270 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001271 true, oFsm.pAdaptFsm.commChan, meParams)
1272 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001273 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001274 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001275 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001276 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001277 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001278 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1279 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1280 return
1281 }
1282 ipv4MulticastTable := make([]uint8, 12)
1283 //Gem Port ID
1284 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1285 //Secondary Key
1286 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1287 // Multicast IP range start This is the 224.0.0.1 address
1288 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1289 // MulticastIp range stop
1290 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1291
1292 meIPV4MCTableParams := me.ParamData{
1293 EntityID: gemPortAttribs.multicastGemID,
1294 Attributes: me.AttributeValueMap{
1295 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1296 },
1297 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001298 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001299 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001300 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1301 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001302 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001303
1304 } else {
1305 meParams := me.ParamData{
1306 EntityID: gemPortAttribs.gemPortID,
1307 Attributes: me.AttributeValueMap{
1308 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1309 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1310 "ServiceProfilePointer": oFsm.mapperSP0ID,
1311 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1312 "GalProfilePointer": galEthernetEID,
1313 },
1314 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001315 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001316 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001317 oFsm.pAdaptFsm.commChan, meParams)
1318 //accept also nil as (error) return value for writing to LastTx
1319 // - this avoids misinterpretation of new received OMCI messages
1320 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001321 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001322 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001323 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001324 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001325 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001326 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001327 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301328 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001329 return
1330 }
1331 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001332
1333 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001334 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301335 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001336}
1337
dbainbri4d3a0dc2020-12-02 00:33:42 +00001338func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001339 const cu16StrictPrioWeight uint16 = 0xFFFF
1340 //find all upstream PrioQueues related to this T-Cont
1341 loQueueMap := ordered_map.NewOrderedMap()
1342 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001343 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001344 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001345 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1346 "prioString": gemPortAttribs.pbitString})
1347 continue
1348 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001349 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301350 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001351 //key does not yet exist
1352 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1353 }
1354 } else {
1355 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1356 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001357 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001358
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001359 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1360 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1361 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1362 // or even be finished without correct SP/WRR setting
1363
1364 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1365 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1366 // even though its T-Cont seems to be wrong ...
1367 loTrafficSchedulerEID := 0x8000
1368 //for all found queues
1369 iter := loQueueMap.IterFunc()
1370 for kv, ok := iter(); ok; kv, ok = iter() {
1371 queueIndex := (kv.Key).(uint16)
1372 meParams := me.ParamData{
1373 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301374 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001375 }
1376 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1377 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001378 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001379 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001380 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001381 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1382 } else {
1383 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001384 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001385 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1386 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001387 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001388 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1389 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1390 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001391 oFsm.mutexPLastTxMeInstance.Lock()
Girish Gowdra0b235842021-03-09 13:06:46 -08001392 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001393 oFsm.pAdaptFsm.commChan, meParams)
1394 //accept also nil as (error) return value for writing to LastTx
1395 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001396 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001397 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001398
1399 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001400 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001401 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001402 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001403 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301404 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001405 return
1406 }
1407
1408 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1409 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1410 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1411 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1412
1413 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001414
1415 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001416 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301417 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001418}
1419
dbainbri4d3a0dc2020-12-02 00:33:42 +00001420func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001421 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001422 if oFsm.isCanceled {
1423 // FSM already canceled before entering wait
1424 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1425 oFsm.mutexIsAwaitingResponse.Unlock()
1426 return fmt.Errorf(cErrWaitAborted)
1427 }
mpagenko7d6bb022021-03-11 15:07:55 +00001428 oFsm.isAwaitingResponse = true
1429 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001430 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301431 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001432 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001433 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001434 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 +00001435 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001436 oFsm.mutexIsAwaitingResponse.Lock()
1437 oFsm.isAwaitingResponse = false
1438 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001439 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001440 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301441 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001442 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001443 oFsm.mutexIsAwaitingResponse.Lock()
1444 oFsm.isAwaitingResponse = false
1445 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001446 return nil
1447 }
mpagenko7d6bb022021-03-11 15:07:55 +00001448 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001449 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001450 oFsm.mutexIsAwaitingResponse.Lock()
1451 oFsm.isAwaitingResponse = false
1452 oFsm.mutexIsAwaitingResponse.Unlock()
1453 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001454 }
1455}