blob: e50bd58834f4f996d14ce3bf883327b3594ecbe7 [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}
1173
dbainbri4d3a0dc2020-12-02 00:33:42 +00001174func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301175 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1176 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001177 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001178 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301179 return
1180 }
1181 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1182 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001183 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001184 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301185 return
1186 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001187 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301188 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001189 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001190 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301191 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001192
1193 //FIXME: If setting TCONT fails we need to revert the DB back. Because of the concurency,
1194 //doing it here may cause a data inconsistency. To fix this problem we need to think on running
1195 //the FSMs of different UNIs sequentially instead of running them concurrently.
1196
Himani Chawla4d908332020-08-31 12:30:20 +05301197 return
1198 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001199 oFsm.mutexPLastTxMeInstance.RLock()
1200 if oFsm.pLastTxMeInstance != nil {
1201 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1202 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1203 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1204 // if, then something like:
1205 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301206
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001207 switch oFsm.pLastTxMeInstance.GetName() {
1208 case "TCont":
1209 { // let the FSM proceed ...
1210 oFsm.mutexPLastTxMeInstance.RUnlock()
1211 if oFsm.requestEventOffset == 0 { //from TCont config request
1212 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1213 } else { // from T-Cont reset request
1214 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1215 }
1216 }
1217 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1218 { // let the PrioQueue init proceed by stopping the wait function
1219 oFsm.mutexPLastTxMeInstance.RUnlock()
1220 oFsm.omciMIdsResponseReceived <- true
1221 }
1222 case "Ieee8021PMapperServiceProfile":
1223 { // let the FSM proceed ...
1224 oFsm.mutexPLastTxMeInstance.RUnlock()
1225 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1226 }
1227 default:
1228 {
1229 oFsm.mutexPLastTxMeInstance.RUnlock()
1230 logger.Warnw(ctx, "Unsupported ME name received!",
1231 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001232 }
Himani Chawla4d908332020-08-31 12:30:20 +05301233 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001234 } else {
1235 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301236 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001237 } else {
1238 oFsm.mutexPLastTxMeInstance.RUnlock()
1239 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301240 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001241}
1242
dbainbri4d3a0dc2020-12-02 00:33:42 +00001243func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001244 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1245 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001246 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001247 log.Fields{"device-id": oFsm.deviceID})
1248 return
1249 }
1250 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1251 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001252 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001253 log.Fields{"device-id": oFsm.deviceID})
1254 return
1255 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001256 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001257 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001258 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001259 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1260 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1261 // store error for mgmt display?
1262 return
1263 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001264 oFsm.mutexPLastTxMeInstance.RLock()
1265 if oFsm.pLastTxMeInstance != nil {
1266 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1267 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1268 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1269 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001270
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001271 switch oFsm.pLastTxMeInstance.GetName() {
1272 case "GemInterworkingTerminationPoint":
1273 { // let the FSM proceed ...
1274 oFsm.mutexPLastTxMeInstance.RUnlock()
1275 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1276 }
1277 case "GemPortNetworkCtp":
1278 { // let the FSM proceed ...
1279 oFsm.mutexPLastTxMeInstance.RUnlock()
1280 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1281 }
1282 case "Ieee8021PMapperServiceProfile":
1283 { // let the FSM proceed ...
1284 oFsm.mutexPLastTxMeInstance.RUnlock()
1285 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1286 }
1287 case "MacBridgePortConfigurationData":
1288 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1289 oFsm.mutexPLastTxMeInstance.RUnlock()
1290 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1291 }
1292 default:
1293 {
1294 oFsm.mutexPLastTxMeInstance.RUnlock()
1295 logger.Warnw(ctx, "Unsupported ME name received!",
1296 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1297 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001298 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001299 } else {
1300 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001301 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001302 } else {
1303 oFsm.mutexPLastTxMeInstance.RUnlock()
1304 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001305 }
1306}
1307
dbainbri4d3a0dc2020-12-02 00:33:42 +00001308func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1309 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001310 "msgType": msg.OmciMsg.MessageType})
1311
1312 switch msg.OmciMsg.MessageType {
1313 case omci.CreateResponseType:
1314 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001315 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301316
mpagenko3dbcdd22020-07-22 07:38:45 +00001317 } //CreateResponseType
1318 case omci.SetResponseType:
1319 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001320 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001321
mpagenko3dbcdd22020-07-22 07:38:45 +00001322 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001323 case omci.DeleteResponseType:
1324 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001325 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001326
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001327 } //DeleteResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001328 default:
1329 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001330 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001331 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001332 return
1333 }
1334 }
1335}
1336
dbainbri4d3a0dc2020-12-02 00:33:42 +00001337func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001338 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1339 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001340 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001341 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1342 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001343 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001344 meParams := me.ParamData{
1345 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1346 Attributes: me.AttributeValueMap{
1347 "PortId": gemPortAttribs.gemPortID,
1348 "TContPointer": oFsm.tcont0ID,
1349 "Direction": gemPortAttribs.direction,
1350 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1351 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1352 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1353 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1354 },
1355 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001356 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001357 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001358 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001359 if err != nil {
1360 oFsm.mutexPLastTxMeInstance.Unlock()
1361 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1362 log.Fields{"device-id": oFsm.deviceID})
1363 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1364 return
1365 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001366 //accept also nil as (error) return value for writing to LastTx
1367 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001368 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001369 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001370 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001371 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001372 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001373 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001374 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301375 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001376 return
1377 }
Girish Gowdra50e56422021-06-01 16:46:04 -07001378 // Mark the gem port to be added for Performance History monitoring
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001379 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001380 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001381 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001382 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001383
1384 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001385 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301386 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001387}
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001388func (oFsm *uniPonAniConfigFsm) hasMulticastGem(ctx context.Context) bool {
1389 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
1390 if gemPortAttribs.isMulticast {
1391 logger.Debugw(ctx, "Found multicast gem", log.Fields{"device-id": oFsm.deviceID})
1392 return true
1393 }
1394 }
1395 return false
1396}
mpagenko3dbcdd22020-07-22 07:38:45 +00001397
dbainbri4d3a0dc2020-12-02 00:33:42 +00001398func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001399 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1400 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001401 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001402 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1403 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001404 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001405
ozgecanetsia4b232302020-11-11 10:58:10 +03001406 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1407 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001408
1409 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001410 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001411 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001412 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001413 "InterworkingOption": 0, // Don't Care
1414 "ServiceProfilePointer": 0, // Don't Care
1415 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001416 },
1417 }
ozgecanetsia72e1c9f2021-05-26 17:26:29 +03001418 if oFsm.pUniTechProf.multicastConfiguredForOtherUniTps(ctx, oFsm.uniTpKey) {
1419 logger.Debugw(ctx, "MulticastGemInterworkingTP already exist", log.Fields{"device-id": oFsm.deviceID, "multicast-gem-id": gemPortAttribs.multicastGemID})
1420 continue
1421 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001422 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001423 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001424 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001425 if err != nil {
1426 oFsm.mutexPLastTxMeInstance.Unlock()
1427 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1428 log.Fields{"device-id": oFsm.deviceID})
1429 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1430 return
1431
1432 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001433 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001434 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001435 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001436 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001437 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001438 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001439 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1440 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1441 return
1442 }
1443 ipv4MulticastTable := make([]uint8, 12)
1444 //Gem Port ID
1445 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1446 //Secondary Key
1447 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1448 // Multicast IP range start This is the 224.0.0.1 address
1449 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1450 // MulticastIp range stop
1451 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1452
1453 meIPV4MCTableParams := me.ParamData{
1454 EntityID: gemPortAttribs.multicastGemID,
1455 Attributes: me.AttributeValueMap{
1456 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1457 },
1458 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001459 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001460 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001461 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001462 if err != nil {
1463 oFsm.mutexPLastTxMeInstance.Unlock()
1464 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1465 log.Fields{"device-id": oFsm.deviceID})
1466 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1467 return
1468 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001469 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001470 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001471
1472 } else {
1473 meParams := me.ParamData{
1474 EntityID: gemPortAttribs.gemPortID,
1475 Attributes: me.AttributeValueMap{
1476 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1477 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1478 "ServiceProfilePointer": oFsm.mapperSP0ID,
1479 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1480 "GalProfilePointer": galEthernetEID,
1481 },
1482 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001483 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001484 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001485 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001486 if err != nil {
1487 oFsm.mutexPLastTxMeInstance.Unlock()
1488 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1489 log.Fields{"device-id": oFsm.deviceID})
1490 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1491 return
1492 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001493 //accept also nil as (error) return value for writing to LastTx
1494 // - this avoids misinterpretation of new received OMCI messages
1495 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001496 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001497 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001498 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001499 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001500 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001501 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001502 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301503 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001504 return
1505 }
1506 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001507
1508 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001509 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301510 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001511}
1512
dbainbri4d3a0dc2020-12-02 00:33:42 +00001513func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Mahir Gunyel7f4483a2021-05-06 12:53:43 -07001514 //If upstream PQs were set before, then no need to set them again. Let state machine to proceed.
1515 if oFsm.tcontSetBefore {
1516 logger.Debugw(ctx, "No need to set PQs again.", log.Fields{
1517 "device-id": oFsm.deviceID, "tcont": oFsm.alloc0ID,
1518 "uni-id": oFsm.pOnuUniPort.uniID,
1519 "techProfile-id": oFsm.techProfileID})
1520 go func(aPAFsm *AdapterFsm) {
1521 if aPAFsm != nil && aPAFsm.pFsm != nil {
1522 _ = aPAFsm.pFsm.Event(aniEvRxPrioqsResp)
1523 }
1524 }(oFsm.pAdaptFsm)
1525 return
1526 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001527 const cu16StrictPrioWeight uint16 = 0xFFFF
1528 //find all upstream PrioQueues related to this T-Cont
1529 loQueueMap := ordered_map.NewOrderedMap()
1530 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001531 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001532 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001533 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1534 "prioString": gemPortAttribs.pbitString})
1535 continue
1536 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001537 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301538 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001539 //key does not yet exist
1540 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1541 }
1542 } else {
1543 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1544 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001545 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001546
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001547 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1548 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1549 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1550 // or even be finished without correct SP/WRR setting
1551
1552 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1553 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1554 // even though its T-Cont seems to be wrong ...
1555 loTrafficSchedulerEID := 0x8000
1556 //for all found queues
1557 iter := loQueueMap.IterFunc()
1558 for kv, ok := iter(); ok; kv, ok = iter() {
1559 queueIndex := (kv.Key).(uint16)
1560 meParams := me.ParamData{
1561 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301562 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001563 }
1564 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1565 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001566 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001567 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001568 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001569 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1570 } else {
1571 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001572 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001573 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1574 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001575 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001576 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1577 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1578 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001579 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001580 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001581 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 if err != nil {
1583 oFsm.mutexPLastTxMeInstance.Unlock()
1584 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1585 log.Fields{"device-id": oFsm.deviceID})
1586 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1587 return
1588 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001589 //accept also nil as (error) return value for writing to LastTx
1590 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001591 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001592 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001593
1594 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001595 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001596 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001597 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001598 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301599 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001600 return
1601 }
1602
1603 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1604 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1605 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1606 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1607
1608 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001609
1610 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001611 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301612 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001613}
1614
dbainbri4d3a0dc2020-12-02 00:33:42 +00001615func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001616 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001617 if oFsm.isCanceled {
1618 // FSM already canceled before entering wait
1619 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1620 oFsm.mutexIsAwaitingResponse.Unlock()
1621 return fmt.Errorf(cErrWaitAborted)
1622 }
mpagenko7d6bb022021-03-11 15:07:55 +00001623 oFsm.isAwaitingResponse = true
1624 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001625 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301626 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001627 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001628 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +00001629 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 +00001630 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001631 oFsm.mutexIsAwaitingResponse.Lock()
1632 oFsm.isAwaitingResponse = false
1633 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001634 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001635 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301636 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001637 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001638 oFsm.mutexIsAwaitingResponse.Lock()
1639 oFsm.isAwaitingResponse = false
1640 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001641 return nil
1642 }
mpagenko7d6bb022021-03-11 15:07:55 +00001643 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001644 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001645 oFsm.mutexIsAwaitingResponse.Lock()
1646 oFsm.isAwaitingResponse = false
1647 oFsm.mutexIsAwaitingResponse.Unlock()
1648 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001649 }
1650}
Holger Hildebrandt0da7e6f2021-05-12 13:08:43 +00001651
1652func (oFsm *uniPonAniConfigFsm) setChanSet(flagValue bool) {
1653 oFsm.mutexChanSet.Lock()
1654 oFsm.chanSet = flagValue
1655 oFsm.mutexChanSet.Unlock()
1656}
1657
1658func (oFsm *uniPonAniConfigFsm) isChanSet() bool {
1659 oFsm.mutexChanSet.RLock()
1660 flagValue := oFsm.chanSet
1661 oFsm.mutexChanSet.RUnlock()
1662 return flagValue
1663}