blob: 9cb7e4cbb83062d6f09f024e8dff5b38a8107a08 [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"
Girish Gowdra50e56422021-06-01 16:46:04 -070033 "github.com/opencord/voltha-lib-go/v5/pkg/log"
dbainbri4d3a0dc2020-12-02 00:33:42 +000034 //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
ozgecanetsia82b91a62021-05-21 18:54:49 +0300405
ozgecanetsia4b232302020-11-11 10:58:10 +0300406 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300407 //TODO this might effectively ignore the for loop starting at line 316
408 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300409 loGemPortAttribs.isMulticast = true
410 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
411 loGemPortAttribs.staticACL = gemEntry.staticACL
412 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530413
dbainbri4d3a0dc2020-12-02 00:33:42 +0000414 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300415 "gemPortID": loGemPortAttribs.gemPortID,
416 "isMulticast": loGemPortAttribs.isMulticast,
417 "multicastGemID": loGemPortAttribs.multicastGemID,
418 "staticACL": loGemPortAttribs.staticACL,
419 "dynamicACL": loGemPortAttribs.dynamicACL,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000420 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300421 })
422
423 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000424 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300425 "gemPortID": loGemPortAttribs.gemPortID,
426 "upQueueID": loGemPortAttribs.upQueueID,
427 "downQueueID": loGemPortAttribs.downQueueID,
428 "pbitString": loGemPortAttribs.pbitString,
429 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000430 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300431 })
432 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530433
434 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
435 }
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000436 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
437 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
438 } else {
439 logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"device-id": oFsm.deviceID})
440 _ = aPAFsm.pFsm.Event(aniEvSkipOmciConfig)
441 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530442 }
443}
444
dbainbri4d3a0dc2020-12-02 00:33:42 +0000445func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
446 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000447 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000448 // in case the used channel is not yet defined (can be re-used after restarts)
449 if oFsm.omciMIdsResponseReceived == nil {
450 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000451 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000452 } else {
453 // as we may 're-use' this instance of FSM and the connected channel
454 // make sure there is no 'lingering' request in the already existing channel:
455 // (simple loop sufficient as we are the only receiver)
456 for len(oFsm.omciMIdsResponseReceived) > 0 {
457 <-oFsm.omciMIdsResponseReceived
458 }
459 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000460 //ensure internal slices are empty (which might be set from previous run) - release memory
461 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000462 oFsm.mutexIsAwaitingResponse.Lock()
463 //reset the canceled state possibly existing from previous reset
464 oFsm.isCanceled = false
465 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000466
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000467 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000468 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000469
470 //let the state machine run forward from here directly
471 pConfigAniStateAFsm := oFsm.pAdaptFsm
472 if pConfigAniStateAFsm != nil {
473 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000474 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000475
mpagenko3dbcdd22020-07-22 07:38:45 +0000476 }
477}
478
dbainbri4d3a0dc2020-12-02 00:33:42 +0000479func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
480 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000481 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000482 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
483 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000484 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300485 meInstance, err := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000486 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300487 if err != nil {
488 logger.Errorw(ctx, "Dot1PMapper create failed, aborting uniPonAniConfigFsm!",
489 log.Fields{"device-id": oFsm.deviceID})
490 pConfigAniStateAFsm := oFsm.pAdaptFsm
491 if pConfigAniStateAFsm != nil {
492 oFsm.mutexPLastTxMeInstance.Unlock()
493 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
494 go func(aPAFsm *AdapterFsm) {
495 if aPAFsm != nil && aPAFsm.pFsm != nil {
496 _ = aPAFsm.pFsm.Event(aniEvReset)
497 }
498 }(pConfigAniStateAFsm)
499 return
500 }
501 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000502 //accept also nil as (error) return value for writing to LastTx
503 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000504 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300505 oFsm.mutexPLastTxMeInstance.Unlock()
506
mpagenko3dbcdd22020-07-22 07:38:45 +0000507}
508
dbainbri4d3a0dc2020-12-02 00:33:42 +0000509func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
510 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000511 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
512 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000513 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000514 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
515 meParams := me.ParamData{
516 EntityID: oFsm.macBPCD0ID,
517 Attributes: me.AttributeValueMap{
518 "BridgeIdPointer": bridgePtr,
519 "PortNum": 0xFF, //fixed unique ANI side indication
520 "TpType": 3, //for .1PMapper
521 "TpPointer": oFsm.mapperSP0ID,
522 },
523 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000524 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300525 meInstance, err := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000526 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300527 if err != nil {
528 logger.Errorw(ctx, "MBPConfigDataVar create failed, aborting uniPonAniConfigFsm!",
529 log.Fields{"device-id": oFsm.deviceID})
530 pConfigAniStateAFsm := oFsm.pAdaptFsm
531 if pConfigAniStateAFsm != nil {
532 oFsm.mutexPLastTxMeInstance.Unlock()
533 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
534 go func(aPAFsm *AdapterFsm) {
535 if aPAFsm != nil && aPAFsm.pFsm != nil {
536 _ = aPAFsm.pFsm.Event(aniEvReset)
537 }
538 }(pConfigAniStateAFsm)
539 return
540 }
541 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000542 //accept also nil as (error) return value for writing to LastTx
543 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000544 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300545 oFsm.mutexPLastTxMeInstance.Unlock()
546
mpagenko3dbcdd22020-07-22 07:38:45 +0000547}
548
dbainbri4d3a0dc2020-12-02 00:33:42 +0000549func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
550 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000551 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
552 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
Mahir Gunyel7f4483a2021-05-06 12:53:43 -0700553 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
554 "tcontExist": oFsm.tcontSetBefore})
555 //If tcont was set before, then no need to set it again. Let state machine to proceed.
556 if oFsm.tcontSetBefore {
557 go func(aPAFsm *AdapterFsm) {
558 if aPAFsm != nil && aPAFsm.pFsm != nil {
559 _ = aPAFsm.pFsm.Event(aniEvRxTcontsResp)
560 }
561 }(oFsm.pAdaptFsm)
562 return
563 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000564 meParams := me.ParamData{
565 EntityID: oFsm.tcont0ID,
566 Attributes: me.AttributeValueMap{
567 "AllocId": oFsm.alloc0ID,
568 },
569 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000570 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300571 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000572 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300573 if err != nil {
574 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
575 log.Fields{"device-id": oFsm.deviceID})
576 pConfigAniStateAFsm := oFsm.pAdaptFsm
577 if pConfigAniStateAFsm != nil {
578 oFsm.mutexPLastTxMeInstance.Unlock()
579 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
580 go func(aPAFsm *AdapterFsm) {
581 if aPAFsm != nil && aPAFsm.pFsm != nil {
582 _ = aPAFsm.pFsm.Event(aniEvReset)
583 }
584 }(pConfigAniStateAFsm)
585 return
586 }
587 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000588 //accept also nil as (error) return value for writing to LastTx
589 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000590 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300591 oFsm.mutexPLastTxMeInstance.Unlock()
592
mpagenko3dbcdd22020-07-22 07:38:45 +0000593}
594
dbainbri4d3a0dc2020-12-02 00:33:42 +0000595func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
596 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000597 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000598 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000599}
600
dbainbri4d3a0dc2020-12-02 00:33:42 +0000601func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
602 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000603 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000604 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000605}
606
dbainbri4d3a0dc2020-12-02 00:33:42 +0000607func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
608 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000609 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000610 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000611}
612
dbainbri4d3a0dc2020-12-02 00:33:42 +0000613func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300614
dbainbri4d3a0dc2020-12-02 00:33:42 +0000615 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000616 "toGemIw": 1024, /* cmp above */
617 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000618
dbainbri4d3a0dc2020-12-02 00:33:42 +0000619 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000620 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000621 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000622
mpagenko3dbcdd22020-07-22 07:38:45 +0000623 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000624 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530625 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000626 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000627
628 //assign the GemPorts according to the configured Prio
629 var loPrioGemPortArray [8]uint16
630 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300631 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000632 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300633 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
634 "prioString": gemPortAttribs.pbitString})
635 continue
636 }
637 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000638 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300639 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
640 "prioString": gemPortAttribs.pbitString})
641 continue
642 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000643 for i := 0; i < 8; i++ {
644 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
645 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
646 if prio == 1 { // Check this p-bit is set
647 if loPrioGemPortArray[i] == 0 {
648 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
649 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000650 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000651 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000652 "SetGemPort": loPrioGemPortArray[i]})
653 }
654 }
655 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000656 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000657 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000658 "prioString": gemPortAttribs.pbitString, "position": i})
659 }
660
661 }
662 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300663
ozgecanetsia4b232302020-11-11 10:58:10 +0300664 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530665 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300666 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530667 if value != 0 {
668 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530669 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000670 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000671 "for Prio": index,
672 "IwPtr": strconv.FormatInt(int64(value), 16),
673 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300674 } else {
675 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000676 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
677 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300678 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530679 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000680 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300681 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000682 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
683 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300684 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530685
686 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000687 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000688 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300689 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
690 // 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 +0000691 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300692 //pConfigAniStateAFsm := oFsm.pAdaptFsm
693 //if pConfigAniStateAFsm != nil {
694 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
695 // go func(aPAFsm *AdapterFsm) {
696 // if aPAFsm != nil && aPAFsm.pFsm != nil {
697 // _ = aPAFsm.pFsm.Event(aniEvReset)
698 // }
699 // }(pConfigAniStateAFsm)
700 //}
701 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000702 pConfigAniStateAFsm := oFsm.pAdaptFsm
703 if pConfigAniStateAFsm != nil {
704 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530705 go func(aPAFsm *AdapterFsm) {
706 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300707 _ = aPAFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000708 }
709 }(pConfigAniStateAFsm)
710 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300711 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000712 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300713 meInstance, err := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300714 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300715 if err != nil {
716 logger.Errorw(ctx, "Dot1PMapperVar set failed, aborting uniPonAniConfigFsm!",
717 log.Fields{"device-id": oFsm.deviceID})
718 pConfigAniStateAFsm := oFsm.pAdaptFsm
719 if pConfigAniStateAFsm != nil {
720 oFsm.mutexPLastTxMeInstance.Unlock()
721 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
722 go func(aPAFsm *AdapterFsm) {
723 if aPAFsm != nil && aPAFsm.pFsm != nil {
724 _ = aPAFsm.pFsm.Event(aniEvReset)
725 }
726 }(pConfigAniStateAFsm)
727 return
728 }
729 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300730 //accept also nil as (error) return value for writing to LastTx
731 // - this avoids misinterpretation of new received OMCI messages
732 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300733 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000734 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000735}
736
dbainbri4d3a0dc2020-12-02 00:33:42 +0000737func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
738 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000739 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000740 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800741 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000742 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
743 //use DeviceHandler event notification directly
744 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
745 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
746 // but only in case the techProfile was configured (not deleted)
747 if oFsm.requestEventOffset == 0 {
748 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
749 }
750 } else {
751 logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000752 }
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000753 if oFsm.isChanSet() {
mpagenko01e726e2020-10-23 09:45:29 +0000754 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000755 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000756 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
757 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +0000758 oFsm.setChanSet(false) //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000759 }
mpagenko01e726e2020-10-23 09:45:29 +0000760
761 //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 +0000762}
763
dbainbri4d3a0dc2020-12-02 00:33:42 +0000764func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000765 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000766 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
767 select {
768 case <-oFsm.waitFlowDeleteChannel:
769 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
770 default:
771 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000772
773 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID] != nil {
774 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
775 oFsm.pUniTechProf.mutexTPState.Unlock()
776 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
777 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
778 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
779 pConfigAniStateAFsm := oFsm.pAdaptFsm
780 if pConfigAniStateAFsm != nil {
781 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
782 go func(aPAFsm *AdapterFsm) {
783 if aPAFsm != nil && aPAFsm.pFsm != nil {
784 _ = aPAFsm.pFsm.Event(aniEvWaitFlowRem)
785 }
786 }(pConfigAniStateAFsm)
787 } else {
788 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
789 }
790 return
Girish Gowdra26a40922021-01-29 17:14:34 -0800791 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000792 } else {
793 logger.Debugw(ctx, "uni vlan config doesn't exist - no flow remove could be pending",
794 log.Fields{"device-id": oFsm.deviceID, "techProfile-id": oFsm.techProfileID})
Girish Gowdra26a40922021-01-29 17:14:34 -0800795 }
796
mpagenko8b07c1b2020-11-26 10:36:31 +0000797 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000798 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
799 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000800 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000801 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
802 "GemIwTp-entity-id": loGemPortID})
803 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
804
805 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000806 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300807 meInstance, err := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000808 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300809 if err != nil {
810 logger.Errorw(ctx, "GemIWTP delete failed, aborting uniPonAniConfigFsm!",
811 log.Fields{"device-id": oFsm.deviceID})
812 pConfigAniStateAFsm := oFsm.pAdaptFsm
813 if pConfigAniStateAFsm != nil {
814 oFsm.mutexPLastTxMeInstance.Unlock()
815 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
816 go func(aPAFsm *AdapterFsm) {
817 if aPAFsm != nil && aPAFsm.pFsm != nil {
818 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
819 }
820 }(pConfigAniStateAFsm)
821 return
822 }
823 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000824 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300825 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000826}
827
mpagenkobb47bc22021-04-20 13:29:09 +0000828func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
829 oFsm.mutexIsAwaitingResponse.Lock()
830 oFsm.isWaitingForFlowDelete = true
831 oFsm.mutexIsAwaitingResponse.Unlock()
832 select {
833 // maybe be also some outside cancel (but no context modeled for the moment ...)
834 // case <-ctx.Done():
835 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000836 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 +0000837 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
838 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
839 oFsm.mutexIsAwaitingResponse.Lock()
840 oFsm.isWaitingForFlowDelete = false
841 oFsm.mutexIsAwaitingResponse.Unlock()
842 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
843 pConfigAniStateAFsm := oFsm.pAdaptFsm
844 if pConfigAniStateAFsm != nil {
845 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
846 go func(aPAFsm *AdapterFsm) {
847 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300848 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000849 }
850 }(pConfigAniStateAFsm)
851 } else {
852 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
853 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
854 }
855 return
856
857 case success := <-oFsm.waitFlowDeleteChannel:
858 if success {
859 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
860 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
861 oFsm.mutexIsAwaitingResponse.Lock()
862 oFsm.isWaitingForFlowDelete = false
863 oFsm.mutexIsAwaitingResponse.Unlock()
864 pConfigAniStateAFsm := oFsm.pAdaptFsm
865 if pConfigAniStateAFsm != nil {
866 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
867 go func(aPAFsm *AdapterFsm) {
868 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300869 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000870 }
871 }(pConfigAniStateAFsm)
872 } else {
873 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
874 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
875 }
876 return
877 }
878 // waiting was aborted (probably on external request)
879 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
880 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
881 oFsm.mutexIsAwaitingResponse.Lock()
882 oFsm.isWaitingForFlowDelete = false
883 oFsm.mutexIsAwaitingResponse.Unlock()
884 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
885 pConfigAniStateAFsm := oFsm.pAdaptFsm
886 if pConfigAniStateAFsm != nil {
887 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
888 go func(aPAFsm *AdapterFsm) {
889 if aPAFsm != nil && aPAFsm.pFsm != nil {
890 _ = aPAFsm.pFsm.Event(aniEvReset)
891 }
892 }(pConfigAniStateAFsm)
893 }
894 return
895 }
896}
897
dbainbri4d3a0dc2020-12-02 00:33:42 +0000898func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000899 oFsm.pUniTechProf.mutexTPState.Lock()
900 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
901 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000902 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000903 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
904 "GemNCTP-entity-id": loGemPortID})
905 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000906 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300907 meInstance, err := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000908 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300909 if err != nil {
910 logger.Errorw(ctx, "GemNCTP delete failed, aborting uniPonAniConfigFsm!",
911 log.Fields{"device-id": oFsm.deviceID})
912 pConfigAniStateAFsm := oFsm.pAdaptFsm
913 if pConfigAniStateAFsm != nil {
914 oFsm.mutexPLastTxMeInstance.Unlock()
915 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
916 go func(aPAFsm *AdapterFsm) {
917 if aPAFsm != nil && aPAFsm.pFsm != nil {
918 _ = aPAFsm.pFsm.Event(aniEvReset)
919 }
920 }(pConfigAniStateAFsm)
921 return
922 }
923 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000924 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000925 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300926
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800927 // Mark the gem port to be removed for Performance History monitoring
928 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700929 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800930 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000931}
932
dbainbri4d3a0dc2020-12-02 00:33:42 +0000933func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
934 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000935 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
936
937 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
938 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
939 meParams := me.ParamData{
940 EntityID: oFsm.tcont0ID,
941 Attributes: me.AttributeValueMap{
942 "AllocId": unusedTcontAllocID,
943 },
944 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000945 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300946 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000947 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300948 if err != nil {
949 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
950 log.Fields{"device-id": oFsm.deviceID})
951 pConfigAniStateAFsm := oFsm.pAdaptFsm
952 if pConfigAniStateAFsm != nil {
953 oFsm.mutexPLastTxMeInstance.Unlock()
954 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
955 go func(aPAFsm *AdapterFsm) {
956 if aPAFsm != nil && aPAFsm.pFsm != nil {
957 _ = aPAFsm.pFsm.Event(aniEvReset)
958 }
959 }(pConfigAniStateAFsm)
960 return
961 }
962 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000963 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300964 oFsm.mutexPLastTxMeInstance.Unlock()
965
mpagenko8b07c1b2020-11-26 10:36:31 +0000966}
967
dbainbri4d3a0dc2020-12-02 00:33:42 +0000968func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
969 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000970 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
971
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000972 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300973 meInstance, err := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000974 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300975 if err != nil {
976 logger.Errorw(ctx, "Dot1Mapper delete failed, aborting uniPonAniConfigFsm!",
977 log.Fields{"device-id": oFsm.deviceID})
978 pConfigAniStateAFsm := oFsm.pAdaptFsm
979 if pConfigAniStateAFsm != nil {
980 oFsm.mutexPLastTxMeInstance.Unlock()
981 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
982 go func(aPAFsm *AdapterFsm) {
983 if aPAFsm != nil && aPAFsm.pFsm != nil {
984 _ = aPAFsm.pFsm.Event(aniEvReset)
985 }
986 }(pConfigAniStateAFsm)
987 return
988 }
989 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000990 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300991 oFsm.mutexPLastTxMeInstance.Unlock()
992
mpagenko8b07c1b2020-11-26 10:36:31 +0000993}
994
dbainbri4d3a0dc2020-12-02 00:33:42 +0000995func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
996 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000997 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
998
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000999 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001000 meInstance, err := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001001 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001002 if err != nil {
1003 logger.Errorw(ctx, "MBPConfigData delete failed, aborting uniPonAniConfigFsm!",
1004 log.Fields{"device-id": oFsm.deviceID})
1005 pConfigAniStateAFsm := oFsm.pAdaptFsm
1006 if pConfigAniStateAFsm != nil {
1007 oFsm.mutexPLastTxMeInstance.Unlock()
1008 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1009 go func(aPAFsm *AdapterFsm) {
1010 if aPAFsm != nil && aPAFsm.pFsm != nil {
1011 _ = aPAFsm.pFsm.Event(aniEvReset)
1012 }
1013 }(pConfigAniStateAFsm)
1014 return
1015 }
1016 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001017 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001018 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001019}
1020
dbainbri4d3a0dc2020-12-02 00:33:42 +00001021func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
1022 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001023 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1024 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001025 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001026 if oFsm.isChanSet() {
mpagenko8b07c1b2020-11-26 10:36:31 +00001027 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +00001028 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001029 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
1030 oFsm.chSuccess <- oFsm.procStep
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001031 oFsm.setChanSet(false) //reset the internal channel state
mpagenko8b07c1b2020-11-26 10:36:31 +00001032 }
1033
1034 //let's reset the state machine in order to release all resources now
1035 pConfigAniStateAFsm := oFsm.pAdaptFsm
1036 if pConfigAniStateAFsm != nil {
1037 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1038 go func(aPAFsm *AdapterFsm) {
1039 if aPAFsm != nil && aPAFsm.pFsm != nil {
1040 _ = aPAFsm.pFsm.Event(aniEvReset)
1041 }
1042 }(pConfigAniStateAFsm)
1043 }
1044}
1045
dbainbri4d3a0dc2020-12-02 00:33:42 +00001046func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
1047 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001048 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001049
mpagenko3dbcdd22020-07-22 07:38:45 +00001050 pConfigAniStateAFsm := oFsm.pAdaptFsm
1051 if pConfigAniStateAFsm != nil {
1052 // abort running message processing
1053 fsmAbortMsg := Message{
1054 Type: TestMsg,
1055 Data: TestMessage{
1056 TestMessageVal: AbortMessageProcessing,
1057 },
1058 }
1059 pConfigAniStateAFsm.commChan <- fsmAbortMsg
1060
1061 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +05301062 go func(aPAFsm *AdapterFsm) {
1063 if aPAFsm != nil && aPAFsm.pFsm != nil {
1064 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +00001065 }
1066 }(pConfigAniStateAFsm)
1067 }
1068}
1069
dbainbri4d3a0dc2020-12-02 00:33:42 +00001070func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
1071 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001072 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001073 oFsm.mutexPLastTxMeInstance.Lock()
1074 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001075 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +00001076}
1077
dbainbri4d3a0dc2020-12-02 00:33:42 +00001078func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
1079 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001080loop:
1081 for {
mpagenko3dbcdd22020-07-22 07:38:45 +00001082 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001083 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001084 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301085 message, ok := <-oFsm.pAdaptFsm.commChan
1086 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001087 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301088 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1089 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1090 break loop
1091 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001092 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301093
1094 switch message.Type {
1095 case TestMsg:
1096 msg, _ := message.Data.(TestMessage)
1097 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001098 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001099 break loop
1100 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001101 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301102 case OMCI:
1103 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001104 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301105 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001106 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301107 "message.Type": message.Type})
1108 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001109
Himani Chawla4d908332020-08-31 12:30:20 +05301110 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001111 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301112}
1113
dbainbri4d3a0dc2020-12-02 00:33:42 +00001114func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301115 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
1116 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001117 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001118 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301119 return
1120 }
1121 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1122 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001123 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001124 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301125 return
1126 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001127 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +00001128 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1129 //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 +00001130 oFsm.mutexPLastTxMeInstance.RLock()
1131 if oFsm.pLastTxMeInstance != nil {
1132 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1133 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1134 // maybe we can use just the same eventName for different state transitions like "forward"
1135 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1136 switch oFsm.pLastTxMeInstance.GetName() {
1137 case "Ieee8021PMapperServiceProfile":
1138 { // let the FSM proceed ...
1139 oFsm.mutexPLastTxMeInstance.RUnlock()
1140 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1141 }
1142 case "MacBridgePortConfigurationData":
1143 { // let the FSM proceed ...
1144 oFsm.mutexPLastTxMeInstance.RUnlock()
1145 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1146 }
1147 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1148 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1149 oFsm.mutexPLastTxMeInstance.RUnlock()
1150 oFsm.omciMIdsResponseReceived <- true
1151 }
1152 default:
1153 {
1154 oFsm.mutexPLastTxMeInstance.RUnlock()
1155 logger.Warnw(ctx, "Unsupported ME name received!",
1156 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1157 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001158 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001159 } else {
1160 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001161 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001162 } else {
1163 oFsm.mutexPLastTxMeInstance.RUnlock()
1164 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001165 }
1166 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001167 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1168 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301169 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1170 return
1171 }
Himani Chawla4d908332020-08-31 12:30:20 +05301172}
Mahir Gunyel01034b62021-06-29 11:25:09 -07001173func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetFailResponseMessage(ctx context.Context, msgObj *omci.SetResponse) {
1174 //If TCONT fails, then we need to revert the allocated TCONT in DB.
1175 //Because FSMs are running sequentially, we don't expect the same TCONT hit by another tech-profile FSM while this FSM is running.
1176 oFsm.mutexPLastTxMeInstance.RLock()
1177 defer oFsm.mutexPLastTxMeInstance.RUnlock()
1178 if oFsm.pLastTxMeInstance != nil && msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1179 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1180 switch oFsm.pLastTxMeInstance.GetName() {
1181 case "TCont":
1182 //If this is for TCONT creation(requestEventOffset=0) and this is the first allocation of TCONT(so noone else is using the same TCONT)
1183 //We should revert DB
1184 if oFsm.requestEventOffset == 0 && !oFsm.tcontSetBefore && oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey] != nil {
1185 logger.Debugw(ctx, "UniPonAniConfigFsm TCONT creation failed on device. Freeing alloc id", log.Fields{"device-id": oFsm.deviceID,
1186 "alloc-id": oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID, "uni-tp": oFsm.uniTpKey})
1187 if pDevEntry := oFsm.pDeviceHandler.getOnuDeviceEntry(ctx, false); pDevEntry != nil {
1188 pDevEntry.freeTcont(ctx, oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID)
1189 } else {
1190 logger.Warnw(ctx, "Unable to get device entry! couldn't free tcont",
1191 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1192 }
1193 }
1194 default:
1195 logger.Warnw(ctx, "Unsupported ME name received with error!",
1196 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "result": msgObj.Result, "device-id": oFsm.deviceID})
1197 }
1198 }
1199}
dbainbri4d3a0dc2020-12-02 00:33:42 +00001200func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301201 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1202 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001203 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001204 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301205 return
1206 }
1207 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1208 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001209 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001210 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301211 return
1212 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001213 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301214 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001215 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001216 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301217 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001218
Mahir Gunyel01034b62021-06-29 11:25:09 -07001219 oFsm.handleOmciAniConfigSetFailResponseMessage(ctx, msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301220 return
1221 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001222 oFsm.mutexPLastTxMeInstance.RLock()
1223 if oFsm.pLastTxMeInstance != nil {
1224 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1225 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1226 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1227 // if, then something like:
1228 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301229
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001230 switch oFsm.pLastTxMeInstance.GetName() {
1231 case "TCont":
1232 { // let the FSM proceed ...
1233 oFsm.mutexPLastTxMeInstance.RUnlock()
1234 if oFsm.requestEventOffset == 0 { //from TCont config request
1235 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1236 } else { // from T-Cont reset request
1237 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1238 }
1239 }
1240 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1241 { // let the PrioQueue init proceed by stopping the wait function
1242 oFsm.mutexPLastTxMeInstance.RUnlock()
1243 oFsm.omciMIdsResponseReceived <- true
1244 }
1245 case "Ieee8021PMapperServiceProfile":
1246 { // let the FSM proceed ...
1247 oFsm.mutexPLastTxMeInstance.RUnlock()
1248 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1249 }
1250 default:
1251 {
1252 oFsm.mutexPLastTxMeInstance.RUnlock()
1253 logger.Warnw(ctx, "Unsupported ME name received!",
1254 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001255 }
Himani Chawla4d908332020-08-31 12:30:20 +05301256 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001257 } else {
1258 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301259 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001260 } else {
1261 oFsm.mutexPLastTxMeInstance.RUnlock()
1262 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301263 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001264}
1265
dbainbri4d3a0dc2020-12-02 00:33:42 +00001266func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001267 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1268 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001269 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001270 log.Fields{"device-id": oFsm.deviceID})
1271 return
1272 }
1273 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1274 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001275 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001276 log.Fields{"device-id": oFsm.deviceID})
1277 return
1278 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001279 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001280 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001281 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001282 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1283 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1284 // store error for mgmt display?
1285 return
1286 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001287 oFsm.mutexPLastTxMeInstance.RLock()
1288 if oFsm.pLastTxMeInstance != nil {
1289 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1290 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1291 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1292 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001293
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001294 switch oFsm.pLastTxMeInstance.GetName() {
1295 case "GemInterworkingTerminationPoint":
1296 { // let the FSM proceed ...
1297 oFsm.mutexPLastTxMeInstance.RUnlock()
1298 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1299 }
1300 case "GemPortNetworkCtp":
1301 { // let the FSM proceed ...
1302 oFsm.mutexPLastTxMeInstance.RUnlock()
1303 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1304 }
1305 case "Ieee8021PMapperServiceProfile":
1306 { // let the FSM proceed ...
1307 oFsm.mutexPLastTxMeInstance.RUnlock()
1308 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1309 }
1310 case "MacBridgePortConfigurationData":
1311 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1312 oFsm.mutexPLastTxMeInstance.RUnlock()
1313 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1314 }
1315 default:
1316 {
1317 oFsm.mutexPLastTxMeInstance.RUnlock()
1318 logger.Warnw(ctx, "Unsupported ME name received!",
1319 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1320 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001321 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001322 } else {
1323 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001324 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001325 } else {
1326 oFsm.mutexPLastTxMeInstance.RUnlock()
1327 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001328 }
1329}
1330
dbainbri4d3a0dc2020-12-02 00:33:42 +00001331func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1332 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001333 "msgType": msg.OmciMsg.MessageType})
1334
1335 switch msg.OmciMsg.MessageType {
1336 case omci.CreateResponseType:
1337 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001338 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301339
mpagenko3dbcdd22020-07-22 07:38:45 +00001340 } //CreateResponseType
1341 case omci.SetResponseType:
1342 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001343 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001344
mpagenko3dbcdd22020-07-22 07:38:45 +00001345 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001346 case omci.DeleteResponseType:
1347 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001348 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001349
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001350 } //DeleteResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001351 default:
1352 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001353 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001354 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001355 return
1356 }
1357 }
1358}
1359
dbainbri4d3a0dc2020-12-02 00:33:42 +00001360func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001361 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1362 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001363 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001364 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1365 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001366 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001367 meParams := me.ParamData{
1368 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1369 Attributes: me.AttributeValueMap{
1370 "PortId": gemPortAttribs.gemPortID,
1371 "TContPointer": oFsm.tcont0ID,
1372 "Direction": gemPortAttribs.direction,
1373 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1374 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1375 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1376 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1377 },
1378 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001379 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001380 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001381 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001382 if err != nil {
1383 oFsm.mutexPLastTxMeInstance.Unlock()
1384 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1385 log.Fields{"device-id": oFsm.deviceID})
1386 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1387 return
1388 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001389 //accept also nil as (error) return value for writing to LastTx
1390 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001391 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001392 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001393 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001394 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001395 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001396 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001397 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301398 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001399 return
1400 }
Girish Gowdra50e56422021-06-01 16:46:04 -07001401 // Mark the gem port to be added for Performance History monitoring
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001402 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001403 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001404 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001405 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001406
1407 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001408 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301409 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001410}
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001411func (oFsm *uniPonAniConfigFsm) hasMulticastGem(ctx context.Context) bool {
1412 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
1413 if gemPortAttribs.isMulticast {
1414 logger.Debugw(ctx, "Found multicast gem", log.Fields{"device-id": oFsm.deviceID})
1415 return true
1416 }
1417 }
1418 return false
1419}
mpagenko3dbcdd22020-07-22 07:38:45 +00001420
dbainbri4d3a0dc2020-12-02 00:33:42 +00001421func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001422 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1423 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001424 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001425 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1426 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001427 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001428
ozgecanetsia4b232302020-11-11 10:58:10 +03001429 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1430 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001431
1432 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001433 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001434 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001435 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001436 "InterworkingOption": 0, // Don't Care
1437 "ServiceProfilePointer": 0, // Don't Care
1438 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001439 },
1440 }
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001441 if oFsm.pUniTechProf.multicastConfiguredForOtherUniTps(ctx, oFsm.uniTpKey) {
1442 logger.Debugw(ctx, "MulticastGemInterworkingTP already exist", log.Fields{"device-id": oFsm.deviceID, "multicast-gem-id": gemPortAttribs.multicastGemID})
1443 continue
1444 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001445 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001446 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001447 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001448 if err != nil {
1449 oFsm.mutexPLastTxMeInstance.Unlock()
1450 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1451 log.Fields{"device-id": oFsm.deviceID})
1452 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1453 return
1454
1455 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001456 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001457 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001458 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001459 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001460 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001461 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001462 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1463 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1464 return
1465 }
1466 ipv4MulticastTable := make([]uint8, 12)
1467 //Gem Port ID
1468 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1469 //Secondary Key
1470 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1471 // Multicast IP range start This is the 224.0.0.1 address
1472 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1473 // MulticastIp range stop
1474 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1475
1476 meIPV4MCTableParams := me.ParamData{
1477 EntityID: gemPortAttribs.multicastGemID,
1478 Attributes: me.AttributeValueMap{
1479 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1480 },
1481 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001482 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001483 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001484 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001485 if err != nil {
1486 oFsm.mutexPLastTxMeInstance.Unlock()
1487 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1488 log.Fields{"device-id": oFsm.deviceID})
1489 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1490 return
1491 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001492 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001493 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001494
1495 } else {
1496 meParams := me.ParamData{
1497 EntityID: gemPortAttribs.gemPortID,
1498 Attributes: me.AttributeValueMap{
1499 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1500 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1501 "ServiceProfilePointer": oFsm.mapperSP0ID,
1502 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1503 "GalProfilePointer": galEthernetEID,
1504 },
1505 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001506 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001507 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001508 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001509 if err != nil {
1510 oFsm.mutexPLastTxMeInstance.Unlock()
1511 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1512 log.Fields{"device-id": oFsm.deviceID})
1513 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1514 return
1515 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001516 //accept also nil as (error) return value for writing to LastTx
1517 // - this avoids misinterpretation of new received OMCI messages
1518 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001519 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001520 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001521 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001522 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001523 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001524 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001525 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301526 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001527 return
1528 }
1529 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001530
1531 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001532 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301533 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001534}
1535
dbainbri4d3a0dc2020-12-02 00:33:42 +00001536func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001537 //If upstream PQs were set before, then no need to set them again. Let state machine to proceed.
1538 if oFsm.tcontSetBefore {
1539 logger.Debugw(ctx, "No need to set PQs again.", log.Fields{
1540 "device-id": oFsm.deviceID, "tcont": oFsm.alloc0ID,
1541 "uni-id": oFsm.pOnuUniPort.uniID,
1542 "techProfile-id": oFsm.techProfileID})
1543 go func(aPAFsm *AdapterFsm) {
1544 if aPAFsm != nil && aPAFsm.pFsm != nil {
1545 _ = aPAFsm.pFsm.Event(aniEvRxPrioqsResp)
1546 }
1547 }(oFsm.pAdaptFsm)
1548 return
1549 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001550 const cu16StrictPrioWeight uint16 = 0xFFFF
1551 //find all upstream PrioQueues related to this T-Cont
1552 loQueueMap := ordered_map.NewOrderedMap()
1553 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001554 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001555 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001556 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1557 "prioString": gemPortAttribs.pbitString})
1558 continue
1559 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001560 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301561 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001562 //key does not yet exist
1563 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1564 }
1565 } else {
1566 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1567 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001568 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001569
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001570 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1571 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1572 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1573 // or even be finished without correct SP/WRR setting
1574
1575 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1576 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1577 // even though its T-Cont seems to be wrong ...
1578 loTrafficSchedulerEID := 0x8000
1579 //for all found queues
1580 iter := loQueueMap.IterFunc()
1581 for kv, ok := iter(); ok; kv, ok = iter() {
1582 queueIndex := (kv.Key).(uint16)
1583 meParams := me.ParamData{
1584 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301585 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001586 }
1587 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1588 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001589 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001590 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001591 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001592 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1593 } else {
1594 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001595 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001596 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1597 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001598 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001599 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1600 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1601 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001602 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001603 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001604 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001605 if err != nil {
1606 oFsm.mutexPLastTxMeInstance.Unlock()
1607 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1608 log.Fields{"device-id": oFsm.deviceID})
1609 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1610 return
1611 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001612 //accept also nil as (error) return value for writing to LastTx
1613 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001614 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001615 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001616
1617 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001618 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001619 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001620 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001621 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301622 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001623 return
1624 }
1625
1626 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1627 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1628 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1629 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1630
1631 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001632
1633 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001634 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301635 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001636}
1637
dbainbri4d3a0dc2020-12-02 00:33:42 +00001638func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001639 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001640 if oFsm.isCanceled {
1641 // FSM already canceled before entering wait
1642 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1643 oFsm.mutexIsAwaitingResponse.Unlock()
1644 return fmt.Errorf(cErrWaitAborted)
1645 }
mpagenko7d6bb022021-03-11 15:07:55 +00001646 oFsm.isAwaitingResponse = true
1647 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001648 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301649 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001650 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001651 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +00001652 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 +00001653 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001654 oFsm.mutexIsAwaitingResponse.Lock()
1655 oFsm.isAwaitingResponse = false
1656 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001657 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001658 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301659 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001660 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001661 oFsm.mutexIsAwaitingResponse.Lock()
1662 oFsm.isAwaitingResponse = false
1663 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001664 return nil
1665 }
mpagenko7d6bb022021-03-11 15:07:55 +00001666 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001667 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001668 oFsm.mutexIsAwaitingResponse.Lock()
1669 oFsm.isAwaitingResponse = false
1670 oFsm.mutexIsAwaitingResponse.Unlock()
1671 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001672 }
1673}
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001674
1675func (oFsm *uniPonAniConfigFsm) setChanSet(flagValue bool) {
1676 oFsm.mutexChanSet.Lock()
1677 oFsm.chanSet = flagValue
1678 oFsm.mutexChanSet.Unlock()
1679}
1680
1681func (oFsm *uniPonAniConfigFsm) isChanSet() bool {
1682 oFsm.mutexChanSet.RLock()
1683 flagValue := oFsm.chanSet
1684 oFsm.mutexChanSet.RUnlock()
1685 return flagValue
1686}