blob: 570198593af9b64b7122479a9e65d45e9c76b745 [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
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000088type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030089 gemPortID uint16
90 upQueueID uint16
91 downQueueID uint16
92 direction uint8
93 qosPolicy string
94 weight uint8
95 pbitString string
96 isMulticast bool
97 multicastGemID uint16
98 staticACL string
99 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000100}
101
Himani Chawla6d2ae152020-09-02 13:11:20 +0530102//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
103type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000104 pDeviceHandler *deviceHandler
105 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530106 pOmciCC *omciCC
107 pOnuUniPort *onuUniPort
108 pUniTechProf *onuUniTechProf
109 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800110 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000111 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000112 requestEvent OnuDeviceEvent
mpagenko7d6bb022021-03-11 15:07:55 +0000113 mutexIsAwaitingResponse sync.RWMutex
mpagenkocf48e452021-04-23 09:23:00 +0000114 isCanceled bool
mpagenko7d6bb022021-03-11 15:07:55 +0000115 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530116 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000117 pAdaptFsm *AdapterFsm
118 chSuccess chan<- uint8
119 procStep uint8
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000120 mutexChanSet sync.RWMutex
mpagenko3dbcdd22020-07-22 07:38:45 +0000121 chanSet bool
122 mapperSP0ID uint16
123 macBPCD0ID uint16
124 tcont0ID uint16
125 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000126 gemPortAttribsSlice []ponAniGemPortAttribs
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000127 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000128 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000129 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000130 isWaitingForFlowDelete bool
131 waitFlowDeleteChannel chan bool
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700132 tcontSetBefore bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000133}
134
Himani Chawla6d2ae152020-09-02 13:11:20 +0530135//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
dbainbri4d3a0dc2020-12-02 00:33:42 +0000136func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800137 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000138 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530139 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000140 pDeviceHandler: apDeviceHandler,
141 deviceID: apDeviceHandler.deviceID,
142 pOmciCC: apDevOmciCC,
143 pOnuUniPort: apUniPort,
144 pUniTechProf: apUniTechProf,
145 pOnuDB: apOnuDB,
146 techProfileID: aTechProfileID,
147 requestEvent: aRequestEvent,
148 chanSet: false,
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700149 tcontSetBefore: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000150 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000151 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000152 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000153
mpagenko01e726e2020-10-23 09:45:29 +0000154 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000155 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000156 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000157 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000158 return nil
159 }
160
161 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000162 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000163 fsm.Events{
164
mpagenko1cc3cb42020-07-27 15:24:38 +0000165 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000166
167 //Note: .1p-Mapper and MBPCD might also have multi instances (per T-Cont) - by now only one 1 T-Cont considered!
mpagenko1cc3cb42020-07-27 15:24:38 +0000168 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000169 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000170 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
171 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000172 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000173 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000174 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000175 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000176 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000177 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000178 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000179
mpagenko8b07c1b2020-11-26 10:36:31 +0000180 //for removing Gem related resources
181 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800182 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
183 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000184 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
185 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
186
187 //for removing TCONT related resources
188 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
189 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
190 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
191 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
192
193 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
194 aniStRemovingGemIW, aniStRemovingGemNCTP,
195 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000196 {Name: aniEvTimeoutMids, Src: []string{
197 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000198
mpagenko1cc3cb42020-07-27 15:24:38 +0000199 // exceptional treatment for all states except aniStResetting
200 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
201 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000202 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000203 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000204 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000205 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000206 {Name: aniEvSkipOmciConfig, Src: []string{aniStStarting}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000207 },
208
209 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000210 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
211 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
212 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
213 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
214 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
215 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
216 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
217 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
218 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
219 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
220 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000221 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000222 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
223 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
224 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
225 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
226 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
227 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
228 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000229 },
230 )
231 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000232 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000233 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000234 return nil
235 }
236
dbainbri4d3a0dc2020-12-02 00:33:42 +0000237 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000238 return instFsm
239}
240
Himani Chawla6d2ae152020-09-02 13:11:20 +0530241//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
242func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000243 oFsm.chSuccess = aChSuccess
244 oFsm.procStep = aProcStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000245 oFsm.setChanSet(true)
mpagenko3dbcdd22020-07-22 07:38:45 +0000246}
247
mpagenko7d6bb022021-03-11 15:07:55 +0000248//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000249func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
250 //early indication about started reset processing
251 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000252 //mutex protection is required for possible concurrent access to FSM members
mpagenkocf48e452021-04-23 09:23:00 +0000253 oFsm.mutexIsAwaitingResponse.Lock()
254 oFsm.isCanceled = true
mpagenko7d6bb022021-03-11 15:07:55 +0000255 if oFsm.isAwaitingResponse {
mpagenkocf48e452021-04-23 09:23:00 +0000256 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
257 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
258 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000259 //use channel to indicate that the response waiting shall be aborted
260 oFsm.omciMIdsResponseReceived <- false
mpagenkocf48e452021-04-23 09:23:00 +0000261 } else {
262 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000263 }
mpagenkocf48e452021-04-23 09:23:00 +0000264
265 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000266 if oFsm.isWaitingForFlowDelete {
mpagenkocf48e452021-04-23 09:23:00 +0000267 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000268 //use channel to indicate that the response waiting shall be aborted
269 oFsm.waitFlowDeleteChannel <- false
mpagenkocf48e452021-04-23 09:23:00 +0000270 } else {
271 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000272 }
mpagenkocf48e452021-04-23 09:23:00 +0000273
mpagenko7d6bb022021-03-11 15:07:55 +0000274 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
275 pAdaptFsm := oFsm.pAdaptFsm
276 if pAdaptFsm != nil {
277 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
278 go func(aPAFsm *AdapterFsm) {
279 if aPAFsm.pFsm != nil {
280 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
281 }
282 }(pAdaptFsm)
283 }
mpagenko73143992021-04-09 15:17:10 +0000284
285 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
286 // access conflicts on internal data by next needed data clearance
287 //activity should be aborted in short time if running with FSM due to above FSM reset
288 // or finished without FSM dependency in short time
289 oFsm.pUniTechProf.lockTpProcMutex()
290 defer oFsm.pUniTechProf.unlockTpProcMutex()
291 //remove all TechProf related internal data to allow for new configuration
292 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000293}
294
Mahir Gunyel6781f962021-05-16 23:30:08 -0700295//nolint: gocyclo
296//TODO:visit here for refactoring for gocyclo
dbainbri4d3a0dc2020-12-02 00:33:42 +0000297func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530298 if aPAFsm != nil && aPAFsm.pFsm != nil {
Mahir Gunyel6781f962021-05-16 23:30:08 -0700299 var err error
300 oFsm.mapperSP0ID, err = generateIeeMaperServiceProfileEID(uint16(oFsm.pOnuUniPort.macBpNo), uint16(oFsm.techProfileID))
301 if err != nil {
302 logger.Errorw(ctx, "error generating maper id", log.Fields{"device-id": oFsm.deviceID,
303 "techProfileID": oFsm.techProfileID, "error": err})
304 return
305 }
306 oFsm.macBPCD0ID, err = generateANISideMBPCDEID(uint16(oFsm.pOnuUniPort.macBpNo), uint16(oFsm.techProfileID))
307 if err != nil {
308 logger.Errorw(ctx, "error generating mbpcd id", log.Fields{"device-id": oFsm.deviceID,
309 "techProfileID": oFsm.techProfileID, "error": err})
310 return
311 }
312 logger.Debugw(ctx, "generated ids for ani config", log.Fields{"mapperSP0ID": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
313 "macBPCD0ID": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16), "device-id": oFsm.deviceID,
314 "macBpNo": oFsm.pOnuUniPort.macBpNo, "techProfileID": oFsm.techProfileID})
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700315 pDevEntry := oFsm.pDeviceHandler.getOnuDeviceEntry(ctx, false)
316 if pDevEntry == nil {
317 logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800318 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530319 }
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700320 tcontInstID, tcontAlreadyExist, err := pDevEntry.allocateFreeTcont(ctx, oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID)
321 if err != nil {
322 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID, "err": err})
323 if oFsm.chanSet {
324 // indicate processing error/abort to the caller
325 oFsm.chSuccess <- 0
326 oFsm.chanSet = false //reset the internal channel state
327 }
328 //reset the state machine to enable usage on subsequent requests
329 _ = aPAFsm.pFsm.Event(aniEvReset)
330 return
331 }
332 oFsm.tcont0ID = tcontInstID
333 oFsm.tcontSetBefore = tcontAlreadyExist
334 logger.Debugw(ctx, "used-tcont-instance-id", log.Fields{"tcont-inst-id": oFsm.tcont0ID,
335 "alloc-id": oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID,
336 "tcontAlreadyExist": tcontAlreadyExist,
337 "device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800338
339 // Access critical state with lock
340 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000341 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
342 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800343 oFsm.pUniTechProf.mutexTPState.Unlock()
344
Himani Chawla26e555c2020-08-31 12:30:20 +0530345 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800346 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300347 loGemPortAttribs := ponAniGemPortAttribs{}
348
Himani Chawla26e555c2020-08-31 12:30:20 +0530349 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
350
dbainbri4d3a0dc2020-12-02 00:33:42 +0000351 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530352
353 loGemPortAttribs.gemPortID = gemEntry.gemPortID
354 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
355 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
356 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
357 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
358
359 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
360 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
361 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
362 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
363 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
364 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
365
366 usQueueFound := false
367 dsQueueFound := false
368 for _, mgmtEntityID := range queueInstKeys {
369 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
370 returnVal := meAttributes["RelatedPort"]
371 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530372 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530373 if relatedPort == usQrelPortMask {
374 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000375 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000376 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530377 usQueueFound = true
378 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
379 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000380 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000381 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530382 dsQueueFound = true
383 }
384 if usQueueFound && dsQueueFound {
385 break
386 }
387 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000388 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530389 }
390 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000391 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530392 }
393 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000394 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000395 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530396 }
397 }
398 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000399 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530400 }
401 loGemPortAttribs.direction = gemEntry.direction
402 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
403 loGemPortAttribs.weight = gemEntry.queueWeight
404 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300405 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300406 //TODO this might effectively ignore the for loop starting at line 316
407 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300408 loGemPortAttribs.isMulticast = true
409 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
410 loGemPortAttribs.staticACL = gemEntry.staticACL
411 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530412
dbainbri4d3a0dc2020-12-02 00:33:42 +0000413 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300414 "gemPortID": loGemPortAttribs.gemPortID,
415 "isMulticast": loGemPortAttribs.isMulticast,
416 "multicastGemID": loGemPortAttribs.multicastGemID,
417 "staticACL": loGemPortAttribs.staticACL,
418 "dynamicACL": loGemPortAttribs.dynamicACL,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000419 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300420 })
421
422 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000423 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300424 "gemPortID": loGemPortAttribs.gemPortID,
425 "upQueueID": loGemPortAttribs.upQueueID,
426 "downQueueID": loGemPortAttribs.downQueueID,
427 "pbitString": loGemPortAttribs.pbitString,
428 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000429 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300430 })
431 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530432
433 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
434 }
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000435 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
436 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
437 } else {
438 logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"device-id": oFsm.deviceID})
439 _ = aPAFsm.pFsm.Event(aniEvSkipOmciConfig)
440 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530441 }
442}
443
dbainbri4d3a0dc2020-12-02 00:33:42 +0000444func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
445 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000446 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000447 // in case the used channel is not yet defined (can be re-used after restarts)
448 if oFsm.omciMIdsResponseReceived == nil {
449 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000450 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000451 } else {
452 // as we may 're-use' this instance of FSM and the connected channel
453 // make sure there is no 'lingering' request in the already existing channel:
454 // (simple loop sufficient as we are the only receiver)
455 for len(oFsm.omciMIdsResponseReceived) > 0 {
456 <-oFsm.omciMIdsResponseReceived
457 }
458 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000459 //ensure internal slices are empty (which might be set from previous run) - release memory
460 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000461 oFsm.mutexIsAwaitingResponse.Lock()
462 //reset the canceled state possibly existing from previous reset
463 oFsm.isCanceled = false
464 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000465
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000466 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000467 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000468
469 //let the state machine run forward from here directly
470 pConfigAniStateAFsm := oFsm.pAdaptFsm
471 if pConfigAniStateAFsm != nil {
472 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000473 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000474
mpagenko3dbcdd22020-07-22 07:38:45 +0000475 }
476}
477
dbainbri4d3a0dc2020-12-02 00:33:42 +0000478func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
479 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000480 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000481 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
482 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000483 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300484 meInstance, err := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000485 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300486 if err != nil {
487 logger.Errorw(ctx, "Dot1PMapper create failed, aborting uniPonAniConfigFsm!",
488 log.Fields{"device-id": oFsm.deviceID})
489 pConfigAniStateAFsm := oFsm.pAdaptFsm
490 if pConfigAniStateAFsm != nil {
491 oFsm.mutexPLastTxMeInstance.Unlock()
492 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
493 go func(aPAFsm *AdapterFsm) {
494 if aPAFsm != nil && aPAFsm.pFsm != nil {
495 _ = aPAFsm.pFsm.Event(aniEvReset)
496 }
497 }(pConfigAniStateAFsm)
498 return
499 }
500 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000501 //accept also nil as (error) return value for writing to LastTx
502 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000503 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300504 oFsm.mutexPLastTxMeInstance.Unlock()
505
mpagenko3dbcdd22020-07-22 07:38:45 +0000506}
507
dbainbri4d3a0dc2020-12-02 00:33:42 +0000508func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
509 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000510 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
511 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000512 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000513 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
514 meParams := me.ParamData{
515 EntityID: oFsm.macBPCD0ID,
516 Attributes: me.AttributeValueMap{
517 "BridgeIdPointer": bridgePtr,
518 "PortNum": 0xFF, //fixed unique ANI side indication
519 "TpType": 3, //for .1PMapper
520 "TpPointer": oFsm.mapperSP0ID,
521 },
522 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000523 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300524 meInstance, err := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000525 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300526 if err != nil {
527 logger.Errorw(ctx, "MBPConfigDataVar create failed, aborting uniPonAniConfigFsm!",
528 log.Fields{"device-id": oFsm.deviceID})
529 pConfigAniStateAFsm := oFsm.pAdaptFsm
530 if pConfigAniStateAFsm != nil {
531 oFsm.mutexPLastTxMeInstance.Unlock()
532 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
533 go func(aPAFsm *AdapterFsm) {
534 if aPAFsm != nil && aPAFsm.pFsm != nil {
535 _ = aPAFsm.pFsm.Event(aniEvReset)
536 }
537 }(pConfigAniStateAFsm)
538 return
539 }
540 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000541 //accept also nil as (error) return value for writing to LastTx
542 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000543 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300544 oFsm.mutexPLastTxMeInstance.Unlock()
545
mpagenko3dbcdd22020-07-22 07:38:45 +0000546}
547
dbainbri4d3a0dc2020-12-02 00:33:42 +0000548func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
549 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000550 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
551 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700552 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
553 "tcontExist": oFsm.tcontSetBefore})
554 //If tcont was set before, then no need to set it again. Let state machine to proceed.
555 if oFsm.tcontSetBefore {
556 go func(aPAFsm *AdapterFsm) {
557 if aPAFsm != nil && aPAFsm.pFsm != nil {
558 _ = aPAFsm.pFsm.Event(aniEvRxTcontsResp)
559 }
560 }(oFsm.pAdaptFsm)
561 return
562 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000563 meParams := me.ParamData{
564 EntityID: oFsm.tcont0ID,
565 Attributes: me.AttributeValueMap{
566 "AllocId": oFsm.alloc0ID,
567 },
568 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000569 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300570 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000571 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300572 if err != nil {
573 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
574 log.Fields{"device-id": oFsm.deviceID})
575 pConfigAniStateAFsm := oFsm.pAdaptFsm
576 if pConfigAniStateAFsm != nil {
577 oFsm.mutexPLastTxMeInstance.Unlock()
578 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
579 go func(aPAFsm *AdapterFsm) {
580 if aPAFsm != nil && aPAFsm.pFsm != nil {
581 _ = aPAFsm.pFsm.Event(aniEvReset)
582 }
583 }(pConfigAniStateAFsm)
584 return
585 }
586 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000587 //accept also nil as (error) return value for writing to LastTx
588 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000589 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300590 oFsm.mutexPLastTxMeInstance.Unlock()
591
mpagenko3dbcdd22020-07-22 07:38:45 +0000592}
593
dbainbri4d3a0dc2020-12-02 00:33:42 +0000594func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
595 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000596 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000597 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000598}
599
dbainbri4d3a0dc2020-12-02 00:33:42 +0000600func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
601 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000602 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000603 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000604}
605
dbainbri4d3a0dc2020-12-02 00:33:42 +0000606func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
607 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000608 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000609 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000610}
611
dbainbri4d3a0dc2020-12-02 00:33:42 +0000612func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300613
dbainbri4d3a0dc2020-12-02 00:33:42 +0000614 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000615 "toGemIw": 1024, /* cmp above */
616 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000617
dbainbri4d3a0dc2020-12-02 00:33:42 +0000618 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000619 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000620 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000621
mpagenko3dbcdd22020-07-22 07:38:45 +0000622 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000623 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530624 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000625 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000626
627 //assign the GemPorts according to the configured Prio
628 var loPrioGemPortArray [8]uint16
629 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300630 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000631 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300632 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
633 "prioString": gemPortAttribs.pbitString})
634 continue
635 }
636 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000637 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300638 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
639 "prioString": gemPortAttribs.pbitString})
640 continue
641 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000642 for i := 0; i < 8; i++ {
643 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
644 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
645 if prio == 1 { // Check this p-bit is set
646 if loPrioGemPortArray[i] == 0 {
647 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
648 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000649 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000650 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000651 "SetGemPort": loPrioGemPortArray[i]})
652 }
653 }
654 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000655 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000656 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000657 "prioString": gemPortAttribs.pbitString, "position": i})
658 }
659
660 }
661 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300662
ozgecanetsia4b232302020-11-11 10:58:10 +0300663 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530664 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300665 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530666 if value != 0 {
667 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530668 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000669 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000670 "for Prio": index,
671 "IwPtr": strconv.FormatInt(int64(value), 16),
672 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300673 } else {
674 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000675 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
676 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300677 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530678 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000679 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300680 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000681 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
682 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300683 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530684
685 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000686 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000687 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300688 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
689 // 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 +0000690 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300691 //pConfigAniStateAFsm := oFsm.pAdaptFsm
692 //if pConfigAniStateAFsm != nil {
693 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
694 // go func(aPAFsm *AdapterFsm) {
695 // if aPAFsm != nil && aPAFsm.pFsm != nil {
696 // _ = aPAFsm.pFsm.Event(aniEvReset)
697 // }
698 // }(pConfigAniStateAFsm)
699 //}
700 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000701 pConfigAniStateAFsm := oFsm.pAdaptFsm
702 if pConfigAniStateAFsm != nil {
703 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530704 go func(aPAFsm *AdapterFsm) {
705 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300706 _ = aPAFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000707 }
708 }(pConfigAniStateAFsm)
709 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300710 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000711 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300712 meInstance, err := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300713 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300714 if err != nil {
715 logger.Errorw(ctx, "Dot1PMapperVar set failed, aborting uniPonAniConfigFsm!",
716 log.Fields{"device-id": oFsm.deviceID})
717 pConfigAniStateAFsm := oFsm.pAdaptFsm
718 if pConfigAniStateAFsm != nil {
719 oFsm.mutexPLastTxMeInstance.Unlock()
720 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
721 go func(aPAFsm *AdapterFsm) {
722 if aPAFsm != nil && aPAFsm.pFsm != nil {
723 _ = aPAFsm.pFsm.Event(aniEvReset)
724 }
725 }(pConfigAniStateAFsm)
726 return
727 }
728 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300729 //accept also nil as (error) return value for writing to LastTx
730 // - this avoids misinterpretation of new received OMCI messages
731 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300732 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000733 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000734}
735
dbainbri4d3a0dc2020-12-02 00:33:42 +0000736func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
737 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000738 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000739 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800740 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000741 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
742 //use DeviceHandler event notification directly
743 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
744 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
745 // but only in case the techProfile was configured (not deleted)
746 if oFsm.requestEventOffset == 0 {
747 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
748 }
749 } else {
750 logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000751 }
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000752 if oFsm.isChanSet() {
mpagenko01e726e2020-10-23 09:45:29 +0000753 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000754 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000755 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
756 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000757 oFsm.setChanSet(false) //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000758 }
mpagenko01e726e2020-10-23 09:45:29 +0000759
760 //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 +0000761}
762
dbainbri4d3a0dc2020-12-02 00:33:42 +0000763func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000764 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000765 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
766 select {
767 case <-oFsm.waitFlowDeleteChannel:
768 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
769 default:
770 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000771
772 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID] != nil {
773 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
774 oFsm.pUniTechProf.mutexTPState.Unlock()
775 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
776 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
777 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
778 pConfigAniStateAFsm := oFsm.pAdaptFsm
779 if pConfigAniStateAFsm != nil {
780 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
781 go func(aPAFsm *AdapterFsm) {
782 if aPAFsm != nil && aPAFsm.pFsm != nil {
783 _ = aPAFsm.pFsm.Event(aniEvWaitFlowRem)
784 }
785 }(pConfigAniStateAFsm)
786 } else {
787 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
788 }
789 return
Girish Gowdra26a40922021-01-29 17:14:34 -0800790 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000791 } else {
792 logger.Debugw(ctx, "uni vlan config doesn't exist - no flow remove could be pending",
793 log.Fields{"device-id": oFsm.deviceID, "techProfile-id": oFsm.techProfileID})
Girish Gowdra26a40922021-01-29 17:14:34 -0800794 }
795
mpagenko8b07c1b2020-11-26 10:36:31 +0000796 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000797 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
798 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000799 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000800 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
801 "GemIwTp-entity-id": loGemPortID})
802 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
803
804 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000805 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300806 meInstance, err := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000807 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300808 if err != nil {
809 logger.Errorw(ctx, "GemIWTP delete failed, aborting uniPonAniConfigFsm!",
810 log.Fields{"device-id": oFsm.deviceID})
811 pConfigAniStateAFsm := oFsm.pAdaptFsm
812 if pConfigAniStateAFsm != nil {
813 oFsm.mutexPLastTxMeInstance.Unlock()
814 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
815 go func(aPAFsm *AdapterFsm) {
816 if aPAFsm != nil && aPAFsm.pFsm != nil {
817 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
818 }
819 }(pConfigAniStateAFsm)
820 return
821 }
822 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000823 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300824 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000825}
826
mpagenkobb47bc22021-04-20 13:29:09 +0000827func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
828 oFsm.mutexIsAwaitingResponse.Lock()
829 oFsm.isWaitingForFlowDelete = true
830 oFsm.mutexIsAwaitingResponse.Unlock()
831 select {
832 // maybe be also some outside cancel (but no context modeled for the moment ...)
833 // case <-ctx.Done():
834 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000835 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 +0000836 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
837 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
838 oFsm.mutexIsAwaitingResponse.Lock()
839 oFsm.isWaitingForFlowDelete = false
840 oFsm.mutexIsAwaitingResponse.Unlock()
841 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
842 pConfigAniStateAFsm := oFsm.pAdaptFsm
843 if pConfigAniStateAFsm != nil {
844 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
845 go func(aPAFsm *AdapterFsm) {
846 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300847 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000848 }
849 }(pConfigAniStateAFsm)
850 } else {
851 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
852 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
853 }
854 return
855
856 case success := <-oFsm.waitFlowDeleteChannel:
857 if success {
858 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
859 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
860 oFsm.mutexIsAwaitingResponse.Lock()
861 oFsm.isWaitingForFlowDelete = false
862 oFsm.mutexIsAwaitingResponse.Unlock()
863 pConfigAniStateAFsm := oFsm.pAdaptFsm
864 if pConfigAniStateAFsm != nil {
865 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
866 go func(aPAFsm *AdapterFsm) {
867 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300868 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000869 }
870 }(pConfigAniStateAFsm)
871 } else {
872 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
873 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
874 }
875 return
876 }
877 // waiting was aborted (probably on external request)
878 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
879 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
880 oFsm.mutexIsAwaitingResponse.Lock()
881 oFsm.isWaitingForFlowDelete = false
882 oFsm.mutexIsAwaitingResponse.Unlock()
883 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
884 pConfigAniStateAFsm := oFsm.pAdaptFsm
885 if pConfigAniStateAFsm != nil {
886 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
887 go func(aPAFsm *AdapterFsm) {
888 if aPAFsm != nil && aPAFsm.pFsm != nil {
889 _ = aPAFsm.pFsm.Event(aniEvReset)
890 }
891 }(pConfigAniStateAFsm)
892 }
893 return
894 }
895}
896
dbainbri4d3a0dc2020-12-02 00:33:42 +0000897func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000898 oFsm.pUniTechProf.mutexTPState.Lock()
899 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
900 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000901 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000902 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
903 "GemNCTP-entity-id": loGemPortID})
904 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000905 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300906 meInstance, err := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000907 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300908 if err != nil {
909 logger.Errorw(ctx, "GemNCTP delete failed, aborting uniPonAniConfigFsm!",
910 log.Fields{"device-id": oFsm.deviceID})
911 pConfigAniStateAFsm := oFsm.pAdaptFsm
912 if pConfigAniStateAFsm != nil {
913 oFsm.mutexPLastTxMeInstance.Unlock()
914 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
915 go func(aPAFsm *AdapterFsm) {
916 if aPAFsm != nil && aPAFsm.pFsm != nil {
917 _ = aPAFsm.pFsm.Event(aniEvReset)
918 }
919 }(pConfigAniStateAFsm)
920 return
921 }
922 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000923 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000924 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300925
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800926 // Mark the gem port to be removed for Performance History monitoring
927 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700928 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800929 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000930}
931
dbainbri4d3a0dc2020-12-02 00:33:42 +0000932func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
933 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000934 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
935
936 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
937 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
938 meParams := me.ParamData{
939 EntityID: oFsm.tcont0ID,
940 Attributes: me.AttributeValueMap{
941 "AllocId": unusedTcontAllocID,
942 },
943 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000944 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300945 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000946 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300947 if err != nil {
948 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
949 log.Fields{"device-id": oFsm.deviceID})
950 pConfigAniStateAFsm := oFsm.pAdaptFsm
951 if pConfigAniStateAFsm != nil {
952 oFsm.mutexPLastTxMeInstance.Unlock()
953 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
954 go func(aPAFsm *AdapterFsm) {
955 if aPAFsm != nil && aPAFsm.pFsm != nil {
956 _ = aPAFsm.pFsm.Event(aniEvReset)
957 }
958 }(pConfigAniStateAFsm)
959 return
960 }
961 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000962 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300963 oFsm.mutexPLastTxMeInstance.Unlock()
964
mpagenko8b07c1b2020-11-26 10:36:31 +0000965}
966
dbainbri4d3a0dc2020-12-02 00:33:42 +0000967func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
968 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000969 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
970
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000971 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300972 meInstance, err := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000973 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300974 if err != nil {
975 logger.Errorw(ctx, "Dot1Mapper delete failed, aborting uniPonAniConfigFsm!",
976 log.Fields{"device-id": oFsm.deviceID})
977 pConfigAniStateAFsm := oFsm.pAdaptFsm
978 if pConfigAniStateAFsm != nil {
979 oFsm.mutexPLastTxMeInstance.Unlock()
980 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
981 go func(aPAFsm *AdapterFsm) {
982 if aPAFsm != nil && aPAFsm.pFsm != nil {
983 _ = aPAFsm.pFsm.Event(aniEvReset)
984 }
985 }(pConfigAniStateAFsm)
986 return
987 }
988 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000989 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300990 oFsm.mutexPLastTxMeInstance.Unlock()
991
mpagenko8b07c1b2020-11-26 10:36:31 +0000992}
993
dbainbri4d3a0dc2020-12-02 00:33:42 +0000994func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
995 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000996 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
997
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000998 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300999 meInstance, err := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001000 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001001 if err != nil {
1002 logger.Errorw(ctx, "MBPConfigData delete failed, aborting uniPonAniConfigFsm!",
1003 log.Fields{"device-id": oFsm.deviceID})
1004 pConfigAniStateAFsm := oFsm.pAdaptFsm
1005 if pConfigAniStateAFsm != nil {
1006 oFsm.mutexPLastTxMeInstance.Unlock()
1007 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1008 go func(aPAFsm *AdapterFsm) {
1009 if aPAFsm != nil && aPAFsm.pFsm != nil {
1010 _ = aPAFsm.pFsm.Event(aniEvReset)
1011 }
1012 }(pConfigAniStateAFsm)
1013 return
1014 }
1015 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001016 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001017 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001018}
1019
dbainbri4d3a0dc2020-12-02 00:33:42 +00001020func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
1021 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001022 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1023 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001024 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001025 if oFsm.isChanSet() {
mpagenko8b07c1b2020-11-26 10:36:31 +00001026 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +00001027 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001028 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
1029 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001030 oFsm.setChanSet(false) //reset the internal channel state
mpagenko8b07c1b2020-11-26 10:36:31 +00001031 }
1032
1033 //let's reset the state machine in order to release all resources now
1034 pConfigAniStateAFsm := oFsm.pAdaptFsm
1035 if pConfigAniStateAFsm != nil {
1036 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1037 go func(aPAFsm *AdapterFsm) {
1038 if aPAFsm != nil && aPAFsm.pFsm != nil {
1039 _ = aPAFsm.pFsm.Event(aniEvReset)
1040 }
1041 }(pConfigAniStateAFsm)
1042 }
1043}
1044
dbainbri4d3a0dc2020-12-02 00:33:42 +00001045func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
1046 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001047 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001048
mpagenko3dbcdd22020-07-22 07:38:45 +00001049 pConfigAniStateAFsm := oFsm.pAdaptFsm
1050 if pConfigAniStateAFsm != nil {
1051 // abort running message processing
1052 fsmAbortMsg := Message{
1053 Type: TestMsg,
1054 Data: TestMessage{
1055 TestMessageVal: AbortMessageProcessing,
1056 },
1057 }
1058 pConfigAniStateAFsm.commChan <- fsmAbortMsg
1059
1060 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +05301061 go func(aPAFsm *AdapterFsm) {
1062 if aPAFsm != nil && aPAFsm.pFsm != nil {
1063 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +00001064 }
1065 }(pConfigAniStateAFsm)
1066 }
1067}
1068
dbainbri4d3a0dc2020-12-02 00:33:42 +00001069func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
1070 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001071 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001072 oFsm.mutexPLastTxMeInstance.Lock()
1073 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001074 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +00001075}
1076
dbainbri4d3a0dc2020-12-02 00:33:42 +00001077func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
1078 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001079loop:
1080 for {
mpagenko3dbcdd22020-07-22 07:38:45 +00001081 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001082 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001083 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301084 message, ok := <-oFsm.pAdaptFsm.commChan
1085 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001086 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301087 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1088 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1089 break loop
1090 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001091 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301092
1093 switch message.Type {
1094 case TestMsg:
1095 msg, _ := message.Data.(TestMessage)
1096 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001097 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001098 break loop
1099 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001100 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301101 case OMCI:
1102 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001103 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301104 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001105 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301106 "message.Type": message.Type})
1107 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001108
Himani Chawla4d908332020-08-31 12:30:20 +05301109 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001110 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301111}
1112
dbainbri4d3a0dc2020-12-02 00:33:42 +00001113func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301114 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
1115 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001116 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001117 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301118 return
1119 }
1120 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1121 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001122 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001123 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301124 return
1125 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001126 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +00001127 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1128 //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 +00001129 oFsm.mutexPLastTxMeInstance.RLock()
1130 if oFsm.pLastTxMeInstance != nil {
1131 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1132 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1133 // maybe we can use just the same eventName for different state transitions like "forward"
1134 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1135 switch oFsm.pLastTxMeInstance.GetName() {
1136 case "Ieee8021PMapperServiceProfile":
1137 { // let the FSM proceed ...
1138 oFsm.mutexPLastTxMeInstance.RUnlock()
1139 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1140 }
1141 case "MacBridgePortConfigurationData":
1142 { // let the FSM proceed ...
1143 oFsm.mutexPLastTxMeInstance.RUnlock()
1144 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1145 }
1146 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1147 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1148 oFsm.mutexPLastTxMeInstance.RUnlock()
1149 oFsm.omciMIdsResponseReceived <- true
1150 }
1151 default:
1152 {
1153 oFsm.mutexPLastTxMeInstance.RUnlock()
1154 logger.Warnw(ctx, "Unsupported ME name received!",
1155 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1156 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001157 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001158 } else {
1159 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001160 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001161 } else {
1162 oFsm.mutexPLastTxMeInstance.RUnlock()
1163 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001164 }
1165 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001166 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1167 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301168 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1169 return
1170 }
Himani Chawla4d908332020-08-31 12:30:20 +05301171}
1172
dbainbri4d3a0dc2020-12-02 00:33:42 +00001173func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301174 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1175 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001176 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001177 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301178 return
1179 }
1180 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1181 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001182 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001183 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301184 return
1185 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001186 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301187 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001188 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001189 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301190 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001191
1192 //FIXME: If setting TCONT fails we need to revert the DB back. Because of the concurency,
1193 //doing it here may cause a data inconsistency. To fix this problem we need to think on running
1194 //the FSMs of different UNIs sequentially instead of running them concurrently.
1195
Himani Chawla4d908332020-08-31 12:30:20 +05301196 return
1197 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001198 oFsm.mutexPLastTxMeInstance.RLock()
1199 if oFsm.pLastTxMeInstance != nil {
1200 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1201 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1202 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1203 // if, then something like:
1204 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301205
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001206 switch oFsm.pLastTxMeInstance.GetName() {
1207 case "TCont":
1208 { // let the FSM proceed ...
1209 oFsm.mutexPLastTxMeInstance.RUnlock()
1210 if oFsm.requestEventOffset == 0 { //from TCont config request
1211 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1212 } else { // from T-Cont reset request
1213 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1214 }
1215 }
1216 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1217 { // let the PrioQueue init proceed by stopping the wait function
1218 oFsm.mutexPLastTxMeInstance.RUnlock()
1219 oFsm.omciMIdsResponseReceived <- true
1220 }
1221 case "Ieee8021PMapperServiceProfile":
1222 { // let the FSM proceed ...
1223 oFsm.mutexPLastTxMeInstance.RUnlock()
1224 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1225 }
1226 default:
1227 {
1228 oFsm.mutexPLastTxMeInstance.RUnlock()
1229 logger.Warnw(ctx, "Unsupported ME name received!",
1230 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001231 }
Himani Chawla4d908332020-08-31 12:30:20 +05301232 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001233 } else {
1234 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301235 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001236 } else {
1237 oFsm.mutexPLastTxMeInstance.RUnlock()
1238 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301239 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001240}
1241
dbainbri4d3a0dc2020-12-02 00:33:42 +00001242func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001243 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1244 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001245 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001246 log.Fields{"device-id": oFsm.deviceID})
1247 return
1248 }
1249 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1250 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001251 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001252 log.Fields{"device-id": oFsm.deviceID})
1253 return
1254 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001255 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001256 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001257 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001258 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1259 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1260 // store error for mgmt display?
1261 return
1262 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001263 oFsm.mutexPLastTxMeInstance.RLock()
1264 if oFsm.pLastTxMeInstance != nil {
1265 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1266 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1267 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1268 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001269
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001270 switch oFsm.pLastTxMeInstance.GetName() {
1271 case "GemInterworkingTerminationPoint":
1272 { // let the FSM proceed ...
1273 oFsm.mutexPLastTxMeInstance.RUnlock()
1274 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1275 }
1276 case "GemPortNetworkCtp":
1277 { // let the FSM proceed ...
1278 oFsm.mutexPLastTxMeInstance.RUnlock()
1279 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1280 }
1281 case "Ieee8021PMapperServiceProfile":
1282 { // let the FSM proceed ...
1283 oFsm.mutexPLastTxMeInstance.RUnlock()
1284 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1285 }
1286 case "MacBridgePortConfigurationData":
1287 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1288 oFsm.mutexPLastTxMeInstance.RUnlock()
1289 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1290 }
1291 default:
1292 {
1293 oFsm.mutexPLastTxMeInstance.RUnlock()
1294 logger.Warnw(ctx, "Unsupported ME name received!",
1295 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1296 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001297 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001298 } else {
1299 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001300 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001301 } else {
1302 oFsm.mutexPLastTxMeInstance.RUnlock()
1303 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001304 }
1305}
1306
dbainbri4d3a0dc2020-12-02 00:33:42 +00001307func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1308 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001309 "msgType": msg.OmciMsg.MessageType})
1310
1311 switch msg.OmciMsg.MessageType {
1312 case omci.CreateResponseType:
1313 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001314 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301315
mpagenko3dbcdd22020-07-22 07:38:45 +00001316 } //CreateResponseType
1317 case omci.SetResponseType:
1318 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001319 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001320
mpagenko3dbcdd22020-07-22 07:38:45 +00001321 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001322 case omci.DeleteResponseType:
1323 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001324 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001325
1326 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001327 default:
1328 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001329 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001330 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001331 return
1332 }
1333 }
1334}
1335
dbainbri4d3a0dc2020-12-02 00:33:42 +00001336func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001337 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1338 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001339 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001340 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1341 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001342 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001343 meParams := me.ParamData{
1344 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1345 Attributes: me.AttributeValueMap{
1346 "PortId": gemPortAttribs.gemPortID,
1347 "TContPointer": oFsm.tcont0ID,
1348 "Direction": gemPortAttribs.direction,
1349 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1350 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1351 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1352 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1353 },
1354 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001355 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001356 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001357 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001358 if err != nil {
1359 oFsm.mutexPLastTxMeInstance.Unlock()
1360 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1361 log.Fields{"device-id": oFsm.deviceID})
1362 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1363 return
1364 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001365 //accept also nil as (error) return value for writing to LastTx
1366 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001367 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001368 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001369 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001370 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001371 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001372 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001373 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301374 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001375 return
1376 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001377 // Mark the gem port to be removed for Performance History monitoring
1378 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001379 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001380 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001381 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001382
1383 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001384 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301385 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001386}
1387
dbainbri4d3a0dc2020-12-02 00:33:42 +00001388func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001389 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1390 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001391 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001392 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1393 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001394 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001395
ozgecanetsia4b232302020-11-11 10:58:10 +03001396 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1397 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001398
1399 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001400 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001401 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001402 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001403 "InterworkingOption": 0, // Don't Care
1404 "ServiceProfilePointer": 0, // Don't Care
1405 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001406 },
1407 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001408 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001409 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001410 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001411 if err != nil {
1412 oFsm.mutexPLastTxMeInstance.Unlock()
1413 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1414 log.Fields{"device-id": oFsm.deviceID})
1415 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1416 return
1417
1418 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001419 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001420 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001421 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001422 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001423 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001424 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001425 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1426 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1427 return
1428 }
1429 ipv4MulticastTable := make([]uint8, 12)
1430 //Gem Port ID
1431 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1432 //Secondary Key
1433 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1434 // Multicast IP range start This is the 224.0.0.1 address
1435 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1436 // MulticastIp range stop
1437 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1438
1439 meIPV4MCTableParams := me.ParamData{
1440 EntityID: gemPortAttribs.multicastGemID,
1441 Attributes: me.AttributeValueMap{
1442 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1443 },
1444 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001445 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001446 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001447 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001448 if err != nil {
1449 oFsm.mutexPLastTxMeInstance.Unlock()
1450 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1451 log.Fields{"device-id": oFsm.deviceID})
1452 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1453 return
1454 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001455 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001456 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001457
1458 } else {
1459 meParams := me.ParamData{
1460 EntityID: gemPortAttribs.gemPortID,
1461 Attributes: me.AttributeValueMap{
1462 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1463 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1464 "ServiceProfilePointer": oFsm.mapperSP0ID,
1465 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1466 "GalProfilePointer": galEthernetEID,
1467 },
1468 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001469 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001470 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001471 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001472 if err != nil {
1473 oFsm.mutexPLastTxMeInstance.Unlock()
1474 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1475 log.Fields{"device-id": oFsm.deviceID})
1476 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1477 return
1478 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001479 //accept also nil as (error) return value for writing to LastTx
1480 // - this avoids misinterpretation of new received OMCI messages
1481 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001482 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001483 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001484 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001485 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001486 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001487 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001488 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301489 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001490 return
1491 }
1492 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001493
1494 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001495 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301496 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001497}
1498
dbainbri4d3a0dc2020-12-02 00:33:42 +00001499func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001500 //If upstream PQs were set before, then no need to set them again. Let state machine to proceed.
1501 if oFsm.tcontSetBefore {
1502 logger.Debugw(ctx, "No need to set PQs again.", log.Fields{
1503 "device-id": oFsm.deviceID, "tcont": oFsm.alloc0ID,
1504 "uni-id": oFsm.pOnuUniPort.uniID,
1505 "techProfile-id": oFsm.techProfileID})
1506 go func(aPAFsm *AdapterFsm) {
1507 if aPAFsm != nil && aPAFsm.pFsm != nil {
1508 _ = aPAFsm.pFsm.Event(aniEvRxPrioqsResp)
1509 }
1510 }(oFsm.pAdaptFsm)
1511 return
1512 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001513 const cu16StrictPrioWeight uint16 = 0xFFFF
1514 //find all upstream PrioQueues related to this T-Cont
1515 loQueueMap := ordered_map.NewOrderedMap()
1516 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001517 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001518 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001519 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1520 "prioString": gemPortAttribs.pbitString})
1521 continue
1522 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001523 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301524 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001525 //key does not yet exist
1526 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1527 }
1528 } else {
1529 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1530 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001531 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001532
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001533 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1534 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1535 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1536 // or even be finished without correct SP/WRR setting
1537
1538 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1539 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1540 // even though its T-Cont seems to be wrong ...
1541 loTrafficSchedulerEID := 0x8000
1542 //for all found queues
1543 iter := loQueueMap.IterFunc()
1544 for kv, ok := iter(); ok; kv, ok = iter() {
1545 queueIndex := (kv.Key).(uint16)
1546 meParams := me.ParamData{
1547 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301548 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001549 }
1550 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1551 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001552 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001553 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001554 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001555 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1556 } else {
1557 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001558 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001559 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1560 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001561 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001562 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1563 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1564 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001565 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001566 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001567 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001568 if err != nil {
1569 oFsm.mutexPLastTxMeInstance.Unlock()
1570 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1571 log.Fields{"device-id": oFsm.deviceID})
1572 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1573 return
1574 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001575 //accept also nil as (error) return value for writing to LastTx
1576 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001577 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001578 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001579
1580 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001581 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001582 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001583 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001584 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301585 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001586 return
1587 }
1588
1589 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1590 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1591 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1592 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1593
1594 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001595
1596 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001597 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301598 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001599}
1600
dbainbri4d3a0dc2020-12-02 00:33:42 +00001601func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001602 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001603 if oFsm.isCanceled {
1604 // FSM already canceled before entering wait
1605 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1606 oFsm.mutexIsAwaitingResponse.Unlock()
1607 return fmt.Errorf(cErrWaitAborted)
1608 }
mpagenko7d6bb022021-03-11 15:07:55 +00001609 oFsm.isAwaitingResponse = true
1610 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001611 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301612 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001613 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001614 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +00001615 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 +00001616 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001617 oFsm.mutexIsAwaitingResponse.Lock()
1618 oFsm.isAwaitingResponse = false
1619 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001620 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001621 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301622 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001623 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001624 oFsm.mutexIsAwaitingResponse.Lock()
1625 oFsm.isAwaitingResponse = false
1626 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001627 return nil
1628 }
mpagenko7d6bb022021-03-11 15:07:55 +00001629 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001630 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001631 oFsm.mutexIsAwaitingResponse.Lock()
1632 oFsm.isAwaitingResponse = false
1633 oFsm.mutexIsAwaitingResponse.Unlock()
1634 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001635 }
1636}
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001637
1638func (oFsm *uniPonAniConfigFsm) setChanSet(flagValue bool) {
1639 oFsm.mutexChanSet.Lock()
1640 oFsm.chanSet = flagValue
1641 oFsm.mutexChanSet.Unlock()
1642}
1643
1644func (oFsm *uniPonAniConfigFsm) isChanSet() bool {
1645 oFsm.mutexChanSet.RLock()
1646 flagValue := oFsm.chanSet
1647 oFsm.mutexChanSet.RUnlock()
1648 return flagValue
1649}