blob: ae70353cbf535b309f34d8f4f0b777dc4c8b02b3 [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
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000124 mutexChanSet sync.RWMutex
mpagenko3dbcdd22020-07-22 07:38:45 +0000125 chanSet bool
126 mapperSP0ID uint16
127 macBPCD0ID uint16
128 tcont0ID uint16
129 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000130 gemPortAttribsSlice []ponAniGemPortAttribs
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000131 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000132 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000133 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000134 isWaitingForFlowDelete bool
135 waitFlowDeleteChannel chan bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000136}
137
Himani Chawla6d2ae152020-09-02 13:11:20 +0530138//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 +0000139func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800140 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000141 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530142 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000143 pDeviceHandler: apDeviceHandler,
144 deviceID: apDeviceHandler.deviceID,
145 pOmciCC: apDevOmciCC,
146 pOnuUniPort: apUniPort,
147 pUniTechProf: apUniTechProf,
148 pOnuDB: apOnuDB,
149 techProfileID: aTechProfileID,
150 requestEvent: aRequestEvent,
151 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000152 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000153 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000154 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000155
mpagenko01e726e2020-10-23 09:45:29 +0000156 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000157 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000158 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000159 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000160 return nil
161 }
162
163 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000164 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000165 fsm.Events{
166
mpagenko1cc3cb42020-07-27 15:24:38 +0000167 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000168
169 //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 +0000170 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000171 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000172 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
173 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000174 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000175 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000176 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000177 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000178 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000179 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000180 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000181
mpagenko8b07c1b2020-11-26 10:36:31 +0000182 //for removing Gem related resources
183 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800184 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
185 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000186 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
187 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
188
189 //for removing TCONT related resources
190 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
191 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
192 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
193 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
194
195 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
196 aniStRemovingGemIW, aniStRemovingGemNCTP,
197 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000198 {Name: aniEvTimeoutMids, Src: []string{
199 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000200
mpagenko1cc3cb42020-07-27 15:24:38 +0000201 // exceptional treatment for all states except aniStResetting
202 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
203 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000204 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000205 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000206 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000207 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000208 {Name: aniEvSkipOmciConfig, Src: []string{aniStStarting}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000209 },
210
211 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000212 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
213 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
214 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
215 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
216 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
217 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
218 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
219 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
220 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
221 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
222 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000223 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000224 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
225 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
226 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
227 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
228 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
229 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
230 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000231 },
232 )
233 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000234 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000235 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000236 return nil
237 }
238
dbainbri4d3a0dc2020-12-02 00:33:42 +0000239 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000240 return instFsm
241}
242
Himani Chawla6d2ae152020-09-02 13:11:20 +0530243//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
244func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000245 oFsm.chSuccess = aChSuccess
246 oFsm.procStep = aProcStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000247 oFsm.setChanSet(true)
mpagenko3dbcdd22020-07-22 07:38:45 +0000248}
249
mpagenko7d6bb022021-03-11 15:07:55 +0000250//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000251func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
252 //early indication about started reset processing
253 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000254 //mutex protection is required for possible concurrent access to FSM members
mpagenkocf48e452021-04-23 09:23:00 +0000255 oFsm.mutexIsAwaitingResponse.Lock()
256 oFsm.isCanceled = true
mpagenko7d6bb022021-03-11 15:07:55 +0000257 if oFsm.isAwaitingResponse {
mpagenkocf48e452021-04-23 09:23:00 +0000258 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
259 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
260 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000261 //use channel to indicate that the response waiting shall be aborted
262 oFsm.omciMIdsResponseReceived <- false
mpagenkocf48e452021-04-23 09:23:00 +0000263 } else {
264 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000265 }
mpagenkocf48e452021-04-23 09:23:00 +0000266
267 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000268 if oFsm.isWaitingForFlowDelete {
mpagenkocf48e452021-04-23 09:23:00 +0000269 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000270 //use channel to indicate that the response waiting shall be aborted
271 oFsm.waitFlowDeleteChannel <- false
mpagenkocf48e452021-04-23 09:23:00 +0000272 } else {
273 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000274 }
mpagenkocf48e452021-04-23 09:23:00 +0000275
mpagenko7d6bb022021-03-11 15:07:55 +0000276 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
277 pAdaptFsm := oFsm.pAdaptFsm
278 if pAdaptFsm != nil {
279 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
280 go func(aPAFsm *AdapterFsm) {
281 if aPAFsm.pFsm != nil {
282 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
283 }
284 }(pAdaptFsm)
285 }
mpagenko73143992021-04-09 15:17:10 +0000286
287 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
288 // access conflicts on internal data by next needed data clearance
289 //activity should be aborted in short time if running with FSM due to above FSM reset
290 // or finished without FSM dependency in short time
291 oFsm.pUniTechProf.lockTpProcMutex()
292 defer oFsm.pUniTechProf.unlockTpProcMutex()
293 //remove all TechProf related internal data to allow for new configuration
294 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000295}
296
Mahir Gunyel6781f962021-05-16 23:30:08 -0700297//nolint: gocyclo
298//TODO:visit here for refactoring for gocyclo
dbainbri4d3a0dc2020-12-02 00:33:42 +0000299func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530300 if aPAFsm != nil && aPAFsm.pFsm != nil {
301 //stick to pythonAdapter numbering scheme
302 //index 0 in naming refers to possible usage of multiple instances (later)
Mahir Gunyel6781f962021-05-16 23:30:08 -0700303 var err error
304 oFsm.mapperSP0ID, err = generateIeeMaperServiceProfileEID(uint16(oFsm.pOnuUniPort.macBpNo), uint16(oFsm.techProfileID))
305 if err != nil {
306 logger.Errorw(ctx, "error generating maper id", log.Fields{"device-id": oFsm.deviceID,
307 "techProfileID": oFsm.techProfileID, "error": err})
308 return
309 }
310 oFsm.macBPCD0ID, err = generateANISideMBPCDEID(uint16(oFsm.pOnuUniPort.macBpNo), uint16(oFsm.techProfileID))
311 if err != nil {
312 logger.Errorw(ctx, "error generating mbpcd id", log.Fields{"device-id": oFsm.deviceID,
313 "techProfileID": oFsm.techProfileID, "error": err})
314 return
315 }
316 logger.Debugw(ctx, "generated ids for ani config", log.Fields{"mapperSP0ID": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
317 "macBPCD0ID": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16), "device-id": oFsm.deviceID,
318 "macBpNo": oFsm.pOnuUniPort.macBpNo, "techProfileID": oFsm.techProfileID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000319 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800320
321 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
322 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
323 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
324 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
325 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
326 // when the ONU is discovered.
327 /*
328 for _, tcontInstID := range tcontInstKeys {
329 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
330 returnVal := tconInst["AllocId"]
331 if returnVal != nil {
332 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
333 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
334 if allocID == 0xff || allocID == 0xffff {
335 foundFreeTcontInstID = true
336 oFsm.tcont0ID = uint16(tcontInstID)
337 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
338 "device-id": oFsm.deviceID})
339 break
340 }
341 } else {
342 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
343 }
344 } else {
345 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
346 }
347 }
348 */
349
350 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
351 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
352 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
353 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
354 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
355 // TP ID will increment in single digit
356 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000357 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800358 "device-id": oFsm.deviceID})
359 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000360 logger.Errorw(ctx, "tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000361 if oFsm.isChanSet() {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800362 // indicate processing error/abort to the caller
363 oFsm.chSuccess <- 0
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000364 oFsm.setChanSet(false) //reset the internal channel state
Girish Gowdra041dcb32020-11-16 16:54:30 -0800365 }
366 //reset the state machine to enable usage on subsequent requests
367 _ = aPAFsm.pFsm.Event(aniEvReset)
368 return
369 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530370 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000371 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800372 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530373 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800374 /*
375 if !foundFreeTcontInstID {
376 // This should never happen. If it does, the behavior is unpredictable.
377 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
378 }*/
379
380 // Access critical state with lock
381 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000382 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
383 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800384 oFsm.pUniTechProf.mutexTPState.Unlock()
385
Himani Chawla26e555c2020-08-31 12:30:20 +0530386 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800387 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300388 loGemPortAttribs := ponAniGemPortAttribs{}
389
Himani Chawla26e555c2020-08-31 12:30:20 +0530390 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
391
dbainbri4d3a0dc2020-12-02 00:33:42 +0000392 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530393
394 loGemPortAttribs.gemPortID = gemEntry.gemPortID
395 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
396 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
397 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
398 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
399
400 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
401 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
402 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
403 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
404 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
405 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
406
407 usQueueFound := false
408 dsQueueFound := false
409 for _, mgmtEntityID := range queueInstKeys {
410 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
411 returnVal := meAttributes["RelatedPort"]
412 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530413 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530414 if relatedPort == usQrelPortMask {
415 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000416 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000417 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530418 usQueueFound = true
419 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
420 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000421 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000422 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530423 dsQueueFound = true
424 }
425 if usQueueFound && dsQueueFound {
426 break
427 }
428 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000429 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530430 }
431 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000432 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530433 }
434 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000435 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000436 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530437 }
438 }
439 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000440 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530441 }
442 loGemPortAttribs.direction = gemEntry.direction
443 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
444 loGemPortAttribs.weight = gemEntry.queueWeight
445 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300446 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300447 //TODO this might effectively ignore the for loop starting at line 316
448 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300449 loGemPortAttribs.isMulticast = true
450 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
451 loGemPortAttribs.staticACL = gemEntry.staticACL
452 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530453
dbainbri4d3a0dc2020-12-02 00:33:42 +0000454 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300455 "gemPortID": loGemPortAttribs.gemPortID,
456 "isMulticast": loGemPortAttribs.isMulticast,
457 "multicastGemID": loGemPortAttribs.multicastGemID,
458 "staticACL": loGemPortAttribs.staticACL,
459 "dynamicACL": loGemPortAttribs.dynamicACL,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000460 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300461 })
462
463 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000464 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300465 "gemPortID": loGemPortAttribs.gemPortID,
466 "upQueueID": loGemPortAttribs.upQueueID,
467 "downQueueID": loGemPortAttribs.downQueueID,
468 "pbitString": loGemPortAttribs.pbitString,
469 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000470 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300471 })
472 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530473
474 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
475 }
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000476 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
477 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
478 } else {
479 logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"device-id": oFsm.deviceID})
480 _ = aPAFsm.pFsm.Event(aniEvSkipOmciConfig)
481 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530482 }
483}
484
dbainbri4d3a0dc2020-12-02 00:33:42 +0000485func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
486 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000487 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000488 // in case the used channel is not yet defined (can be re-used after restarts)
489 if oFsm.omciMIdsResponseReceived == nil {
490 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000491 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000492 } else {
493 // as we may 're-use' this instance of FSM and the connected channel
494 // make sure there is no 'lingering' request in the already existing channel:
495 // (simple loop sufficient as we are the only receiver)
496 for len(oFsm.omciMIdsResponseReceived) > 0 {
497 <-oFsm.omciMIdsResponseReceived
498 }
499 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000500 //ensure internal slices are empty (which might be set from previous run) - release memory
501 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000502 oFsm.mutexIsAwaitingResponse.Lock()
503 //reset the canceled state possibly existing from previous reset
504 oFsm.isCanceled = false
505 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000506
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000507 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000508 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000509
510 //let the state machine run forward from here directly
511 pConfigAniStateAFsm := oFsm.pAdaptFsm
512 if pConfigAniStateAFsm != nil {
513 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000514 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000515
mpagenko3dbcdd22020-07-22 07:38:45 +0000516 }
517}
518
dbainbri4d3a0dc2020-12-02 00:33:42 +0000519func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
520 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000521 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000522 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
523 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000524 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300525 meInstance, err := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000526 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300527 if err != nil {
528 logger.Errorw(ctx, "Dot1PMapper create failed, aborting uniPonAniConfigFsm!",
529 log.Fields{"device-id": oFsm.deviceID})
530 pConfigAniStateAFsm := oFsm.pAdaptFsm
531 if pConfigAniStateAFsm != nil {
532 oFsm.mutexPLastTxMeInstance.Unlock()
533 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
534 go func(aPAFsm *AdapterFsm) {
535 if aPAFsm != nil && aPAFsm.pFsm != nil {
536 _ = aPAFsm.pFsm.Event(aniEvReset)
537 }
538 }(pConfigAniStateAFsm)
539 return
540 }
541 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000542 //accept also nil as (error) return value for writing to LastTx
543 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000544 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300545 oFsm.mutexPLastTxMeInstance.Unlock()
546
mpagenko3dbcdd22020-07-22 07:38:45 +0000547}
548
dbainbri4d3a0dc2020-12-02 00:33:42 +0000549func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
550 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000551 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
552 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000553 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000554 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
555 meParams := me.ParamData{
556 EntityID: oFsm.macBPCD0ID,
557 Attributes: me.AttributeValueMap{
558 "BridgeIdPointer": bridgePtr,
559 "PortNum": 0xFF, //fixed unique ANI side indication
560 "TpType": 3, //for .1PMapper
561 "TpPointer": oFsm.mapperSP0ID,
562 },
563 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000564 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300565 meInstance, err := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000566 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300567 if err != nil {
568 logger.Errorw(ctx, "MBPConfigDataVar create failed, aborting uniPonAniConfigFsm!",
569 log.Fields{"device-id": oFsm.deviceID})
570 pConfigAniStateAFsm := oFsm.pAdaptFsm
571 if pConfigAniStateAFsm != nil {
572 oFsm.mutexPLastTxMeInstance.Unlock()
573 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
574 go func(aPAFsm *AdapterFsm) {
575 if aPAFsm != nil && aPAFsm.pFsm != nil {
576 _ = aPAFsm.pFsm.Event(aniEvReset)
577 }
578 }(pConfigAniStateAFsm)
579 return
580 }
581 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000582 //accept also nil as (error) return value for writing to LastTx
583 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000584 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300585 oFsm.mutexPLastTxMeInstance.Unlock()
586
mpagenko3dbcdd22020-07-22 07:38:45 +0000587}
588
dbainbri4d3a0dc2020-12-02 00:33:42 +0000589func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
590 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000591 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
592 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000593 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000594 meParams := me.ParamData{
595 EntityID: oFsm.tcont0ID,
596 Attributes: me.AttributeValueMap{
597 "AllocId": oFsm.alloc0ID,
598 },
599 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000600 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300601 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000602 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300603 if err != nil {
604 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
605 log.Fields{"device-id": oFsm.deviceID})
606 pConfigAniStateAFsm := oFsm.pAdaptFsm
607 if pConfigAniStateAFsm != nil {
608 oFsm.mutexPLastTxMeInstance.Unlock()
609 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
610 go func(aPAFsm *AdapterFsm) {
611 if aPAFsm != nil && aPAFsm.pFsm != nil {
612 _ = aPAFsm.pFsm.Event(aniEvReset)
613 }
614 }(pConfigAniStateAFsm)
615 return
616 }
617 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000618 //accept also nil as (error) return value for writing to LastTx
619 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000620 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300621 oFsm.mutexPLastTxMeInstance.Unlock()
622
mpagenko3dbcdd22020-07-22 07:38:45 +0000623}
624
dbainbri4d3a0dc2020-12-02 00:33:42 +0000625func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
626 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000627 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000628 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000629}
630
dbainbri4d3a0dc2020-12-02 00:33:42 +0000631func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
632 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000633 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000634 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000635}
636
dbainbri4d3a0dc2020-12-02 00:33:42 +0000637func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
638 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000639 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000640 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000641}
642
dbainbri4d3a0dc2020-12-02 00:33:42 +0000643func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300644
dbainbri4d3a0dc2020-12-02 00:33:42 +0000645 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000646 "toGemIw": 1024, /* cmp above */
647 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000648
dbainbri4d3a0dc2020-12-02 00:33:42 +0000649 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000650 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000651 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000652
mpagenko3dbcdd22020-07-22 07:38:45 +0000653 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000654 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530655 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000656 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000657
658 //assign the GemPorts according to the configured Prio
659 var loPrioGemPortArray [8]uint16
660 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300661 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000662 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300663 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
664 "prioString": gemPortAttribs.pbitString})
665 continue
666 }
667 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000668 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300669 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
670 "prioString": gemPortAttribs.pbitString})
671 continue
672 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000673 for i := 0; i < 8; i++ {
674 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
675 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
676 if prio == 1 { // Check this p-bit is set
677 if loPrioGemPortArray[i] == 0 {
678 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
679 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000680 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000681 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000682 "SetGemPort": loPrioGemPortArray[i]})
683 }
684 }
685 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000686 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000687 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000688 "prioString": gemPortAttribs.pbitString, "position": i})
689 }
690
691 }
692 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300693
ozgecanetsia4b232302020-11-11 10:58:10 +0300694 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530695 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300696 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530697 if value != 0 {
698 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530699 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000700 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000701 "for Prio": index,
702 "IwPtr": strconv.FormatInt(int64(value), 16),
703 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300704 } else {
705 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000706 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
707 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300708 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530709 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000710 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300711 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000712 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
713 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300714 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530715
716 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000717 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000718 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300719 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
720 // 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 +0000721 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300722 //pConfigAniStateAFsm := oFsm.pAdaptFsm
723 //if pConfigAniStateAFsm != nil {
724 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
725 // go func(aPAFsm *AdapterFsm) {
726 // if aPAFsm != nil && aPAFsm.pFsm != nil {
727 // _ = aPAFsm.pFsm.Event(aniEvReset)
728 // }
729 // }(pConfigAniStateAFsm)
730 //}
731 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000732 pConfigAniStateAFsm := oFsm.pAdaptFsm
733 if pConfigAniStateAFsm != nil {
734 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530735 go func(aPAFsm *AdapterFsm) {
736 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300737 _ = aPAFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000738 }
739 }(pConfigAniStateAFsm)
740 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300741 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000742 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300743 meInstance, err := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300744 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300745 if err != nil {
746 logger.Errorw(ctx, "Dot1PMapperVar set failed, aborting uniPonAniConfigFsm!",
747 log.Fields{"device-id": oFsm.deviceID})
748 pConfigAniStateAFsm := oFsm.pAdaptFsm
749 if pConfigAniStateAFsm != nil {
750 oFsm.mutexPLastTxMeInstance.Unlock()
751 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
752 go func(aPAFsm *AdapterFsm) {
753 if aPAFsm != nil && aPAFsm.pFsm != nil {
754 _ = aPAFsm.pFsm.Event(aniEvReset)
755 }
756 }(pConfigAniStateAFsm)
757 return
758 }
759 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300760 //accept also nil as (error) return value for writing to LastTx
761 // - this avoids misinterpretation of new received OMCI messages
762 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300763 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000764 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000765}
766
dbainbri4d3a0dc2020-12-02 00:33:42 +0000767func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
768 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000769 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000770 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800771 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000772 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
773 //use DeviceHandler event notification directly
774 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
775 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
776 // but only in case the techProfile was configured (not deleted)
777 if oFsm.requestEventOffset == 0 {
778 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
779 }
780 } else {
781 logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000782 }
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000783 if oFsm.isChanSet() {
mpagenko01e726e2020-10-23 09:45:29 +0000784 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000785 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000786 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
787 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000788 oFsm.setChanSet(false) //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000789 }
mpagenko01e726e2020-10-23 09:45:29 +0000790
791 //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 +0000792}
793
dbainbri4d3a0dc2020-12-02 00:33:42 +0000794func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000795 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000796 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
797 select {
798 case <-oFsm.waitFlowDeleteChannel:
799 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
800 default:
801 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000802
803 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID] != nil {
804 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
805 oFsm.pUniTechProf.mutexTPState.Unlock()
806 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
807 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
808 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
809 pConfigAniStateAFsm := oFsm.pAdaptFsm
810 if pConfigAniStateAFsm != nil {
811 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
812 go func(aPAFsm *AdapterFsm) {
813 if aPAFsm != nil && aPAFsm.pFsm != nil {
814 _ = aPAFsm.pFsm.Event(aniEvWaitFlowRem)
815 }
816 }(pConfigAniStateAFsm)
817 } else {
818 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
819 }
820 return
Girish Gowdra26a40922021-01-29 17:14:34 -0800821 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000822 } else {
823 logger.Debugw(ctx, "uni vlan config doesn't exist - no flow remove could be pending",
824 log.Fields{"device-id": oFsm.deviceID, "techProfile-id": oFsm.techProfileID})
Girish Gowdra26a40922021-01-29 17:14:34 -0800825 }
826
mpagenko8b07c1b2020-11-26 10:36:31 +0000827 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000828 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
829 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000830 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000831 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
832 "GemIwTp-entity-id": loGemPortID})
833 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
834
835 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000836 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300837 meInstance, err := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000838 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300839 if err != nil {
840 logger.Errorw(ctx, "GemIWTP delete failed, aborting uniPonAniConfigFsm!",
841 log.Fields{"device-id": oFsm.deviceID})
842 pConfigAniStateAFsm := oFsm.pAdaptFsm
843 if pConfigAniStateAFsm != nil {
844 oFsm.mutexPLastTxMeInstance.Unlock()
845 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
846 go func(aPAFsm *AdapterFsm) {
847 if aPAFsm != nil && aPAFsm.pFsm != nil {
848 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
849 }
850 }(pConfigAniStateAFsm)
851 return
852 }
853 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000854 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300855 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000856}
857
mpagenkobb47bc22021-04-20 13:29:09 +0000858func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
859 oFsm.mutexIsAwaitingResponse.Lock()
860 oFsm.isWaitingForFlowDelete = true
861 oFsm.mutexIsAwaitingResponse.Unlock()
862 select {
863 // maybe be also some outside cancel (but no context modeled for the moment ...)
864 // case <-ctx.Done():
865 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000866 case <-time.After(2 * oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
mpagenkobb47bc22021-04-20 13:29:09 +0000867 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
868 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
869 oFsm.mutexIsAwaitingResponse.Lock()
870 oFsm.isWaitingForFlowDelete = false
871 oFsm.mutexIsAwaitingResponse.Unlock()
872 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
873 pConfigAniStateAFsm := oFsm.pAdaptFsm
874 if pConfigAniStateAFsm != nil {
875 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
876 go func(aPAFsm *AdapterFsm) {
877 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300878 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000879 }
880 }(pConfigAniStateAFsm)
881 } else {
882 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
883 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
884 }
885 return
886
887 case success := <-oFsm.waitFlowDeleteChannel:
888 if success {
889 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
890 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
891 oFsm.mutexIsAwaitingResponse.Lock()
892 oFsm.isWaitingForFlowDelete = false
893 oFsm.mutexIsAwaitingResponse.Unlock()
894 pConfigAniStateAFsm := oFsm.pAdaptFsm
895 if pConfigAniStateAFsm != nil {
896 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
897 go func(aPAFsm *AdapterFsm) {
898 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300899 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000900 }
901 }(pConfigAniStateAFsm)
902 } else {
903 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
904 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
905 }
906 return
907 }
908 // waiting was aborted (probably on external request)
909 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
910 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
911 oFsm.mutexIsAwaitingResponse.Lock()
912 oFsm.isWaitingForFlowDelete = false
913 oFsm.mutexIsAwaitingResponse.Unlock()
914 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
915 pConfigAniStateAFsm := oFsm.pAdaptFsm
916 if pConfigAniStateAFsm != nil {
917 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
918 go func(aPAFsm *AdapterFsm) {
919 if aPAFsm != nil && aPAFsm.pFsm != nil {
920 _ = aPAFsm.pFsm.Event(aniEvReset)
921 }
922 }(pConfigAniStateAFsm)
923 }
924 return
925 }
926}
927
dbainbri4d3a0dc2020-12-02 00:33:42 +0000928func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000929 oFsm.pUniTechProf.mutexTPState.Lock()
930 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
931 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000932 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000933 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
934 "GemNCTP-entity-id": loGemPortID})
935 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000936 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300937 meInstance, err := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000938 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300939 if err != nil {
940 logger.Errorw(ctx, "GemNCTP delete failed, aborting uniPonAniConfigFsm!",
941 log.Fields{"device-id": oFsm.deviceID})
942 pConfigAniStateAFsm := oFsm.pAdaptFsm
943 if pConfigAniStateAFsm != nil {
944 oFsm.mutexPLastTxMeInstance.Unlock()
945 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
946 go func(aPAFsm *AdapterFsm) {
947 if aPAFsm != nil && aPAFsm.pFsm != nil {
948 _ = aPAFsm.pFsm.Event(aniEvReset)
949 }
950 }(pConfigAniStateAFsm)
951 return
952 }
953 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000954 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000955 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300956
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800957 // Mark the gem port to be removed for Performance History monitoring
958 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700959 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800960 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000961}
962
dbainbri4d3a0dc2020-12-02 00:33:42 +0000963func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
964 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000965 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
966
967 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
968 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
969 meParams := me.ParamData{
970 EntityID: oFsm.tcont0ID,
971 Attributes: me.AttributeValueMap{
972 "AllocId": unusedTcontAllocID,
973 },
974 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000975 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300976 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000977 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300978 if err != nil {
979 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
980 log.Fields{"device-id": oFsm.deviceID})
981 pConfigAniStateAFsm := oFsm.pAdaptFsm
982 if pConfigAniStateAFsm != nil {
983 oFsm.mutexPLastTxMeInstance.Unlock()
984 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
985 go func(aPAFsm *AdapterFsm) {
986 if aPAFsm != nil && aPAFsm.pFsm != nil {
987 _ = aPAFsm.pFsm.Event(aniEvReset)
988 }
989 }(pConfigAniStateAFsm)
990 return
991 }
992 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000993 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300994 oFsm.mutexPLastTxMeInstance.Unlock()
995
mpagenko8b07c1b2020-11-26 10:36:31 +0000996}
997
dbainbri4d3a0dc2020-12-02 00:33:42 +0000998func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
999 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001000 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1001
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001002 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001003 meInstance, err := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001004 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001005 if err != nil {
1006 logger.Errorw(ctx, "Dot1Mapper delete failed, aborting uniPonAniConfigFsm!",
1007 log.Fields{"device-id": oFsm.deviceID})
1008 pConfigAniStateAFsm := oFsm.pAdaptFsm
1009 if pConfigAniStateAFsm != nil {
1010 oFsm.mutexPLastTxMeInstance.Unlock()
1011 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1012 go func(aPAFsm *AdapterFsm) {
1013 if aPAFsm != nil && aPAFsm.pFsm != nil {
1014 _ = aPAFsm.pFsm.Event(aniEvReset)
1015 }
1016 }(pConfigAniStateAFsm)
1017 return
1018 }
1019 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001020 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001021 oFsm.mutexPLastTxMeInstance.Unlock()
1022
mpagenko8b07c1b2020-11-26 10:36:31 +00001023}
1024
dbainbri4d3a0dc2020-12-02 00:33:42 +00001025func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
1026 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001027 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1028
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001029 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001030 meInstance, err := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001031 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001032 if err != nil {
1033 logger.Errorw(ctx, "MBPConfigData delete failed, aborting uniPonAniConfigFsm!",
1034 log.Fields{"device-id": oFsm.deviceID})
1035 pConfigAniStateAFsm := oFsm.pAdaptFsm
1036 if pConfigAniStateAFsm != nil {
1037 oFsm.mutexPLastTxMeInstance.Unlock()
1038 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1039 go func(aPAFsm *AdapterFsm) {
1040 if aPAFsm != nil && aPAFsm.pFsm != nil {
1041 _ = aPAFsm.pFsm.Event(aniEvReset)
1042 }
1043 }(pConfigAniStateAFsm)
1044 return
1045 }
1046 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001047 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001048 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001049}
1050
dbainbri4d3a0dc2020-12-02 00:33:42 +00001051func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
1052 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001053 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1054 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001055 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001056 if oFsm.isChanSet() {
mpagenko8b07c1b2020-11-26 10:36:31 +00001057 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +00001058 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001059 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
1060 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001061 oFsm.setChanSet(false) //reset the internal channel state
mpagenko8b07c1b2020-11-26 10:36:31 +00001062 }
1063
1064 //let's reset the state machine in order to release all resources now
1065 pConfigAniStateAFsm := oFsm.pAdaptFsm
1066 if pConfigAniStateAFsm != nil {
1067 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1068 go func(aPAFsm *AdapterFsm) {
1069 if aPAFsm != nil && aPAFsm.pFsm != nil {
1070 _ = aPAFsm.pFsm.Event(aniEvReset)
1071 }
1072 }(pConfigAniStateAFsm)
1073 }
1074}
1075
dbainbri4d3a0dc2020-12-02 00:33:42 +00001076func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
1077 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001078 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001079
mpagenko3dbcdd22020-07-22 07:38:45 +00001080 pConfigAniStateAFsm := oFsm.pAdaptFsm
1081 if pConfigAniStateAFsm != nil {
1082 // abort running message processing
1083 fsmAbortMsg := Message{
1084 Type: TestMsg,
1085 Data: TestMessage{
1086 TestMessageVal: AbortMessageProcessing,
1087 },
1088 }
1089 pConfigAniStateAFsm.commChan <- fsmAbortMsg
1090
1091 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +05301092 go func(aPAFsm *AdapterFsm) {
1093 if aPAFsm != nil && aPAFsm.pFsm != nil {
1094 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +00001095 }
1096 }(pConfigAniStateAFsm)
1097 }
1098}
1099
dbainbri4d3a0dc2020-12-02 00:33:42 +00001100func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
1101 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001102 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001103 oFsm.mutexPLastTxMeInstance.Lock()
1104 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001105 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +00001106}
1107
dbainbri4d3a0dc2020-12-02 00:33:42 +00001108func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
1109 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001110loop:
1111 for {
mpagenko3dbcdd22020-07-22 07:38:45 +00001112 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001113 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001114 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301115 message, ok := <-oFsm.pAdaptFsm.commChan
1116 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001117 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301118 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1119 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1120 break loop
1121 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001122 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301123
1124 switch message.Type {
1125 case TestMsg:
1126 msg, _ := message.Data.(TestMessage)
1127 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001128 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001129 break loop
1130 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001131 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301132 case OMCI:
1133 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001134 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301135 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001136 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301137 "message.Type": message.Type})
1138 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001139
Himani Chawla4d908332020-08-31 12:30:20 +05301140 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001141 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301142}
1143
dbainbri4d3a0dc2020-12-02 00:33:42 +00001144func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301145 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
1146 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001147 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001148 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301149 return
1150 }
1151 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1152 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001153 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001154 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301155 return
1156 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001157 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +00001158 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1159 //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 +00001160 oFsm.mutexPLastTxMeInstance.RLock()
1161 if oFsm.pLastTxMeInstance != nil {
1162 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1163 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1164 // maybe we can use just the same eventName for different state transitions like "forward"
1165 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1166 switch oFsm.pLastTxMeInstance.GetName() {
1167 case "Ieee8021PMapperServiceProfile":
1168 { // let the FSM proceed ...
1169 oFsm.mutexPLastTxMeInstance.RUnlock()
1170 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1171 }
1172 case "MacBridgePortConfigurationData":
1173 { // let the FSM proceed ...
1174 oFsm.mutexPLastTxMeInstance.RUnlock()
1175 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1176 }
1177 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1178 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1179 oFsm.mutexPLastTxMeInstance.RUnlock()
1180 oFsm.omciMIdsResponseReceived <- true
1181 }
1182 default:
1183 {
1184 oFsm.mutexPLastTxMeInstance.RUnlock()
1185 logger.Warnw(ctx, "Unsupported ME name received!",
1186 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1187 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001188 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001189 } else {
1190 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001191 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001192 } else {
1193 oFsm.mutexPLastTxMeInstance.RUnlock()
1194 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001195 }
1196 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001197 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1198 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301199 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1200 return
1201 }
Himani Chawla4d908332020-08-31 12:30:20 +05301202}
1203
dbainbri4d3a0dc2020-12-02 00:33:42 +00001204func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301205 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1206 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001207 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001208 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301209 return
1210 }
1211 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1212 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001213 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001214 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301215 return
1216 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001217 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301218 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001219 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001220 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301221 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1222 return
1223 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001224 oFsm.mutexPLastTxMeInstance.RLock()
1225 if oFsm.pLastTxMeInstance != nil {
1226 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1227 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1228 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1229 // if, then something like:
1230 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301231
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001232 switch oFsm.pLastTxMeInstance.GetName() {
1233 case "TCont":
1234 { // let the FSM proceed ...
1235 oFsm.mutexPLastTxMeInstance.RUnlock()
1236 if oFsm.requestEventOffset == 0 { //from TCont config request
1237 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1238 } else { // from T-Cont reset request
1239 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1240 }
1241 }
1242 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1243 { // let the PrioQueue init proceed by stopping the wait function
1244 oFsm.mutexPLastTxMeInstance.RUnlock()
1245 oFsm.omciMIdsResponseReceived <- true
1246 }
1247 case "Ieee8021PMapperServiceProfile":
1248 { // let the FSM proceed ...
1249 oFsm.mutexPLastTxMeInstance.RUnlock()
1250 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1251 }
1252 default:
1253 {
1254 oFsm.mutexPLastTxMeInstance.RUnlock()
1255 logger.Warnw(ctx, "Unsupported ME name received!",
1256 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001257 }
Himani Chawla4d908332020-08-31 12:30:20 +05301258 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001259 } else {
1260 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301261 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001262 } else {
1263 oFsm.mutexPLastTxMeInstance.RUnlock()
1264 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301265 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001266}
1267
dbainbri4d3a0dc2020-12-02 00:33:42 +00001268func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001269 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1270 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001271 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001272 log.Fields{"device-id": oFsm.deviceID})
1273 return
1274 }
1275 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1276 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001277 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001278 log.Fields{"device-id": oFsm.deviceID})
1279 return
1280 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001281 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001282 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001283 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001284 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1285 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1286 // store error for mgmt display?
1287 return
1288 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001289 oFsm.mutexPLastTxMeInstance.RLock()
1290 if oFsm.pLastTxMeInstance != nil {
1291 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1292 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1293 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1294 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001295
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001296 switch oFsm.pLastTxMeInstance.GetName() {
1297 case "GemInterworkingTerminationPoint":
1298 { // let the FSM proceed ...
1299 oFsm.mutexPLastTxMeInstance.RUnlock()
1300 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1301 }
1302 case "GemPortNetworkCtp":
1303 { // let the FSM proceed ...
1304 oFsm.mutexPLastTxMeInstance.RUnlock()
1305 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1306 }
1307 case "Ieee8021PMapperServiceProfile":
1308 { // let the FSM proceed ...
1309 oFsm.mutexPLastTxMeInstance.RUnlock()
1310 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1311 }
1312 case "MacBridgePortConfigurationData":
1313 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1314 oFsm.mutexPLastTxMeInstance.RUnlock()
1315 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1316 }
1317 default:
1318 {
1319 oFsm.mutexPLastTxMeInstance.RUnlock()
1320 logger.Warnw(ctx, "Unsupported ME name received!",
1321 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1322 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001323 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001324 } else {
1325 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001326 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001327 } else {
1328 oFsm.mutexPLastTxMeInstance.RUnlock()
1329 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001330 }
1331}
1332
dbainbri4d3a0dc2020-12-02 00:33:42 +00001333func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1334 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001335 "msgType": msg.OmciMsg.MessageType})
1336
1337 switch msg.OmciMsg.MessageType {
1338 case omci.CreateResponseType:
1339 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001340 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301341
mpagenko3dbcdd22020-07-22 07:38:45 +00001342 } //CreateResponseType
1343 case omci.SetResponseType:
1344 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001345 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001346
mpagenko3dbcdd22020-07-22 07:38:45 +00001347 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001348 case omci.DeleteResponseType:
1349 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001350 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001351
1352 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001353 default:
1354 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001355 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001356 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001357 return
1358 }
1359 }
1360}
1361
dbainbri4d3a0dc2020-12-02 00:33:42 +00001362func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001363 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1364 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001365 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001366 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1367 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001368 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001369 meParams := me.ParamData{
1370 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1371 Attributes: me.AttributeValueMap{
1372 "PortId": gemPortAttribs.gemPortID,
1373 "TContPointer": oFsm.tcont0ID,
1374 "Direction": gemPortAttribs.direction,
1375 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1376 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1377 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1378 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1379 },
1380 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001381 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001382 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001383 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001384 if err != nil {
1385 oFsm.mutexPLastTxMeInstance.Unlock()
1386 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1387 log.Fields{"device-id": oFsm.deviceID})
1388 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1389 return
1390 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001391 //accept also nil as (error) return value for writing to LastTx
1392 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001393 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001394 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001395 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001396 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001397 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001398 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001399 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301400 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001401 return
1402 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001403 // Mark the gem port to be removed for Performance History monitoring
1404 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001405 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001406 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001407 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001408
1409 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001410 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301411 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001412}
1413
dbainbri4d3a0dc2020-12-02 00:33:42 +00001414func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001415 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1416 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001417 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001418 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1419 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001420 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001421
ozgecanetsia4b232302020-11-11 10:58:10 +03001422 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1423 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001424
1425 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001426 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001427 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001428 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001429 "InterworkingOption": 0, // Don't Care
1430 "ServiceProfilePointer": 0, // Don't Care
1431 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001432 },
1433 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001434 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001435 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001436 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001437 if err != nil {
1438 oFsm.mutexPLastTxMeInstance.Unlock()
1439 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1440 log.Fields{"device-id": oFsm.deviceID})
1441 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1442 return
1443
1444 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001445 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001446 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001447 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001448 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001449 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001450 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001451 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1452 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1453 return
1454 }
1455 ipv4MulticastTable := make([]uint8, 12)
1456 //Gem Port ID
1457 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1458 //Secondary Key
1459 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1460 // Multicast IP range start This is the 224.0.0.1 address
1461 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1462 // MulticastIp range stop
1463 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1464
1465 meIPV4MCTableParams := me.ParamData{
1466 EntityID: gemPortAttribs.multicastGemID,
1467 Attributes: me.AttributeValueMap{
1468 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1469 },
1470 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001471 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001472 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001473 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001474 if err != nil {
1475 oFsm.mutexPLastTxMeInstance.Unlock()
1476 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1477 log.Fields{"device-id": oFsm.deviceID})
1478 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1479 return
1480 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001481 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001482 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001483
1484 } else {
1485 meParams := me.ParamData{
1486 EntityID: gemPortAttribs.gemPortID,
1487 Attributes: me.AttributeValueMap{
1488 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1489 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1490 "ServiceProfilePointer": oFsm.mapperSP0ID,
1491 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1492 "GalProfilePointer": galEthernetEID,
1493 },
1494 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001495 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001496 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001497 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001498 if err != nil {
1499 oFsm.mutexPLastTxMeInstance.Unlock()
1500 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1501 log.Fields{"device-id": oFsm.deviceID})
1502 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1503 return
1504 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001505 //accept also nil as (error) return value for writing to LastTx
1506 // - this avoids misinterpretation of new received OMCI messages
1507 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001508 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001509 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001510 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001511 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001512 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001513 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001514 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301515 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001516 return
1517 }
1518 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001519
1520 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001521 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301522 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001523}
1524
dbainbri4d3a0dc2020-12-02 00:33:42 +00001525func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001526 const cu16StrictPrioWeight uint16 = 0xFFFF
1527 //find all upstream PrioQueues related to this T-Cont
1528 loQueueMap := ordered_map.NewOrderedMap()
1529 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001530 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001531 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001532 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1533 "prioString": gemPortAttribs.pbitString})
1534 continue
1535 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001536 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301537 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001538 //key does not yet exist
1539 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1540 }
1541 } else {
1542 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1543 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001544 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001545
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001546 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1547 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1548 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1549 // or even be finished without correct SP/WRR setting
1550
1551 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1552 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1553 // even though its T-Cont seems to be wrong ...
1554 loTrafficSchedulerEID := 0x8000
1555 //for all found queues
1556 iter := loQueueMap.IterFunc()
1557 for kv, ok := iter(); ok; kv, ok = iter() {
1558 queueIndex := (kv.Key).(uint16)
1559 meParams := me.ParamData{
1560 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301561 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001562 }
1563 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1564 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001565 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001566 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001567 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001568 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1569 } else {
1570 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001571 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001572 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1573 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001574 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001575 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1576 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1577 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001578 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001579 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001580 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001581 if err != nil {
1582 oFsm.mutexPLastTxMeInstance.Unlock()
1583 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1584 log.Fields{"device-id": oFsm.deviceID})
1585 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1586 return
1587 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001588 //accept also nil as (error) return value for writing to LastTx
1589 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001590 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001591 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001592
1593 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001594 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001595 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001596 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001597 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301598 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001599 return
1600 }
1601
1602 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1603 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1604 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1605 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1606
1607 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001608
1609 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001610 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301611 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001612}
1613
dbainbri4d3a0dc2020-12-02 00:33:42 +00001614func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001615 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001616 if oFsm.isCanceled {
1617 // FSM already canceled before entering wait
1618 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1619 oFsm.mutexIsAwaitingResponse.Unlock()
1620 return fmt.Errorf(cErrWaitAborted)
1621 }
mpagenko7d6bb022021-03-11 15:07:55 +00001622 oFsm.isAwaitingResponse = true
1623 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001624 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301625 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001626 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001627 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +00001628 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
dbainbri4d3a0dc2020-12-02 00:33:42 +00001629 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001630 oFsm.mutexIsAwaitingResponse.Lock()
1631 oFsm.isAwaitingResponse = false
1632 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001633 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001634 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301635 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001636 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001637 oFsm.mutexIsAwaitingResponse.Lock()
1638 oFsm.isAwaitingResponse = false
1639 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001640 return nil
1641 }
mpagenko7d6bb022021-03-11 15:07:55 +00001642 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001643 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001644 oFsm.mutexIsAwaitingResponse.Lock()
1645 oFsm.isAwaitingResponse = false
1646 oFsm.mutexIsAwaitingResponse.Unlock()
1647 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001648 }
1649}
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001650
1651func (oFsm *uniPonAniConfigFsm) setChanSet(flagValue bool) {
1652 oFsm.mutexChanSet.Lock()
1653 oFsm.chanSet = flagValue
1654 oFsm.mutexChanSet.Unlock()
1655}
1656
1657func (oFsm *uniPonAniConfigFsm) isChanSet() bool {
1658 oFsm.mutexChanSet.RLock()
1659 flagValue := oFsm.chanSet
1660 oFsm.mutexChanSet.RUnlock()
1661 return flagValue
1662}