blob: c7433c80c9dd2a94ebd6a17db39572919f012e77 [file] [log] [blame]
mpagenko3dbcdd22020-07-22 07:38:45 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
ozgecanetsia4b232302020-11-11 10:58:10 +030022 "encoding/binary"
Himani Chawla4d908332020-08-31 12:30:20 +053023 "fmt"
ozgecanetsia4b232302020-11-11 10:58:10 +030024 "net"
mpagenko3dbcdd22020-07-22 07:38:45 +000025 "strconv"
mpagenko7d6bb022021-03-11 15:07:55 +000026 "sync"
mpagenko3dbcdd22020-07-22 07:38:45 +000027 "time"
28
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000029 "github.com/cevaris/ordered_map"
mpagenko3dbcdd22020-07-22 07:38:45 +000030 "github.com/looplab/fsm"
mpagenko3dbcdd22020-07-22 07:38:45 +000031 "github.com/opencord/omci-lib-go"
32 me "github.com/opencord/omci-lib-go/generated"
dbainbri4d3a0dc2020-12-02 00:33:42 +000033 "github.com/opencord/voltha-lib-go/v4/pkg/log"
34 //ic "github.com/opencord/voltha-protos/v4/go/inter_container"
35 //"github.com/opencord/voltha-protos/v4/go/openflow_13"
36 //"github.com/opencord/voltha-protos/v4/go/voltha"
mpagenko3dbcdd22020-07-22 07:38:45 +000037)
38
mpagenko1cc3cb42020-07-27 15:24:38 +000039const (
40 // events of config PON ANI port FSM
mpagenko8b07c1b2020-11-26 10:36:31 +000041 aniEvStart = "aniEvStart"
42 aniEvStartConfig = "aniEvStartConfig"
43 aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
44 aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
45 aniEvRxTcontsResp = "aniEvRxTcontsResp"
46 aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
47 aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
48 aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
49 aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
50 aniEvRemGemiw = "aniEvRemGemiw"
Girish Gowdra26a40922021-01-29 17:14:34 -080051 aniEvWaitFlowRem = "aniEvWaitFlowRem"
52 aniEvFlowRemDone = "aniEvFlowRemDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000053 aniEvRxRemGemiwResp = "aniEvRxRemGemiwResp"
54 aniEvRxRemGemntpResp = "aniEvRxRemGemntpResp"
55 aniEvRemTcontPath = "aniEvRemTcontPath"
56 aniEvRxResetTcontResp = "aniEvRxResetTcontResp"
57 aniEvRxRem1pMapperResp = "aniEvRxRem1pMapperResp"
58 aniEvRxRemAniBPCDResp = "aniEvRxRemAniBPCDResp"
59 aniEvTimeoutSimple = "aniEvTimeoutSimple"
60 aniEvTimeoutMids = "aniEvTimeoutMids"
61 aniEvReset = "aniEvReset"
62 aniEvRestart = "aniEvRestart"
mpagenko1cc3cb42020-07-27 15:24:38 +000063)
64const (
65 // states of config PON ANI port FSM
66 aniStDisabled = "aniStDisabled"
67 aniStStarting = "aniStStarting"
68 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
69 aniStCreatingMBPCD = "aniStCreatingMBPCD"
70 aniStSettingTconts = "aniStSettingTconts"
71 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
72 aniStCreatingGemIWs = "aniStCreatingGemIWs"
73 aniStSettingPQs = "aniStSettingPQs"
74 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
75 aniStConfigDone = "aniStConfigDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000076 aniStRemovingGemIW = "aniStRemovingGemIW"
Girish Gowdra26a40922021-01-29 17:14:34 -080077 aniStWaitingFlowRem = "aniStWaitingFlowRem"
mpagenko8b07c1b2020-11-26 10:36:31 +000078 aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
79 aniStResetTcont = "aniStResetTcont"
80 aniStRemDot1PMapper = "aniStRemDot1PMapper"
81 aniStRemAniBPCD = "aniStRemAniBPCD"
82 aniStRemoveDone = "aniStRemoveDone"
mpagenko1cc3cb42020-07-27 15:24:38 +000083 aniStResetting = "aniStResetting"
84)
Holger Hildebrandt10d98192021-01-27 15:29:31 +000085const cAniFsmIdleState = aniStConfigDone
mpagenko1cc3cb42020-07-27 15:24:38 +000086
Girish Gowdra041dcb32020-11-16 16:54:30 -080087const (
88 tpIDOffset = 64
89)
90
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000091type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030092 gemPortID uint16
93 upQueueID uint16
94 downQueueID uint16
95 direction uint8
96 qosPolicy string
97 weight uint8
98 pbitString string
99 isMulticast bool
100 multicastGemID uint16
101 staticACL string
102 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000103}
104
Himani Chawla6d2ae152020-09-02 13:11:20 +0530105//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
106type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000107 pDeviceHandler *deviceHandler
108 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530109 pOmciCC *omciCC
110 pOnuUniPort *onuUniPort
111 pUniTechProf *onuUniTechProf
112 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800113 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000114 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000115 requestEvent OnuDeviceEvent
mpagenko7d6bb022021-03-11 15:07:55 +0000116 mutexIsAwaitingResponse sync.RWMutex
117 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530118 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000119 pAdaptFsm *AdapterFsm
120 chSuccess chan<- uint8
121 procStep uint8
122 chanSet bool
123 mapperSP0ID uint16
124 macBPCD0ID uint16
125 tcont0ID uint16
126 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000127 gemPortAttribsSlice []ponAniGemPortAttribs
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
mpagenko3dbcdd22020-07-22 07:38:45 +0000132}
133
Himani Chawla6d2ae152020-09-02 13:11:20 +0530134//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 +0000135func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800136 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000137 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530138 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000139 pDeviceHandler: apDeviceHandler,
140 deviceID: apDeviceHandler.deviceID,
141 pOmciCC: apDevOmciCC,
142 pOnuUniPort: apUniPort,
143 pUniTechProf: apUniTechProf,
144 pOnuDB: apOnuDB,
145 techProfileID: aTechProfileID,
146 requestEvent: aRequestEvent,
147 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000148 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000149 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000150 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000151
mpagenko01e726e2020-10-23 09:45:29 +0000152 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000153 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000154 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000155 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000156 return nil
157 }
158
159 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000160 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000161 fsm.Events{
162
mpagenko1cc3cb42020-07-27 15:24:38 +0000163 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000164
165 //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 +0000166 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000167 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000168 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
169 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000170 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000171 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000172 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000173 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000174 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000175 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000176 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000177
mpagenko8b07c1b2020-11-26 10:36:31 +0000178 //for removing Gem related resources
179 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800180 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
181 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000182 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
183 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
184
185 //for removing TCONT related resources
186 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
187 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
188 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
189 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
190
191 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
192 aniStRemovingGemIW, aniStRemovingGemNCTP,
193 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000194 {Name: aniEvTimeoutMids, Src: []string{
195 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000196
mpagenko1cc3cb42020-07-27 15:24:38 +0000197 // exceptional treatment for all states except aniStResetting
198 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
199 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000200 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000201 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000202 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000203 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
mpagenko3dbcdd22020-07-22 07:38:45 +0000204 },
205
206 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000207 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
208 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
209 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
210 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
211 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
212 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
213 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
214 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
215 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
216 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
217 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000218 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000219 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
220 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
221 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
222 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
223 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
224 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
225 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000226 },
227 )
228 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000229 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000230 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000231 return nil
232 }
233
dbainbri4d3a0dc2020-12-02 00:33:42 +0000234 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000235 return instFsm
236}
237
Himani Chawla6d2ae152020-09-02 13:11:20 +0530238//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
239func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000240 oFsm.chSuccess = aChSuccess
241 oFsm.procStep = aProcStep
242 oFsm.chanSet = true
243}
244
mpagenko7d6bb022021-03-11 15:07:55 +0000245//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000246func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
247 //early indication about started reset processing
248 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000249 //mutex protection is required for possible concurrent access to FSM members
250 oFsm.mutexIsAwaitingResponse.RLock()
251 defer oFsm.mutexIsAwaitingResponse.RUnlock()
252 if oFsm.isAwaitingResponse {
253 //use channel to indicate that the response waiting shall be aborted
254 oFsm.omciMIdsResponseReceived <- false
255 }
mpagenkobb47bc22021-04-20 13:29:09 +0000256 if oFsm.isWaitingForFlowDelete {
257 //use channel to indicate that the response waiting shall be aborted
258 oFsm.waitFlowDeleteChannel <- false
259 }
mpagenko7d6bb022021-03-11 15:07:55 +0000260 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
261 pAdaptFsm := oFsm.pAdaptFsm
262 if pAdaptFsm != nil {
263 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
264 go func(aPAFsm *AdapterFsm) {
265 if aPAFsm.pFsm != nil {
266 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
267 }
268 }(pAdaptFsm)
269 }
mpagenko73143992021-04-09 15:17:10 +0000270
271 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
272 // access conflicts on internal data by next needed data clearance
273 //activity should be aborted in short time if running with FSM due to above FSM reset
274 // or finished without FSM dependency in short time
275 oFsm.pUniTechProf.lockTpProcMutex()
276 defer oFsm.pUniTechProf.unlockTpProcMutex()
277 //remove all TechProf related internal data to allow for new configuration
278 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000279}
280
dbainbri4d3a0dc2020-12-02 00:33:42 +0000281func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530282 if aPAFsm != nil && aPAFsm.pFsm != nil {
283 //stick to pythonAdapter numbering scheme
284 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800285 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
286 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530287
Girish Gowdra041dcb32020-11-16 16:54:30 -0800288 /*
289 // Find a free TCONT Instance ID and use it
290 foundFreeTcontInstID := false
291 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000292 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800293
294 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
295 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
296 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
297 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
298 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
299 // when the ONU is discovered.
300 /*
301 for _, tcontInstID := range tcontInstKeys {
302 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
303 returnVal := tconInst["AllocId"]
304 if returnVal != nil {
305 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
306 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
307 if allocID == 0xff || allocID == 0xffff {
308 foundFreeTcontInstID = true
309 oFsm.tcont0ID = uint16(tcontInstID)
310 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
311 "device-id": oFsm.deviceID})
312 break
313 }
314 } else {
315 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
316 }
317 } else {
318 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
319 }
320 }
321 */
322
323 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
324 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
325 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
326 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
327 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
328 // TP ID will increment in single digit
329 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000330 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800331 "device-id": oFsm.deviceID})
332 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000333 logger.Errorw(ctx, "tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800334 if oFsm.chanSet {
335 // indicate processing error/abort to the caller
336 oFsm.chSuccess <- 0
337 oFsm.chanSet = false //reset the internal channel state
338 }
339 //reset the state machine to enable usage on subsequent requests
340 _ = aPAFsm.pFsm.Event(aniEvReset)
341 return
342 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530343 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000344 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800345 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530346 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800347 /*
348 if !foundFreeTcontInstID {
349 // This should never happen. If it does, the behavior is unpredictable.
350 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
351 }*/
352
353 // Access critical state with lock
354 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000355 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
356 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800357 oFsm.pUniTechProf.mutexTPState.Unlock()
358
Himani Chawla26e555c2020-08-31 12:30:20 +0530359 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800360 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300361 loGemPortAttribs := ponAniGemPortAttribs{}
362
Himani Chawla26e555c2020-08-31 12:30:20 +0530363 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
364
dbainbri4d3a0dc2020-12-02 00:33:42 +0000365 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530366
367 loGemPortAttribs.gemPortID = gemEntry.gemPortID
368 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
369 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
370 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
371 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
372
373 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
374 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
375 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
376 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
377 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
378 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
379
380 usQueueFound := false
381 dsQueueFound := false
382 for _, mgmtEntityID := range queueInstKeys {
383 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
384 returnVal := meAttributes["RelatedPort"]
385 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530386 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530387 if relatedPort == usQrelPortMask {
388 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000389 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000390 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530391 usQueueFound = true
392 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
393 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000394 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000395 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530396 dsQueueFound = true
397 }
398 if usQueueFound && dsQueueFound {
399 break
400 }
401 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000402 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530403 }
404 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000405 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530406 }
407 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000408 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000409 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530410 }
411 }
412 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000413 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530414 }
415 loGemPortAttribs.direction = gemEntry.direction
416 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
417 loGemPortAttribs.weight = gemEntry.queueWeight
418 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300419 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300420 //TODO this might effectively ignore the for loop starting at line 316
421 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300422 loGemPortAttribs.isMulticast = true
423 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
424 loGemPortAttribs.staticACL = gemEntry.staticACL
425 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530426
dbainbri4d3a0dc2020-12-02 00:33:42 +0000427 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300428 "gemPortID": loGemPortAttribs.gemPortID,
429 "isMulticast": loGemPortAttribs.isMulticast,
430 "multicastGemID": loGemPortAttribs.multicastGemID,
431 "staticACL": loGemPortAttribs.staticACL,
432 "dynamicACL": loGemPortAttribs.dynamicACL,
433 })
434
435 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000436 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300437 "gemPortID": loGemPortAttribs.gemPortID,
438 "upQueueID": loGemPortAttribs.upQueueID,
439 "downQueueID": loGemPortAttribs.downQueueID,
440 "pbitString": loGemPortAttribs.pbitString,
441 "prioQueueIndex": gemEntry.prioQueueIndex,
442 })
443 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530444
445 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
446 }
447 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
448 }
449}
450
dbainbri4d3a0dc2020-12-02 00:33:42 +0000451func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
452 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000453 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000454 // in case the used channel is not yet defined (can be re-used after restarts)
455 if oFsm.omciMIdsResponseReceived == nil {
456 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000457 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000458 } else {
459 // as we may 're-use' this instance of FSM and the connected channel
460 // make sure there is no 'lingering' request in the already existing channel:
461 // (simple loop sufficient as we are the only receiver)
462 for len(oFsm.omciMIdsResponseReceived) > 0 {
463 <-oFsm.omciMIdsResponseReceived
464 }
465 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000466 //ensure internal slices are empty (which might be set from previous run) - release memory
467 oFsm.gemPortAttribsSlice = nil
468
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000469 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000470 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000471
472 //let the state machine run forward from here directly
473 pConfigAniStateAFsm := oFsm.pAdaptFsm
474 if pConfigAniStateAFsm != nil {
475 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000476 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000477
mpagenko3dbcdd22020-07-22 07:38:45 +0000478 }
479}
480
dbainbri4d3a0dc2020-12-02 00:33:42 +0000481func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
482 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000483 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000484 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
485 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Girish Gowdra0b235842021-03-09 13:06:46 -0800486 meInstance := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000487 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
488 //accept also nil as (error) return value for writing to LastTx
489 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000490 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000491}
492
dbainbri4d3a0dc2020-12-02 00:33:42 +0000493func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
494 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000495 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
496 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000497 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000498 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
499 meParams := me.ParamData{
500 EntityID: oFsm.macBPCD0ID,
501 Attributes: me.AttributeValueMap{
502 "BridgeIdPointer": bridgePtr,
503 "PortNum": 0xFF, //fixed unique ANI side indication
504 "TpType": 3, //for .1PMapper
505 "TpPointer": oFsm.mapperSP0ID,
506 },
507 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800508 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000509 oFsm.pAdaptFsm.commChan, meParams)
510 //accept also nil as (error) return value for writing to LastTx
511 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000512 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000513}
514
dbainbri4d3a0dc2020-12-02 00:33:42 +0000515func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
516 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000517 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
518 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000519 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000520 meParams := me.ParamData{
521 EntityID: oFsm.tcont0ID,
522 Attributes: me.AttributeValueMap{
523 "AllocId": oFsm.alloc0ID,
524 },
525 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800526 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000527 oFsm.pAdaptFsm.commChan, meParams)
528 //accept also nil as (error) return value for writing to LastTx
529 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000530 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +0000531}
532
dbainbri4d3a0dc2020-12-02 00:33:42 +0000533func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
534 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000535 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000536 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000537}
538
dbainbri4d3a0dc2020-12-02 00:33:42 +0000539func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
540 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000541 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000542 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000543}
544
dbainbri4d3a0dc2020-12-02 00:33:42 +0000545func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
546 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000547 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000548 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000549}
550
dbainbri4d3a0dc2020-12-02 00:33:42 +0000551func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300552
dbainbri4d3a0dc2020-12-02 00:33:42 +0000553 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000554 "toGemIw": 1024, /* cmp above */
555 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000556
dbainbri4d3a0dc2020-12-02 00:33:42 +0000557 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000558 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000559 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000560
mpagenko3dbcdd22020-07-22 07:38:45 +0000561 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000562 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530563 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000564 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000565
566 //assign the GemPorts according to the configured Prio
567 var loPrioGemPortArray [8]uint16
568 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300569 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000570 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300571 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
572 "prioString": gemPortAttribs.pbitString})
573 continue
574 }
575 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000576 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300577 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
578 "prioString": gemPortAttribs.pbitString})
579 continue
580 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000581 for i := 0; i < 8; i++ {
582 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
583 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
584 if prio == 1 { // Check this p-bit is set
585 if loPrioGemPortArray[i] == 0 {
586 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
587 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000588 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000589 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000590 "SetGemPort": loPrioGemPortArray[i]})
591 }
592 }
593 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000594 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000595 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000596 "prioString": gemPortAttribs.pbitString, "position": i})
597 }
598
599 }
600 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300601
ozgecanetsia4b232302020-11-11 10:58:10 +0300602 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530603 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300604 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530605 if value != 0 {
606 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530607 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000608 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000609 "for Prio": index,
610 "IwPtr": strconv.FormatInt(int64(value), 16),
611 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300612 } else {
613 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000614 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
615 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300616 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530617 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000618 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300619 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000620 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
621 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300622 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530623
624 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000625 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000626 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300627 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
628 // 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 +0000629 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300630 //pConfigAniStateAFsm := oFsm.pAdaptFsm
631 //if pConfigAniStateAFsm != nil {
632 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
633 // go func(aPAFsm *AdapterFsm) {
634 // if aPAFsm != nil && aPAFsm.pFsm != nil {
635 // _ = aPAFsm.pFsm.Event(aniEvReset)
636 // }
637 // }(pConfigAniStateAFsm)
638 //}
639 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000640 pConfigAniStateAFsm := oFsm.pAdaptFsm
641 if pConfigAniStateAFsm != nil {
642 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530643 go func(aPAFsm *AdapterFsm) {
644 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300645 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000646 }
647 }(pConfigAniStateAFsm)
648 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300649 } else {
Girish Gowdra0b235842021-03-09 13:06:46 -0800650 meInstance := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300651 oFsm.pAdaptFsm.commChan, meParams)
652 //accept also nil as (error) return value for writing to LastTx
653 // - this avoids misinterpretation of new received OMCI messages
654 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000655 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000656}
657
dbainbri4d3a0dc2020-12-02 00:33:42 +0000658func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
659 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000660 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000661 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000662 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko01e726e2020-10-23 09:45:29 +0000663 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800664 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko01e726e2020-10-23 09:45:29 +0000665 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
mpagenko8b07c1b2020-11-26 10:36:31 +0000666 // but only in case the techProfile was configured (not deleted)
667 if oFsm.requestEventOffset == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000668 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
mpagenko8b07c1b2020-11-26 10:36:31 +0000669 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000670
mpagenko01e726e2020-10-23 09:45:29 +0000671 if oFsm.chanSet {
672 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000673 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000674 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
675 oFsm.chSuccess <- oFsm.procStep
676 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000677 }
mpagenko01e726e2020-10-23 09:45:29 +0000678
679 //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 +0000680}
681
dbainbri4d3a0dc2020-12-02 00:33:42 +0000682func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000683 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000684 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
685 select {
686 case <-oFsm.waitFlowDeleteChannel:
687 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
688 default:
689 }
690 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
mpagenkoa23a6292021-02-23 10:40:10 +0000691 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800692 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
693 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
694 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
695 pConfigAniStateAFsm := oFsm.pAdaptFsm
696 if pConfigAniStateAFsm != nil {
697 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
698 go func(aPAFsm *AdapterFsm) {
699 if aPAFsm != nil && aPAFsm.pFsm != nil {
700 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvWaitFlowRem)
701 }
702 }(pConfigAniStateAFsm)
703 } else {
704 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
705 }
706 return
707 }
708
mpagenko8b07c1b2020-11-26 10:36:31 +0000709 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000710 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
711 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000712 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000713 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
714 "GemIwTp-entity-id": loGemPortID})
715 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
716
717 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800718 meInstance := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000719 oFsm.pAdaptFsm.commChan, loGemPortID)
720 oFsm.pLastTxMeInstance = meInstance
721}
722
mpagenkobb47bc22021-04-20 13:29:09 +0000723func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
724 oFsm.mutexIsAwaitingResponse.Lock()
725 oFsm.isWaitingForFlowDelete = true
726 oFsm.mutexIsAwaitingResponse.Unlock()
727 select {
728 // maybe be also some outside cancel (but no context modeled for the moment ...)
729 // case <-ctx.Done():
730 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
731 case <-time.After(10 * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
732 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
733 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
734 oFsm.mutexIsAwaitingResponse.Lock()
735 oFsm.isWaitingForFlowDelete = false
736 oFsm.mutexIsAwaitingResponse.Unlock()
737 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
738 pConfigAniStateAFsm := oFsm.pAdaptFsm
739 if pConfigAniStateAFsm != nil {
740 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
741 go func(aPAFsm *AdapterFsm) {
742 if aPAFsm != nil && aPAFsm.pFsm != nil {
743 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
744 }
745 }(pConfigAniStateAFsm)
746 } else {
747 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
748 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
749 }
750 return
751
752 case success := <-oFsm.waitFlowDeleteChannel:
753 if success {
754 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
755 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
756 oFsm.mutexIsAwaitingResponse.Lock()
757 oFsm.isWaitingForFlowDelete = false
758 oFsm.mutexIsAwaitingResponse.Unlock()
759 pConfigAniStateAFsm := oFsm.pAdaptFsm
760 if pConfigAniStateAFsm != nil {
761 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
762 go func(aPAFsm *AdapterFsm) {
763 if aPAFsm != nil && aPAFsm.pFsm != nil {
764 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvFlowRemDone)
765 }
766 }(pConfigAniStateAFsm)
767 } else {
768 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
769 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
770 }
771 return
772 }
773 // waiting was aborted (probably on external request)
774 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
775 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
776 oFsm.mutexIsAwaitingResponse.Lock()
777 oFsm.isWaitingForFlowDelete = false
778 oFsm.mutexIsAwaitingResponse.Unlock()
779 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
780 pConfigAniStateAFsm := oFsm.pAdaptFsm
781 if pConfigAniStateAFsm != nil {
782 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
783 go func(aPAFsm *AdapterFsm) {
784 if aPAFsm != nil && aPAFsm.pFsm != nil {
785 _ = aPAFsm.pFsm.Event(aniEvReset)
786 }
787 }(pConfigAniStateAFsm)
788 }
789 return
790 }
791}
792
dbainbri4d3a0dc2020-12-02 00:33:42 +0000793func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000794 oFsm.pUniTechProf.mutexTPState.Lock()
795 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
796 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000797 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000798 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
799 "GemNCTP-entity-id": loGemPortID})
800 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Girish Gowdra0b235842021-03-09 13:06:46 -0800801 meInstance := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000802 oFsm.pAdaptFsm.commChan, loGemPortID)
803 oFsm.pLastTxMeInstance = meInstance
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800804 // Mark the gem port to be removed for Performance History monitoring
805 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
806 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(loGemPortID)
807 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000808}
809
dbainbri4d3a0dc2020-12-02 00:33:42 +0000810func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
811 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000812 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
813
814 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
815 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
816 meParams := me.ParamData{
817 EntityID: oFsm.tcont0ID,
818 Attributes: me.AttributeValueMap{
819 "AllocId": unusedTcontAllocID,
820 },
821 }
Girish Gowdra0b235842021-03-09 13:06:46 -0800822 meInstance := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000823 oFsm.pAdaptFsm.commChan, meParams)
824 oFsm.pLastTxMeInstance = meInstance
825}
826
dbainbri4d3a0dc2020-12-02 00:33:42 +0000827func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
828 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000829 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
830
Girish Gowdra0b235842021-03-09 13:06:46 -0800831 meInstance := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000832 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
833 oFsm.pLastTxMeInstance = meInstance
834}
835
dbainbri4d3a0dc2020-12-02 00:33:42 +0000836func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
837 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000838 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
839
Girish Gowdra0b235842021-03-09 13:06:46 -0800840 meInstance := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000841 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
842 oFsm.pLastTxMeInstance = meInstance
843}
844
dbainbri4d3a0dc2020-12-02 00:33:42 +0000845func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
846 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000847 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
848 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +0000849 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +0000850 if oFsm.chanSet {
851 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000852 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000853 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
854 oFsm.chSuccess <- oFsm.procStep
855 oFsm.chanSet = false //reset the internal channel state
856 }
857
858 //let's reset the state machine in order to release all resources now
859 pConfigAniStateAFsm := oFsm.pAdaptFsm
860 if pConfigAniStateAFsm != nil {
861 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
862 go func(aPAFsm *AdapterFsm) {
863 if aPAFsm != nil && aPAFsm.pFsm != nil {
864 _ = aPAFsm.pFsm.Event(aniEvReset)
865 }
866 }(pConfigAniStateAFsm)
867 }
868}
869
dbainbri4d3a0dc2020-12-02 00:33:42 +0000870func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
871 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000872 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000873
mpagenko3dbcdd22020-07-22 07:38:45 +0000874 pConfigAniStateAFsm := oFsm.pAdaptFsm
875 if pConfigAniStateAFsm != nil {
876 // abort running message processing
877 fsmAbortMsg := Message{
878 Type: TestMsg,
879 Data: TestMessage{
880 TestMessageVal: AbortMessageProcessing,
881 },
882 }
883 pConfigAniStateAFsm.commChan <- fsmAbortMsg
884
885 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +0530886 go func(aPAFsm *AdapterFsm) {
887 if aPAFsm != nil && aPAFsm.pFsm != nil {
888 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +0000889 }
890 }(pConfigAniStateAFsm)
891 }
892}
893
dbainbri4d3a0dc2020-12-02 00:33:42 +0000894func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
895 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000896 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko01e726e2020-10-23 09:45:29 +0000897 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +0000898}
899
dbainbri4d3a0dc2020-12-02 00:33:42 +0000900func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
901 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000902loop:
903 for {
mpagenko3dbcdd22020-07-22 07:38:45 +0000904 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000905 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000906 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530907 message, ok := <-oFsm.pAdaptFsm.commChan
908 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000909 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530910 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
911 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
912 break loop
913 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000914 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530915
916 switch message.Type {
917 case TestMsg:
918 msg, _ := message.Data.(TestMessage)
919 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000920 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000921 break loop
922 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000923 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530924 case OMCI:
925 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000926 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +0530927 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +0000928 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530929 "message.Type": message.Type})
930 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000931
Himani Chawla4d908332020-08-31 12:30:20 +0530932 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000933 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530934}
935
dbainbri4d3a0dc2020-12-02 00:33:42 +0000936func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530937 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
938 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000939 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000940 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530941 return
942 }
943 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
944 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000945 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000946 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530947 return
948 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000949 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +0000950 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
951 //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
952 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
953 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
954 // maybe we can use just the same eventName for different state transitions like "forward"
955 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
956 switch oFsm.pLastTxMeInstance.GetName() {
957 case "Ieee8021PMapperServiceProfile":
958 { // let the FSM proceed ...
959 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
960 }
961 case "MacBridgePortConfigurationData":
962 { // let the FSM proceed ...
963 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
964 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300965 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
mpagenkofc4f56e2020-11-04 17:17:49 +0000966 { // let aniConfig Multi-Id processing proceed by stopping the wait function
967 oFsm.omciMIdsResponseReceived <- true
968 }
969 }
970 }
971 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000972 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530973 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
974 return
975 }
Himani Chawla4d908332020-08-31 12:30:20 +0530976}
977
dbainbri4d3a0dc2020-12-02 00:33:42 +0000978func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +0530979 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
980 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000981 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000982 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530983 return
984 }
985 msgObj, msgOk := msgLayer.(*omci.SetResponse)
986 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000987 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +0000988 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530989 return
990 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000991 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +0530992 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000993 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +0000994 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +0530995 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
996 return
997 }
mpagenko01e726e2020-10-23 09:45:29 +0000998 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
999 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
Himani Chawla4d908332020-08-31 12:30:20 +05301000 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1001 // if, then something like:
1002 //oFsm.pOnuDB.StoreMe(msgObj)
1003
mpagenko01e726e2020-10-23 09:45:29 +00001004 switch oFsm.pLastTxMeInstance.GetName() {
Himani Chawla4d908332020-08-31 12:30:20 +05301005 case "TCont":
1006 { // let the FSM proceed ...
mpagenko8b07c1b2020-11-26 10:36:31 +00001007 if oFsm.requestEventOffset == 0 { //from TCont config request
1008 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1009 } else { // from T-Cont reset request
1010 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1011 }
Himani Chawla4d908332020-08-31 12:30:20 +05301012 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001013 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
Himani Chawla4d908332020-08-31 12:30:20 +05301014 { // let the PrioQueue init proceed by stopping the wait function
1015 oFsm.omciMIdsResponseReceived <- true
1016 }
1017 case "Ieee8021PMapperServiceProfile":
1018 { // let the FSM proceed ...
1019 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1020 }
1021 }
1022 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001023}
1024
dbainbri4d3a0dc2020-12-02 00:33:42 +00001025func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001026 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1027 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001028 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001029 log.Fields{"device-id": oFsm.deviceID})
1030 return
1031 }
1032 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1033 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001034 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001035 log.Fields{"device-id": oFsm.deviceID})
1036 return
1037 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001038 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001039 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001040 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001041 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1042 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1043 // store error for mgmt display?
1044 return
1045 }
1046 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1047 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1048 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1049 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
1050
1051 switch oFsm.pLastTxMeInstance.GetName() {
1052 case "GemInterworkingTerminationPoint":
1053 { // let the FSM proceed ...
1054 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1055 }
1056 case "GemPortNetworkCtp":
1057 { // let the FSM proceed ...
1058 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1059 }
1060 case "Ieee8021PMapperServiceProfile":
1061 { // let the FSM proceed ...
1062 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1063 }
1064 case "MacBridgePortConfigurationData":
1065 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1066 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1067 }
1068 }
1069 }
1070}
1071
dbainbri4d3a0dc2020-12-02 00:33:42 +00001072func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1073 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001074 "msgType": msg.OmciMsg.MessageType})
1075
1076 switch msg.OmciMsg.MessageType {
1077 case omci.CreateResponseType:
1078 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001079 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301080
mpagenko3dbcdd22020-07-22 07:38:45 +00001081 } //CreateResponseType
1082 case omci.SetResponseType:
1083 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001084 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001085
mpagenko3dbcdd22020-07-22 07:38:45 +00001086 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001087 case omci.DeleteResponseType:
1088 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001089 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001090
1091 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001092 default:
1093 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001094 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001095 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001096 return
1097 }
1098 }
1099}
1100
dbainbri4d3a0dc2020-12-02 00:33:42 +00001101func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001102 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1103 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001104 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001105 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1106 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001107 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001108 meParams := me.ParamData{
1109 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1110 Attributes: me.AttributeValueMap{
1111 "PortId": gemPortAttribs.gemPortID,
1112 "TContPointer": oFsm.tcont0ID,
1113 "Direction": gemPortAttribs.direction,
1114 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1115 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1116 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1117 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1118 },
1119 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001120 meInstance := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001121 oFsm.pAdaptFsm.commChan, meParams)
1122 //accept also nil as (error) return value for writing to LastTx
1123 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001124 oFsm.pLastTxMeInstance = meInstance
mpagenko3dbcdd22020-07-22 07:38:45 +00001125
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001126 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001127 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001128 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001129 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001130 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301131 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001132 return
1133 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001134 // Mark the gem port to be removed for Performance History monitoring
1135 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
1136 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(gemPortAttribs.gemPortID)
1137 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001138 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001139
1140 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001141 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301142 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001143}
1144
dbainbri4d3a0dc2020-12-02 00:33:42 +00001145func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001146 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1147 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001148 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001149 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1150 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001151 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001152
ozgecanetsia4b232302020-11-11 10:58:10 +03001153 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1154 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001155
1156 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001157 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001158 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001159 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001160 "InterworkingOption": 0, // Don't Care
1161 "ServiceProfilePointer": 0, // Don't Care
1162 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001163 },
1164 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001165 meInstance := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001166 true, oFsm.pAdaptFsm.commChan, meParams)
1167 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001168 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001169 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001170 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001171 logger.Errorw(ctx, "GemTP IW multicast create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001172 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1173 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1174 return
1175 }
1176 ipv4MulticastTable := make([]uint8, 12)
1177 //Gem Port ID
1178 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1179 //Secondary Key
1180 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1181 // Multicast IP range start This is the 224.0.0.1 address
1182 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1183 // MulticastIp range stop
1184 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1185
1186 meIPV4MCTableParams := me.ParamData{
1187 EntityID: gemPortAttribs.multicastGemID,
1188 Attributes: me.AttributeValueMap{
1189 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1190 },
1191 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001192 meIPV4MCTableInstance := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001193 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
1194 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
ozgecanetsia4b232302020-11-11 10:58:10 +03001195
1196 } else {
1197 meParams := me.ParamData{
1198 EntityID: gemPortAttribs.gemPortID,
1199 Attributes: me.AttributeValueMap{
1200 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1201 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1202 "ServiceProfilePointer": oFsm.mapperSP0ID,
1203 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1204 "GalProfilePointer": galEthernetEID,
1205 },
1206 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001207 meInstance := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001208 oFsm.pAdaptFsm.commChan, meParams)
1209 //accept also nil as (error) return value for writing to LastTx
1210 // - this avoids misinterpretation of new received OMCI messages
1211 oFsm.pLastTxMeInstance = meInstance
1212 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001213 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001214 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001215 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001216 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001217 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301218 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001219 return
1220 }
1221 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001222
1223 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001224 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301225 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001226}
1227
dbainbri4d3a0dc2020-12-02 00:33:42 +00001228func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001229 const cu16StrictPrioWeight uint16 = 0xFFFF
1230 //find all upstream PrioQueues related to this T-Cont
1231 loQueueMap := ordered_map.NewOrderedMap()
1232 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001233 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001234 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001235 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1236 "prioString": gemPortAttribs.pbitString})
1237 continue
1238 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001239 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301240 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001241 //key does not yet exist
1242 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1243 }
1244 } else {
1245 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1246 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001247 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001248
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001249 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1250 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1251 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1252 // or even be finished without correct SP/WRR setting
1253
1254 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1255 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1256 // even though its T-Cont seems to be wrong ...
1257 loTrafficSchedulerEID := 0x8000
1258 //for all found queues
1259 iter := loQueueMap.IterFunc()
1260 for kv, ok := iter(); ok; kv, ok = iter() {
1261 queueIndex := (kv.Key).(uint16)
1262 meParams := me.ParamData{
1263 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301264 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001265 }
1266 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1267 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001268 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001269 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001270 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001271 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1272 } else {
1273 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001274 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001275 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1276 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001277 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001278 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1279 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1280 }
Girish Gowdra0b235842021-03-09 13:06:46 -08001281 meInstance := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001282 oFsm.pAdaptFsm.commChan, meParams)
1283 //accept also nil as (error) return value for writing to LastTx
1284 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001285 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001286
1287 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001288 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001289 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001290 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001291 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301292 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001293 return
1294 }
1295
1296 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1297 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1298 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1299 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1300
1301 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001302
1303 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001304 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301305 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001306}
1307
dbainbri4d3a0dc2020-12-02 00:33:42 +00001308func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001309 oFsm.mutexIsAwaitingResponse.Lock()
1310 oFsm.isAwaitingResponse = true
1311 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001312 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301313 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001314 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001315 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001316 case <-time.After(30 * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
dbainbri4d3a0dc2020-12-02 00:33:42 +00001317 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001318 oFsm.mutexIsAwaitingResponse.Lock()
1319 oFsm.isAwaitingResponse = false
1320 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001321 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001322 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301323 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001324 logger.Debug(ctx, "uniPonAniConfigFsm multi entity response received")
mpagenko7d6bb022021-03-11 15:07:55 +00001325 oFsm.mutexIsAwaitingResponse.Lock()
1326 oFsm.isAwaitingResponse = false
1327 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001328 return nil
1329 }
mpagenko7d6bb022021-03-11 15:07:55 +00001330 // waiting was aborted (probably on external request)
1331 logger.Debugw(ctx, "uniPonAniConfigFsm wait for multi entity response aborted", log.Fields{"for device-id": oFsm.deviceID})
1332 oFsm.mutexIsAwaitingResponse.Lock()
1333 oFsm.isAwaitingResponse = false
1334 oFsm.mutexIsAwaitingResponse.Unlock()
1335 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001336 }
1337}