blob: e03eb17b335a61468f6e3a03b4ecfb6ecd2a1f27 [file] [log] [blame]
mpagenko3dbcdd22020-07-22 07:38:45 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
ozgecanetsia4b232302020-11-11 10:58:10 +030022 "encoding/binary"
Himani Chawla4d908332020-08-31 12:30:20 +053023 "fmt"
ozgecanetsia4b232302020-11-11 10:58:10 +030024 "net"
mpagenko3dbcdd22020-07-22 07:38:45 +000025 "strconv"
mpagenko7d6bb022021-03-11 15:07:55 +000026 "sync"
mpagenko3dbcdd22020-07-22 07:38:45 +000027 "time"
28
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000029 "github.com/cevaris/ordered_map"
mpagenko3dbcdd22020-07-22 07:38:45 +000030 "github.com/looplab/fsm"
mpagenko3dbcdd22020-07-22 07:38:45 +000031 "github.com/opencord/omci-lib-go"
32 me "github.com/opencord/omci-lib-go/generated"
dbainbri4d3a0dc2020-12-02 00:33:42 +000033 "github.com/opencord/voltha-lib-go/v4/pkg/log"
34 //ic "github.com/opencord/voltha-protos/v4/go/inter_container"
35 //"github.com/opencord/voltha-protos/v4/go/openflow_13"
36 //"github.com/opencord/voltha-protos/v4/go/voltha"
mpagenko3dbcdd22020-07-22 07:38:45 +000037)
38
mpagenko1cc3cb42020-07-27 15:24:38 +000039const (
40 // events of config PON ANI port FSM
mpagenko8b07c1b2020-11-26 10:36:31 +000041 aniEvStart = "aniEvStart"
42 aniEvStartConfig = "aniEvStartConfig"
43 aniEvRxDot1pmapCResp = "aniEvRxDot1pmapCResp"
44 aniEvRxMbpcdResp = "aniEvRxMbpcdResp"
45 aniEvRxTcontsResp = "aniEvRxTcontsResp"
46 aniEvRxGemntcpsResp = "aniEvRxGemntcpsResp"
47 aniEvRxGemiwsResp = "aniEvRxGemiwsResp"
48 aniEvRxPrioqsResp = "aniEvRxPrioqsResp"
49 aniEvRxDot1pmapSResp = "aniEvRxDot1pmapSResp"
50 aniEvRemGemiw = "aniEvRemGemiw"
Girish Gowdra26a40922021-01-29 17:14:34 -080051 aniEvWaitFlowRem = "aniEvWaitFlowRem"
52 aniEvFlowRemDone = "aniEvFlowRemDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000053 aniEvRxRemGemiwResp = "aniEvRxRemGemiwResp"
54 aniEvRxRemGemntpResp = "aniEvRxRemGemntpResp"
55 aniEvRemTcontPath = "aniEvRemTcontPath"
56 aniEvRxResetTcontResp = "aniEvRxResetTcontResp"
57 aniEvRxRem1pMapperResp = "aniEvRxRem1pMapperResp"
58 aniEvRxRemAniBPCDResp = "aniEvRxRemAniBPCDResp"
59 aniEvTimeoutSimple = "aniEvTimeoutSimple"
60 aniEvTimeoutMids = "aniEvTimeoutMids"
61 aniEvReset = "aniEvReset"
62 aniEvRestart = "aniEvRestart"
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +000063 aniEvSkipOmciConfig = "aniEvSkipOmciConfig"
mpagenko1cc3cb42020-07-27 15:24:38 +000064)
65const (
66 // states of config PON ANI port FSM
67 aniStDisabled = "aniStDisabled"
68 aniStStarting = "aniStStarting"
69 aniStCreatingDot1PMapper = "aniStCreatingDot1PMapper"
70 aniStCreatingMBPCD = "aniStCreatingMBPCD"
71 aniStSettingTconts = "aniStSettingTconts"
72 aniStCreatingGemNCTPs = "aniStCreatingGemNCTPs"
73 aniStCreatingGemIWs = "aniStCreatingGemIWs"
74 aniStSettingPQs = "aniStSettingPQs"
75 aniStSettingDot1PMapper = "aniStSettingDot1PMapper"
76 aniStConfigDone = "aniStConfigDone"
mpagenko8b07c1b2020-11-26 10:36:31 +000077 aniStRemovingGemIW = "aniStRemovingGemIW"
Girish Gowdra26a40922021-01-29 17:14:34 -080078 aniStWaitingFlowRem = "aniStWaitingFlowRem"
mpagenko8b07c1b2020-11-26 10:36:31 +000079 aniStRemovingGemNCTP = "aniStRemovingGemNCTP"
80 aniStResetTcont = "aniStResetTcont"
81 aniStRemDot1PMapper = "aniStRemDot1PMapper"
82 aniStRemAniBPCD = "aniStRemAniBPCD"
83 aniStRemoveDone = "aniStRemoveDone"
mpagenko1cc3cb42020-07-27 15:24:38 +000084 aniStResetting = "aniStResetting"
85)
Holger Hildebrandt10d98192021-01-27 15:29:31 +000086const cAniFsmIdleState = aniStConfigDone
mpagenko1cc3cb42020-07-27 15:24:38 +000087
Girish Gowdra041dcb32020-11-16 16:54:30 -080088const (
89 tpIDOffset = 64
90)
91
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +000092type ponAniGemPortAttribs struct {
ozgecanetsia4b232302020-11-11 10:58:10 +030093 gemPortID uint16
94 upQueueID uint16
95 downQueueID uint16
96 direction uint8
97 qosPolicy string
98 weight uint8
99 pbitString string
100 isMulticast bool
101 multicastGemID uint16
102 staticACL string
103 dynamicACL string
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000104}
105
Himani Chawla6d2ae152020-09-02 13:11:20 +0530106//uniPonAniConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
107type uniPonAniConfigFsm struct {
mpagenko01e726e2020-10-23 09:45:29 +0000108 pDeviceHandler *deviceHandler
109 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530110 pOmciCC *omciCC
111 pOnuUniPort *onuUniPort
112 pUniTechProf *onuUniTechProf
113 pOnuDB *onuDeviceDB
Girish Gowdra041dcb32020-11-16 16:54:30 -0800114 techProfileID uint8
mpagenko8b07c1b2020-11-26 10:36:31 +0000115 uniTpKey uniTP
mpagenko3dbcdd22020-07-22 07:38:45 +0000116 requestEvent OnuDeviceEvent
mpagenko7d6bb022021-03-11 15:07:55 +0000117 mutexIsAwaitingResponse sync.RWMutex
mpagenkocf48e452021-04-23 09:23:00 +0000118 isCanceled bool
mpagenko7d6bb022021-03-11 15:07:55 +0000119 isAwaitingResponse bool
Himani Chawla4d908332020-08-31 12:30:20 +0530120 omciMIdsResponseReceived chan bool //separate channel needed for checking multiInstance OMCI message responses
mpagenko3dbcdd22020-07-22 07:38:45 +0000121 pAdaptFsm *AdapterFsm
122 chSuccess chan<- uint8
123 procStep uint8
124 chanSet bool
125 mapperSP0ID uint16
126 macBPCD0ID uint16
127 tcont0ID uint16
128 alloc0ID uint16
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000129 gemPortAttribsSlice []ponAniGemPortAttribs
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000130 mutexPLastTxMeInstance sync.RWMutex
mpagenko01e726e2020-10-23 09:45:29 +0000131 pLastTxMeInstance *me.ManagedEntity
mpagenko8b07c1b2020-11-26 10:36:31 +0000132 requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
mpagenkobb47bc22021-04-20 13:29:09 +0000133 isWaitingForFlowDelete bool
134 waitFlowDeleteChannel chan bool
mpagenko3dbcdd22020-07-22 07:38:45 +0000135}
136
Himani Chawla6d2ae152020-09-02 13:11:20 +0530137//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 +0000138func newUniPonAniConfigFsm(ctx context.Context, apDevOmciCC *omciCC, apUniPort *onuUniPort, apUniTechProf *onuUniTechProf,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800139 apOnuDB *onuDeviceDB, aTechProfileID uint8, aRequestEvent OnuDeviceEvent, aName string,
mpagenko01e726e2020-10-23 09:45:29 +0000140 apDeviceHandler *deviceHandler, aCommChannel chan Message) *uniPonAniConfigFsm {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530141 instFsm := &uniPonAniConfigFsm{
mpagenko01e726e2020-10-23 09:45:29 +0000142 pDeviceHandler: apDeviceHandler,
143 deviceID: apDeviceHandler.deviceID,
144 pOmciCC: apDevOmciCC,
145 pOnuUniPort: apUniPort,
146 pUniTechProf: apUniTechProf,
147 pOnuDB: apOnuDB,
148 techProfileID: aTechProfileID,
149 requestEvent: aRequestEvent,
150 chanSet: false,
mpagenko3dbcdd22020-07-22 07:38:45 +0000151 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000152 instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
mpagenkobb47bc22021-04-20 13:29:09 +0000153 instFsm.waitFlowDeleteChannel = make(chan bool)
mpagenko8b07c1b2020-11-26 10:36:31 +0000154
mpagenko01e726e2020-10-23 09:45:29 +0000155 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenko3dbcdd22020-07-22 07:38:45 +0000156 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000157 logger.Errorw(ctx, "uniPonAniConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000158 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000159 return nil
160 }
161
162 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
mpagenko1cc3cb42020-07-27 15:24:38 +0000163 aniStDisabled,
mpagenko3dbcdd22020-07-22 07:38:45 +0000164 fsm.Events{
165
mpagenko1cc3cb42020-07-27 15:24:38 +0000166 {Name: aniEvStart, Src: []string{aniStDisabled}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000167
168 //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 +0000169 {Name: aniEvStartConfig, Src: []string{aniStStarting}, Dst: aniStCreatingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000170 {Name: aniEvRxDot1pmapCResp, Src: []string{aniStCreatingDot1PMapper}, Dst: aniStCreatingMBPCD},
mpagenko1cc3cb42020-07-27 15:24:38 +0000171 {Name: aniEvRxMbpcdResp, Src: []string{aniStCreatingMBPCD}, Dst: aniStSettingTconts},
172 {Name: aniEvRxTcontsResp, Src: []string{aniStSettingTconts}, Dst: aniStCreatingGemNCTPs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000173 // the creatingGemNCTPs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000174 {Name: aniEvRxGemntcpsResp, Src: []string{aniStCreatingGemNCTPs}, Dst: aniStCreatingGemIWs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000175 // the creatingGemIWs state is used for multi ME config if required for all configured/available GemPorts
mpagenko1cc3cb42020-07-27 15:24:38 +0000176 {Name: aniEvRxGemiwsResp, Src: []string{aniStCreatingGemIWs}, Dst: aniStSettingPQs},
mpagenko3dbcdd22020-07-22 07:38:45 +0000177 // the settingPQs state is used for multi ME config if required for all configured/available upstream PriorityQueues
mpagenko1cc3cb42020-07-27 15:24:38 +0000178 {Name: aniEvRxPrioqsResp, Src: []string{aniStSettingPQs}, Dst: aniStSettingDot1PMapper},
mpagenkodff5dda2020-08-28 11:52:01 +0000179 {Name: aniEvRxDot1pmapSResp, Src: []string{aniStSettingDot1PMapper}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000180
mpagenko8b07c1b2020-11-26 10:36:31 +0000181 //for removing Gem related resources
182 {Name: aniEvRemGemiw, Src: []string{aniStConfigDone}, Dst: aniStRemovingGemIW},
Girish Gowdra26a40922021-01-29 17:14:34 -0800183 {Name: aniEvWaitFlowRem, Src: []string{aniStRemovingGemIW}, Dst: aniStWaitingFlowRem},
184 {Name: aniEvFlowRemDone, Src: []string{aniStWaitingFlowRem}, Dst: aniStRemovingGemIW},
mpagenko8b07c1b2020-11-26 10:36:31 +0000185 {Name: aniEvRxRemGemiwResp, Src: []string{aniStRemovingGemIW}, Dst: aniStRemovingGemNCTP},
186 {Name: aniEvRxRemGemntpResp, Src: []string{aniStRemovingGemNCTP}, Dst: aniStConfigDone},
187
188 //for removing TCONT related resources
189 {Name: aniEvRemTcontPath, Src: []string{aniStConfigDone}, Dst: aniStResetTcont},
190 {Name: aniEvRxResetTcontResp, Src: []string{aniStResetTcont}, Dst: aniStRemDot1PMapper},
191 {Name: aniEvRxRem1pMapperResp, Src: []string{aniStRemDot1PMapper}, Dst: aniStRemAniBPCD},
192 {Name: aniEvRxRemAniBPCDResp, Src: []string{aniStRemAniBPCD}, Dst: aniStRemoveDone},
193
194 {Name: aniEvTimeoutSimple, Src: []string{aniStCreatingDot1PMapper, aniStCreatingMBPCD, aniStSettingTconts, aniStSettingDot1PMapper,
195 aniStRemovingGemIW, aniStRemovingGemNCTP,
196 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStStarting},
mpagenko1cc3cb42020-07-27 15:24:38 +0000197 {Name: aniEvTimeoutMids, Src: []string{
198 aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs}, Dst: aniStStarting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000199
mpagenko1cc3cb42020-07-27 15:24:38 +0000200 // exceptional treatment for all states except aniStResetting
201 {Name: aniEvReset, Src: []string{aniStStarting, aniStCreatingDot1PMapper, aniStCreatingMBPCD,
202 aniStSettingTconts, aniStCreatingGemNCTPs, aniStCreatingGemIWs, aniStSettingPQs, aniStSettingDot1PMapper,
mpagenkobb47bc22021-04-20 13:29:09 +0000203 aniStConfigDone, aniStRemovingGemIW, aniStWaitingFlowRem, aniStRemovingGemNCTP,
mpagenko8b07c1b2020-11-26 10:36:31 +0000204 aniStResetTcont, aniStRemDot1PMapper, aniStRemAniBPCD, aniStRemoveDone}, Dst: aniStResetting},
mpagenko3dbcdd22020-07-22 07:38:45 +0000205 // the only way to get to resource-cleared disabled state again is via "resseting"
mpagenko1cc3cb42020-07-27 15:24:38 +0000206 {Name: aniEvRestart, Src: []string{aniStResetting}, Dst: aniStDisabled},
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000207 {Name: aniEvSkipOmciConfig, Src: []string{aniStStarting}, Dst: aniStConfigDone},
mpagenko3dbcdd22020-07-22 07:38:45 +0000208 },
209
210 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000211 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
212 ("enter_" + aniStStarting): func(e *fsm.Event) { instFsm.enterConfigStartingState(ctx, e) },
213 ("enter_" + aniStCreatingDot1PMapper): func(e *fsm.Event) { instFsm.enterCreatingDot1PMapper(ctx, e) },
214 ("enter_" + aniStCreatingMBPCD): func(e *fsm.Event) { instFsm.enterCreatingMBPCD(ctx, e) },
215 ("enter_" + aniStSettingTconts): func(e *fsm.Event) { instFsm.enterSettingTconts(ctx, e) },
216 ("enter_" + aniStCreatingGemNCTPs): func(e *fsm.Event) { instFsm.enterCreatingGemNCTPs(ctx, e) },
217 ("enter_" + aniStCreatingGemIWs): func(e *fsm.Event) { instFsm.enterCreatingGemIWs(ctx, e) },
218 ("enter_" + aniStSettingPQs): func(e *fsm.Event) { instFsm.enterSettingPQs(ctx, e) },
219 ("enter_" + aniStSettingDot1PMapper): func(e *fsm.Event) { instFsm.enterSettingDot1PMapper(ctx, e) },
220 ("enter_" + aniStConfigDone): func(e *fsm.Event) { instFsm.enterAniConfigDone(ctx, e) },
221 ("enter_" + aniStRemovingGemIW): func(e *fsm.Event) { instFsm.enterRemovingGemIW(ctx, e) },
mpagenkobb47bc22021-04-20 13:29:09 +0000222 ("enter_" + aniStWaitingFlowRem): func(e *fsm.Event) { instFsm.enterWaitingFlowRem(ctx, e) },
dbainbri4d3a0dc2020-12-02 00:33:42 +0000223 ("enter_" + aniStRemovingGemNCTP): func(e *fsm.Event) { instFsm.enterRemovingGemNCTP(ctx, e) },
224 ("enter_" + aniStResetTcont): func(e *fsm.Event) { instFsm.enterResettingTcont(ctx, e) },
225 ("enter_" + aniStRemDot1PMapper): func(e *fsm.Event) { instFsm.enterRemoving1pMapper(ctx, e) },
226 ("enter_" + aniStRemAniBPCD): func(e *fsm.Event) { instFsm.enterRemovingAniBPCD(ctx, e) },
227 ("enter_" + aniStRemoveDone): func(e *fsm.Event) { instFsm.enterAniRemoveDone(ctx, e) },
228 ("enter_" + aniStResetting): func(e *fsm.Event) { instFsm.enterResettingState(ctx, e) },
229 ("enter_" + aniStDisabled): func(e *fsm.Event) { instFsm.enterDisabledState(ctx, e) },
mpagenko3dbcdd22020-07-22 07:38:45 +0000230 },
231 )
232 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000233 logger.Errorw(ctx, "uniPonAniConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000234 "device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000235 return nil
236 }
237
dbainbri4d3a0dc2020-12-02 00:33:42 +0000238 logger.Debugw(ctx, "uniPonAniConfigFsm created", log.Fields{"device-id": instFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000239 return instFsm
240}
241
Himani Chawla6d2ae152020-09-02 13:11:20 +0530242//setFsmCompleteChannel sets the requested channel and channel result for transfer on success
243func (oFsm *uniPonAniConfigFsm) setFsmCompleteChannel(aChSuccess chan<- uint8, aProcStep uint8) {
mpagenko3dbcdd22020-07-22 07:38:45 +0000244 oFsm.chSuccess = aChSuccess
245 oFsm.procStep = aProcStep
246 oFsm.chanSet = true
247}
248
mpagenko7d6bb022021-03-11 15:07:55 +0000249//CancelProcessing ensures that suspended processing at waiting on some response is aborted and reset of FSM
mpagenko73143992021-04-09 15:17:10 +0000250func (oFsm *uniPonAniConfigFsm) CancelProcessing(ctx context.Context) {
251 //early indication about started reset processing
252 oFsm.pUniTechProf.setProfileResetting(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
mpagenko7d6bb022021-03-11 15:07:55 +0000253 //mutex protection is required for possible concurrent access to FSM members
mpagenkocf48e452021-04-23 09:23:00 +0000254 oFsm.mutexIsAwaitingResponse.Lock()
255 oFsm.isCanceled = true
mpagenko7d6bb022021-03-11 15:07:55 +0000256 if oFsm.isAwaitingResponse {
mpagenkocf48e452021-04-23 09:23:00 +0000257 //attention: for an unbuffered channel the sender is blocked until the value is received (processed)!
258 // accordingly the mutex must be released before sending to channel here (mutex acquired in receiver)
259 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000260 //use channel to indicate that the response waiting shall be aborted
261 oFsm.omciMIdsResponseReceived <- false
mpagenkocf48e452021-04-23 09:23:00 +0000262 } else {
263 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko7d6bb022021-03-11 15:07:55 +0000264 }
mpagenkocf48e452021-04-23 09:23:00 +0000265
266 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000267 if oFsm.isWaitingForFlowDelete {
mpagenkocf48e452021-04-23 09:23:00 +0000268 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000269 //use channel to indicate that the response waiting shall be aborted
270 oFsm.waitFlowDeleteChannel <- false
mpagenkocf48e452021-04-23 09:23:00 +0000271 } else {
272 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenkobb47bc22021-04-20 13:29:09 +0000273 }
mpagenkocf48e452021-04-23 09:23:00 +0000274
mpagenko7d6bb022021-03-11 15:07:55 +0000275 // in any case (even if it might be automatically requested by above cancellation of waiting) ensure resetting the FSM
276 pAdaptFsm := oFsm.pAdaptFsm
277 if pAdaptFsm != nil {
278 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
279 go func(aPAFsm *AdapterFsm) {
280 if aPAFsm.pFsm != nil {
281 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
282 }
283 }(pAdaptFsm)
284 }
mpagenko73143992021-04-09 15:17:10 +0000285
286 //wait for completion of possibly ongoing techprofile config/remove requests to avoid
287 // access conflicts on internal data by next needed data clearance
288 //activity should be aborted in short time if running with FSM due to above FSM reset
289 // or finished without FSM dependency in short time
290 oFsm.pUniTechProf.lockTpProcMutex()
291 defer oFsm.pUniTechProf.unlockTpProcMutex()
292 //remove all TechProf related internal data to allow for new configuration
293 oFsm.pUniTechProf.clearAniSideConfig(ctx, oFsm.pOnuUniPort.uniID, oFsm.techProfileID)
mpagenko7d6bb022021-03-11 15:07:55 +0000294}
295
dbainbri4d3a0dc2020-12-02 00:33:42 +0000296func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
Himani Chawla26e555c2020-08-31 12:30:20 +0530297 if aPAFsm != nil && aPAFsm.pFsm != nil {
298 //stick to pythonAdapter numbering scheme
299 //index 0 in naming refers to possible usage of multiple instances (later)
Girish Gowdra041dcb32020-11-16 16:54:30 -0800300 oFsm.mapperSP0ID = ieeeMapperServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) + uint16(oFsm.techProfileID)
301 oFsm.macBPCD0ID = macBridgePortAniEID + uint16(oFsm.pOnuUniPort.entityID) + uint16(oFsm.techProfileID)
Himani Chawla26e555c2020-08-31 12:30:20 +0530302
Girish Gowdra041dcb32020-11-16 16:54:30 -0800303 /*
304 // Find a free TCONT Instance ID and use it
305 foundFreeTcontInstID := false
306 */
dbainbri4d3a0dc2020-12-02 00:33:42 +0000307 if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
Girish Gowdra041dcb32020-11-16 16:54:30 -0800308
309 // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
310 // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
311 // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
312 // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
313 // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
314 // when the ONU is discovered.
315 /*
316 for _, tcontInstID := range tcontInstKeys {
317 tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
318 returnVal := tconInst["AllocId"]
319 if returnVal != nil {
320 if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
321 // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
322 if allocID == 0xff || allocID == 0xffff {
323 foundFreeTcontInstID = true
324 oFsm.tcont0ID = uint16(tcontInstID)
325 logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
326 "device-id": oFsm.deviceID})
327 break
328 }
329 } else {
330 logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
331 }
332 } else {
333 logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
334 }
335 }
336 */
337
338 // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
339 if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
340 // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
341 // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
342 // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
343 // TP ID will increment in single digit
344 oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
dbainbri4d3a0dc2020-12-02 00:33:42 +0000345 logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800346 "device-id": oFsm.deviceID})
347 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000348 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 -0800349 if oFsm.chanSet {
350 // indicate processing error/abort to the caller
351 oFsm.chSuccess <- 0
352 oFsm.chanSet = false //reset the internal channel state
353 }
354 //reset the state machine to enable usage on subsequent requests
355 _ = aPAFsm.pFsm.Event(aniEvReset)
356 return
357 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530358 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000359 logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra041dcb32020-11-16 16:54:30 -0800360 return
Himani Chawla26e555c2020-08-31 12:30:20 +0530361 }
Girish Gowdra041dcb32020-11-16 16:54:30 -0800362 /*
363 if !foundFreeTcontInstID {
364 // This should never happen. If it does, the behavior is unpredictable.
365 logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
366 }*/
367
368 // Access critical state with lock
369 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000370 oFsm.alloc0ID = oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID
371 mapGemPortParams := oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].mapGemPortParams
Girish Gowdra041dcb32020-11-16 16:54:30 -0800372 oFsm.pUniTechProf.mutexTPState.Unlock()
373
Himani Chawla26e555c2020-08-31 12:30:20 +0530374 //for all TechProfile set GemIndices
Girish Gowdra041dcb32020-11-16 16:54:30 -0800375 for _, gemEntry := range mapGemPortParams {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300376 loGemPortAttribs := ponAniGemPortAttribs{}
377
Himani Chawla26e555c2020-08-31 12:30:20 +0530378 //collect all GemConfigData in a separate Fsm related slice (needed also to avoid mix-up with unsorted mapPonAniConfig)
379
dbainbri4d3a0dc2020-12-02 00:33:42 +0000380 if queueInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.PriorityQueueClassID); len(queueInstKeys) > 0 {
Himani Chawla26e555c2020-08-31 12:30:20 +0530381
382 loGemPortAttribs.gemPortID = gemEntry.gemPortID
383 // MibDb usage: upstream PrioQueue.RelatedPort = xxxxyyyy with xxxx=TCont.Entity(incl. slot) and yyyy=prio
384 // i.e.: search PrioQueue list with xxxx=actual T-Cont.Entity,
385 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == yyyy (expect 0..7)
386 usQrelPortMask := uint32((((uint32)(oFsm.tcont0ID)) << 16) + uint32(gemEntry.prioQueueIndex))
387
388 // MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
389 // i.e.: search PrioQueue list with yy=actual pOnuUniPort.uniID,
390 // from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
391 // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
392 // Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
393 dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.uniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
394
395 usQueueFound := false
396 dsQueueFound := false
397 for _, mgmtEntityID := range queueInstKeys {
398 if meAttributes := oFsm.pOnuDB.GetMe(me.PriorityQueueClassID, mgmtEntityID); meAttributes != nil {
399 returnVal := meAttributes["RelatedPort"]
400 if returnVal != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530401 if relatedPort, err := oFsm.pOnuDB.getUint32Attrib(returnVal); err == nil {
Himani Chawla26e555c2020-08-31 12:30:20 +0530402 if relatedPort == usQrelPortMask {
403 loGemPortAttribs.upQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000404 logger.Debugw(ctx, "UpQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000405 "upQueueID": strconv.FormatInt(int64(loGemPortAttribs.upQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530406 usQueueFound = true
407 } else if (relatedPort&0xFFFFFF) == dsQrelPortMask && mgmtEntityID < 0x8000 {
408 loGemPortAttribs.downQueueID = mgmtEntityID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000409 logger.Debugw(ctx, "DownQueue for GemPort found:", log.Fields{"gemPortID": loGemPortAttribs.gemPortID,
mpagenko01e726e2020-10-23 09:45:29 +0000410 "downQueueID": strconv.FormatInt(int64(loGemPortAttribs.downQueueID), 16), "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530411 dsQueueFound = true
412 }
413 if usQueueFound && dsQueueFound {
414 break
415 }
416 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000417 logger.Warnw(ctx, "Could not convert attribute value", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530418 }
419 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000420 logger.Warnw(ctx, "'RelatedPort' not found in meAttributes:", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530421 }
422 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000423 logger.Warnw(ctx, "No attributes available in DB:", log.Fields{"meClassID": me.PriorityQueueClassID,
mpagenko01e726e2020-10-23 09:45:29 +0000424 "mgmtEntityID": mgmtEntityID, "device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530425 }
426 }
427 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000428 logger.Warnw(ctx, "No PriorityQueue instances found", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla26e555c2020-08-31 12:30:20 +0530429 }
430 loGemPortAttribs.direction = gemEntry.direction
431 loGemPortAttribs.qosPolicy = gemEntry.queueSchedPolicy
432 loGemPortAttribs.weight = gemEntry.queueWeight
433 loGemPortAttribs.pbitString = gemEntry.pbitString
ozgecanetsia4b232302020-11-11 10:58:10 +0300434 if gemEntry.isMulticast {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300435 //TODO this might effectively ignore the for loop starting at line 316
436 loGemPortAttribs.gemPortID = gemEntry.multicastGemPortID
ozgecanetsia4b232302020-11-11 10:58:10 +0300437 loGemPortAttribs.isMulticast = true
438 loGemPortAttribs.multicastGemID = gemEntry.multicastGemPortID
439 loGemPortAttribs.staticACL = gemEntry.staticACL
440 loGemPortAttribs.dynamicACL = gemEntry.dynamicACL
Himani Chawla26e555c2020-08-31 12:30:20 +0530441
dbainbri4d3a0dc2020-12-02 00:33:42 +0000442 logger.Debugw(ctx, "Multicast GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300443 "gemPortID": loGemPortAttribs.gemPortID,
444 "isMulticast": loGemPortAttribs.isMulticast,
445 "multicastGemID": loGemPortAttribs.multicastGemID,
446 "staticACL": loGemPortAttribs.staticACL,
447 "dynamicACL": loGemPortAttribs.dynamicACL,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000448 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300449 })
450
451 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000452 logger.Debugw(ctx, "Upstream GemPort attributes:", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300453 "gemPortID": loGemPortAttribs.gemPortID,
454 "upQueueID": loGemPortAttribs.upQueueID,
455 "downQueueID": loGemPortAttribs.downQueueID,
456 "pbitString": loGemPortAttribs.pbitString,
457 "prioQueueIndex": gemEntry.prioQueueIndex,
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000458 "device-id": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300459 })
460 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530461
462 oFsm.gemPortAttribsSlice = append(oFsm.gemPortAttribsSlice, loGemPortAttribs)
463 }
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000464 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
465 _ = aPAFsm.pFsm.Event(aniEvStartConfig)
466 } else {
467 logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"device-id": oFsm.deviceID})
468 _ = aPAFsm.pFsm.Event(aniEvSkipOmciConfig)
469 }
Himani Chawla26e555c2020-08-31 12:30:20 +0530470 }
471}
472
dbainbri4d3a0dc2020-12-02 00:33:42 +0000473func (oFsm *uniPonAniConfigFsm) enterConfigStartingState(ctx context.Context, e *fsm.Event) {
474 logger.Debugw(ctx, "UniPonAniConfigFsm start", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000475 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000476 // in case the used channel is not yet defined (can be re-used after restarts)
477 if oFsm.omciMIdsResponseReceived == nil {
478 oFsm.omciMIdsResponseReceived = make(chan bool)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000479 logger.Debug(ctx, "uniPonAniConfigFsm - OMCI multiInstance RxChannel defined")
mpagenko3dbcdd22020-07-22 07:38:45 +0000480 } else {
481 // as we may 're-use' this instance of FSM and the connected channel
482 // make sure there is no 'lingering' request in the already existing channel:
483 // (simple loop sufficient as we are the only receiver)
484 for len(oFsm.omciMIdsResponseReceived) > 0 {
485 <-oFsm.omciMIdsResponseReceived
486 }
487 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000488 //ensure internal slices are empty (which might be set from previous run) - release memory
489 oFsm.gemPortAttribsSlice = nil
mpagenkocf48e452021-04-23 09:23:00 +0000490 oFsm.mutexIsAwaitingResponse.Lock()
491 //reset the canceled state possibly existing from previous reset
492 oFsm.isCanceled = false
493 oFsm.mutexIsAwaitingResponse.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000494
Holger Hildebrandtbe523842021-03-10 10:47:18 +0000495 // start go routine for processing of ANI config messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000496 go oFsm.processOmciAniMessages(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000497
498 //let the state machine run forward from here directly
499 pConfigAniStateAFsm := oFsm.pAdaptFsm
500 if pConfigAniStateAFsm != nil {
501 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
dbainbri4d3a0dc2020-12-02 00:33:42 +0000502 go oFsm.prepareAndEnterConfigState(ctx, pConfigAniStateAFsm)
mpagenko3dbcdd22020-07-22 07:38:45 +0000503
mpagenko3dbcdd22020-07-22 07:38:45 +0000504 }
505}
506
dbainbri4d3a0dc2020-12-02 00:33:42 +0000507func (oFsm *uniPonAniConfigFsm) enterCreatingDot1PMapper(ctx context.Context, e *fsm.Event) {
508 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::Dot1PMapper", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000509 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000510 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
511 oFsm.requestEventOffset = 0 //0 offset for last config request activity
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000512 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300513 meInstance, err := oFsm.pOmciCC.sendCreateDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000514 oFsm.mapperSP0ID, oFsm.pAdaptFsm.commChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300515 if err != nil {
516 logger.Errorw(ctx, "Dot1PMapper create failed, aborting uniPonAniConfigFsm!",
517 log.Fields{"device-id": oFsm.deviceID})
518 pConfigAniStateAFsm := oFsm.pAdaptFsm
519 if pConfigAniStateAFsm != nil {
520 oFsm.mutexPLastTxMeInstance.Unlock()
521 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
522 go func(aPAFsm *AdapterFsm) {
523 if aPAFsm != nil && aPAFsm.pFsm != nil {
524 _ = aPAFsm.pFsm.Event(aniEvReset)
525 }
526 }(pConfigAniStateAFsm)
527 return
528 }
529 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000530 //accept also nil as (error) return value for writing to LastTx
531 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000532 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300533 oFsm.mutexPLastTxMeInstance.Unlock()
534
mpagenko3dbcdd22020-07-22 07:38:45 +0000535}
536
dbainbri4d3a0dc2020-12-02 00:33:42 +0000537func (oFsm *uniPonAniConfigFsm) enterCreatingMBPCD(ctx context.Context, e *fsm.Event) {
538 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::MBPCD", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000539 "EntitytId": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16),
540 "TPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000541 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000542 bridgePtr := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo) //cmp also omci_cc.go::sendCreateMBServiceProfile
543 meParams := me.ParamData{
544 EntityID: oFsm.macBPCD0ID,
545 Attributes: me.AttributeValueMap{
546 "BridgeIdPointer": bridgePtr,
547 "PortNum": 0xFF, //fixed unique ANI side indication
548 "TpType": 3, //for .1PMapper
549 "TpPointer": oFsm.mapperSP0ID,
550 },
551 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000552 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300553 meInstance, err := oFsm.pOmciCC.sendCreateMBPConfigDataVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000554 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300555 if err != nil {
556 logger.Errorw(ctx, "MBPConfigDataVar create failed, aborting uniPonAniConfigFsm!",
557 log.Fields{"device-id": oFsm.deviceID})
558 pConfigAniStateAFsm := oFsm.pAdaptFsm
559 if pConfigAniStateAFsm != nil {
560 oFsm.mutexPLastTxMeInstance.Unlock()
561 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
562 go func(aPAFsm *AdapterFsm) {
563 if aPAFsm != nil && aPAFsm.pFsm != nil {
564 _ = aPAFsm.pFsm.Event(aniEvReset)
565 }
566 }(pConfigAniStateAFsm)
567 return
568 }
569 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000570 //accept also nil as (error) return value for writing to LastTx
571 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000572 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300573 oFsm.mutexPLastTxMeInstance.Unlock()
574
mpagenko3dbcdd22020-07-22 07:38:45 +0000575}
576
dbainbri4d3a0dc2020-12-02 00:33:42 +0000577func (oFsm *uniPonAniConfigFsm) enterSettingTconts(ctx context.Context, e *fsm.Event) {
578 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
mpagenko3dbcdd22020-07-22 07:38:45 +0000579 "EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
580 "AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
mpagenko8b07c1b2020-11-26 10:36:31 +0000581 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000582 meParams := me.ParamData{
583 EntityID: oFsm.tcont0ID,
584 Attributes: me.AttributeValueMap{
585 "AllocId": oFsm.alloc0ID,
586 },
587 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000588 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300589 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko3dbcdd22020-07-22 07:38:45 +0000590 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300591 if err != nil {
592 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
593 log.Fields{"device-id": oFsm.deviceID})
594 pConfigAniStateAFsm := oFsm.pAdaptFsm
595 if pConfigAniStateAFsm != nil {
596 oFsm.mutexPLastTxMeInstance.Unlock()
597 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
598 go func(aPAFsm *AdapterFsm) {
599 if aPAFsm != nil && aPAFsm.pFsm != nil {
600 _ = aPAFsm.pFsm.Event(aniEvReset)
601 }
602 }(pConfigAniStateAFsm)
603 return
604 }
605 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000606 //accept also nil as (error) return value for writing to LastTx
607 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +0000608 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300609 oFsm.mutexPLastTxMeInstance.Unlock()
610
mpagenko3dbcdd22020-07-22 07:38:45 +0000611}
612
dbainbri4d3a0dc2020-12-02 00:33:42 +0000613func (oFsm *uniPonAniConfigFsm) enterCreatingGemNCTPs(ctx context.Context, e *fsm.Event) {
614 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemNWCtp loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000615 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000616 go oFsm.performCreatingGemNCTPs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000617}
618
dbainbri4d3a0dc2020-12-02 00:33:42 +0000619func (oFsm *uniPonAniConfigFsm) enterCreatingGemIWs(ctx context.Context, e *fsm.Event) {
620 logger.Debugw(ctx, "uniPonAniConfigFsm - start creating GemIwTP loop", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000621 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000622 go oFsm.performCreatingGemIWs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000623}
624
dbainbri4d3a0dc2020-12-02 00:33:42 +0000625func (oFsm *uniPonAniConfigFsm) enterSettingPQs(ctx context.Context, e *fsm.Event) {
626 logger.Debugw(ctx, "uniPonAniConfigFsm - start setting PrioQueue loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000627 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000628 go oFsm.performSettingPQs(ctx)
mpagenko3dbcdd22020-07-22 07:38:45 +0000629}
630
dbainbri4d3a0dc2020-12-02 00:33:42 +0000631func (oFsm *uniPonAniConfigFsm) enterSettingDot1PMapper(ctx context.Context, e *fsm.Event) {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300632
dbainbri4d3a0dc2020-12-02 00:33:42 +0000633 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::.1pMapper with all PBits set", log.Fields{"EntitytId": 0x8042, /*cmp above*/
mpagenko8b07c1b2020-11-26 10:36:31 +0000634 "toGemIw": 1024, /* cmp above */
635 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
mpagenko3dbcdd22020-07-22 07:38:45 +0000636
dbainbri4d3a0dc2020-12-02 00:33:42 +0000637 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::1pMapper", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000638 "EntitytId": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000639 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000640
mpagenko3dbcdd22020-07-22 07:38:45 +0000641 meParams := me.ParamData{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000642 EntityID: oFsm.mapperSP0ID,
Himani Chawla4d908332020-08-31 12:30:20 +0530643 Attributes: make(me.AttributeValueMap),
mpagenko3dbcdd22020-07-22 07:38:45 +0000644 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000645
646 //assign the GemPorts according to the configured Prio
647 var loPrioGemPortArray [8]uint16
648 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300649 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000650 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring .1pMapper", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300651 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
652 "prioString": gemPortAttribs.pbitString})
653 continue
654 }
655 if gemPortAttribs.pbitString == "" {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000656 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString empty string error", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300657 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
658 "prioString": gemPortAttribs.pbitString})
659 continue
660 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000661 for i := 0; i < 8; i++ {
662 // "lenOfPbitMap(8) - i + 1" will give i-th pbit value from LSB position in the pbit map string
663 if prio, err := strconv.Atoi(string(gemPortAttribs.pbitString[7-i])); err == nil {
664 if prio == 1 { // Check this p-bit is set
665 if loPrioGemPortArray[i] == 0 {
666 loPrioGemPortArray[i] = gemPortAttribs.gemPortID //gemPortId=EntityID and unique
667 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000668 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString not unique", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000669 "device-id": oFsm.deviceID, "IgnoredGemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000670 "SetGemPort": loPrioGemPortArray[i]})
671 }
672 }
673 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000674 logger.Warnw(ctx, "uniPonAniConfigFsm PrioString evaluation error", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000675 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000676 "prioString": gemPortAttribs.pbitString, "position": i})
677 }
678
679 }
680 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300681
ozgecanetsia4b232302020-11-11 10:58:10 +0300682 var foundIwPtr = false
Himani Chawla4d908332020-08-31 12:30:20 +0530683 for index, value := range loPrioGemPortArray {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300684 meAttribute := fmt.Sprintf("InterworkTpPointerForPBitPriority%d", index)
Himani Chawla4d908332020-08-31 12:30:20 +0530685 if value != 0 {
686 foundIwPtr = true
Himani Chawla4d908332020-08-31 12:30:20 +0530687 meParams.Attributes[meAttribute] = value
dbainbri4d3a0dc2020-12-02 00:33:42 +0000688 logger.Debugw(ctx, "UniPonAniConfigFsm Set::1pMapper", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000689 "for Prio": index,
690 "IwPtr": strconv.FormatInt(int64(value), 16),
691 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300692 } else {
693 // The null pointer 0xFFFF specifies that frames with the associated priority are to be discarded.
mpagenko8b5fdd22020-12-17 17:58:32 +0000694 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
695 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300696 meParams.Attributes[meAttribute] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530697 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000698 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300699 // The TP type value 0 also indicates bridging mapping, and the TP pointer should be set to 0xFFFF
mpagenko8b5fdd22020-12-17 17:58:32 +0000700 // setting this parameter is not strictly needed anymore with the ensured .1pMapper create default setting
701 // but except for processing effort does not really harm - left to keep changes low
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300702 meParams.Attributes["TpPointer"] = 0xffff
Himani Chawla4d908332020-08-31 12:30:20 +0530703
704 if !foundIwPtr {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000705 logger.Debugw(ctx, "UniPonAniConfigFsm no GemIwPtr found for .1pMapper - abort", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000706 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300707 //TODO With multicast is possible that no upstream gem ports are not present in the tech profile,
708 // 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 +0000709 //let's reset the state machine in order to release all resources now
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300710 //pConfigAniStateAFsm := oFsm.pAdaptFsm
711 //if pConfigAniStateAFsm != nil {
712 // // obviously calling some FSM event here directly does not work - so trying to decouple it ...
713 // go func(aPAFsm *AdapterFsm) {
714 // if aPAFsm != nil && aPAFsm.pFsm != nil {
715 // _ = aPAFsm.pFsm.Event(aniEvReset)
716 // }
717 // }(pConfigAniStateAFsm)
718 //}
719 //Moving forward the FSM as if the response was received correctly.
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000720 pConfigAniStateAFsm := oFsm.pAdaptFsm
721 if pConfigAniStateAFsm != nil {
722 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
Himani Chawla26e555c2020-08-31 12:30:20 +0530723 go func(aPAFsm *AdapterFsm) {
724 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300725 _ = aPAFsm.pFsm.Event(aniEvRxDot1pmapSResp)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000726 }
727 }(pConfigAniStateAFsm)
728 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300729 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000730 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300731 meInstance, err := oFsm.pOmciCC.sendSetDot1PMapperVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300732 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300733 if err != nil {
734 logger.Errorw(ctx, "Dot1PMapperVar set failed, aborting uniPonAniConfigFsm!",
735 log.Fields{"device-id": oFsm.deviceID})
736 pConfigAniStateAFsm := oFsm.pAdaptFsm
737 if pConfigAniStateAFsm != nil {
738 oFsm.mutexPLastTxMeInstance.Unlock()
739 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
740 go func(aPAFsm *AdapterFsm) {
741 if aPAFsm != nil && aPAFsm.pFsm != nil {
742 _ = aPAFsm.pFsm.Event(aniEvReset)
743 }
744 }(pConfigAniStateAFsm)
745 return
746 }
747 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300748 //accept also nil as (error) return value for writing to LastTx
749 // - this avoids misinterpretation of new received OMCI messages
750 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300751 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +0000752 }
mpagenko3dbcdd22020-07-22 07:38:45 +0000753}
754
dbainbri4d3a0dc2020-12-02 00:33:42 +0000755func (oFsm *uniPonAniConfigFsm) enterAniConfigDone(ctx context.Context, e *fsm.Event) {
756 logger.Debugw(ctx, "uniPonAniConfigFsm ani config done", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000757 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
mpagenko01e726e2020-10-23 09:45:29 +0000758 //store that the UNI related techProfile processing is done for the given Profile and Uni
Girish Gowdra041dcb32020-11-16 16:54:30 -0800759 oFsm.pUniTechProf.setConfigDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID, true)
Holger Hildebrandt01bc3bf2021-04-26 09:59:01 +0000760 if !oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
761 //use DeviceHandler event notification directly
762 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
763 //if techProfile processing is done it must be checked, if some prior/parallel flow configuration is pending
764 // but only in case the techProfile was configured (not deleted)
765 if oFsm.requestEventOffset == 0 {
766 go oFsm.pDeviceHandler.verifyUniVlanConfigRequest(ctx, oFsm.pOnuUniPort, oFsm.techProfileID)
767 }
768 } else {
769 logger.Debugw(ctx, "reconciling - skip AniConfigDone processing", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +0000770 }
mpagenko01e726e2020-10-23 09:45:29 +0000771 if oFsm.chanSet {
772 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +0000773 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000774 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
775 oFsm.chSuccess <- oFsm.procStep
776 oFsm.chanSet = false //reset the internal channel state
mpagenko3dbcdd22020-07-22 07:38:45 +0000777 }
mpagenko01e726e2020-10-23 09:45:29 +0000778
779 //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 +0000780}
781
dbainbri4d3a0dc2020-12-02 00:33:42 +0000782func (oFsm *uniPonAniConfigFsm) enterRemovingGemIW(ctx context.Context, e *fsm.Event) {
mpagenkoa23a6292021-02-23 10:40:10 +0000783 oFsm.pUniTechProf.mutexTPState.Lock()
mpagenkobb47bc22021-04-20 13:29:09 +0000784 //flush the waitFlowDeleteChannel - possibly already/still set by some previous activity
785 select {
786 case <-oFsm.waitFlowDeleteChannel:
787 logger.Debug(ctx, "flushed waitFlowDeleteChannel")
788 default:
789 }
790 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
mpagenkoa23a6292021-02-23 10:40:10 +0000791 oFsm.pUniTechProf.mutexTPState.Unlock()
Girish Gowdra26a40922021-01-29 17:14:34 -0800792 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
793 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
794 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
795 pConfigAniStateAFsm := oFsm.pAdaptFsm
796 if pConfigAniStateAFsm != nil {
797 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
798 go func(aPAFsm *AdapterFsm) {
799 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300800 _ = aPAFsm.pFsm.Event(aniEvWaitFlowRem)
Girish Gowdra26a40922021-01-29 17:14:34 -0800801 }
802 }(pConfigAniStateAFsm)
803 } else {
804 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
805 }
806 return
807 }
808
mpagenko8b07c1b2020-11-26 10:36:31 +0000809 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000810 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
811 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000812 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000813 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
814 "GemIwTp-entity-id": loGemPortID})
815 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
816
817 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000818 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300819 meInstance, err := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000820 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300821 if err != nil {
822 logger.Errorw(ctx, "GemIWTP delete failed, aborting uniPonAniConfigFsm!",
823 log.Fields{"device-id": oFsm.deviceID})
824 pConfigAniStateAFsm := oFsm.pAdaptFsm
825 if pConfigAniStateAFsm != nil {
826 oFsm.mutexPLastTxMeInstance.Unlock()
827 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
828 go func(aPAFsm *AdapterFsm) {
829 if aPAFsm != nil && aPAFsm.pFsm != nil {
830 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
831 }
832 }(pConfigAniStateAFsm)
833 return
834 }
835 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000836 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300837 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000838}
839
mpagenkobb47bc22021-04-20 13:29:09 +0000840func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
841 oFsm.mutexIsAwaitingResponse.Lock()
842 oFsm.isWaitingForFlowDelete = true
843 oFsm.mutexIsAwaitingResponse.Unlock()
844 select {
845 // maybe be also some outside cancel (but no context modeled for the moment ...)
846 // case <-ctx.Done():
847 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
848 case <-time.After(10 * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
849 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
850 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
851 oFsm.mutexIsAwaitingResponse.Lock()
852 oFsm.isWaitingForFlowDelete = false
853 oFsm.mutexIsAwaitingResponse.Unlock()
854 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
855 pConfigAniStateAFsm := oFsm.pAdaptFsm
856 if pConfigAniStateAFsm != nil {
857 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
858 go func(aPAFsm *AdapterFsm) {
859 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300860 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000861 }
862 }(pConfigAniStateAFsm)
863 } else {
864 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
865 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
866 }
867 return
868
869 case success := <-oFsm.waitFlowDeleteChannel:
870 if success {
871 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
872 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
873 oFsm.mutexIsAwaitingResponse.Lock()
874 oFsm.isWaitingForFlowDelete = false
875 oFsm.mutexIsAwaitingResponse.Unlock()
876 pConfigAniStateAFsm := oFsm.pAdaptFsm
877 if pConfigAniStateAFsm != nil {
878 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
879 go func(aPAFsm *AdapterFsm) {
880 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300881 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000882 }
883 }(pConfigAniStateAFsm)
884 } else {
885 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
886 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
887 }
888 return
889 }
890 // waiting was aborted (probably on external request)
891 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
892 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
893 oFsm.mutexIsAwaitingResponse.Lock()
894 oFsm.isWaitingForFlowDelete = false
895 oFsm.mutexIsAwaitingResponse.Unlock()
896 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
897 pConfigAniStateAFsm := oFsm.pAdaptFsm
898 if pConfigAniStateAFsm != nil {
899 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
900 go func(aPAFsm *AdapterFsm) {
901 if aPAFsm != nil && aPAFsm.pFsm != nil {
902 _ = aPAFsm.pFsm.Event(aniEvReset)
903 }
904 }(pConfigAniStateAFsm)
905 }
906 return
907 }
908}
909
dbainbri4d3a0dc2020-12-02 00:33:42 +0000910func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000911 oFsm.pUniTechProf.mutexTPState.Lock()
912 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
913 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000914 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000915 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
916 "GemNCTP-entity-id": loGemPortID})
917 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000918 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300919 meInstance, err := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000920 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300921 if err != nil {
922 logger.Errorw(ctx, "GemNCTP delete failed, aborting uniPonAniConfigFsm!",
923 log.Fields{"device-id": oFsm.deviceID})
924 pConfigAniStateAFsm := oFsm.pAdaptFsm
925 if pConfigAniStateAFsm != nil {
926 oFsm.mutexPLastTxMeInstance.Unlock()
927 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
928 go func(aPAFsm *AdapterFsm) {
929 if aPAFsm != nil && aPAFsm.pFsm != nil {
930 _ = aPAFsm.pFsm.Event(aniEvReset)
931 }
932 }(pConfigAniStateAFsm)
933 return
934 }
935 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000936 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000937 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300938
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800939 // Mark the gem port to be removed for Performance History monitoring
940 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700941 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800942 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000943}
944
dbainbri4d3a0dc2020-12-02 00:33:42 +0000945func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
946 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000947 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
948
949 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
950 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
951 meParams := me.ParamData{
952 EntityID: oFsm.tcont0ID,
953 Attributes: me.AttributeValueMap{
954 "AllocId": unusedTcontAllocID,
955 },
956 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000957 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300958 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000959 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300960 if err != nil {
961 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
962 log.Fields{"device-id": oFsm.deviceID})
963 pConfigAniStateAFsm := oFsm.pAdaptFsm
964 if pConfigAniStateAFsm != nil {
965 oFsm.mutexPLastTxMeInstance.Unlock()
966 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
967 go func(aPAFsm *AdapterFsm) {
968 if aPAFsm != nil && aPAFsm.pFsm != nil {
969 _ = aPAFsm.pFsm.Event(aniEvReset)
970 }
971 }(pConfigAniStateAFsm)
972 return
973 }
974 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000975 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300976 oFsm.mutexPLastTxMeInstance.Unlock()
977
mpagenko8b07c1b2020-11-26 10:36:31 +0000978}
979
dbainbri4d3a0dc2020-12-02 00:33:42 +0000980func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
981 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000982 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
983
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000984 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300985 meInstance, err := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000986 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300987 if err != nil {
988 logger.Errorw(ctx, "Dot1Mapper delete failed, aborting uniPonAniConfigFsm!",
989 log.Fields{"device-id": oFsm.deviceID})
990 pConfigAniStateAFsm := oFsm.pAdaptFsm
991 if pConfigAniStateAFsm != nil {
992 oFsm.mutexPLastTxMeInstance.Unlock()
993 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
994 go func(aPAFsm *AdapterFsm) {
995 if aPAFsm != nil && aPAFsm.pFsm != nil {
996 _ = aPAFsm.pFsm.Event(aniEvReset)
997 }
998 }(pConfigAniStateAFsm)
999 return
1000 }
1001 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001002 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001003 oFsm.mutexPLastTxMeInstance.Unlock()
1004
mpagenko8b07c1b2020-11-26 10:36:31 +00001005}
1006
dbainbri4d3a0dc2020-12-02 00:33:42 +00001007func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
1008 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001009 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1010
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001011 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001012 meInstance, err := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001013 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001014 if err != nil {
1015 logger.Errorw(ctx, "MBPConfigData delete failed, aborting uniPonAniConfigFsm!",
1016 log.Fields{"device-id": oFsm.deviceID})
1017 pConfigAniStateAFsm := oFsm.pAdaptFsm
1018 if pConfigAniStateAFsm != nil {
1019 oFsm.mutexPLastTxMeInstance.Unlock()
1020 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1021 go func(aPAFsm *AdapterFsm) {
1022 if aPAFsm != nil && aPAFsm.pFsm != nil {
1023 _ = aPAFsm.pFsm.Event(aniEvReset)
1024 }
1025 }(pConfigAniStateAFsm)
1026 return
1027 }
1028 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001029 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001030 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001031}
1032
dbainbri4d3a0dc2020-12-02 00:33:42 +00001033func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
1034 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001035 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1036 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001037 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +00001038 if oFsm.chanSet {
1039 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +00001040 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001041 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
1042 oFsm.chSuccess <- oFsm.procStep
1043 oFsm.chanSet = false //reset the internal channel state
1044 }
1045
1046 //let's reset the state machine in order to release all resources now
1047 pConfigAniStateAFsm := oFsm.pAdaptFsm
1048 if pConfigAniStateAFsm != nil {
1049 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1050 go func(aPAFsm *AdapterFsm) {
1051 if aPAFsm != nil && aPAFsm.pFsm != nil {
1052 _ = aPAFsm.pFsm.Event(aniEvReset)
1053 }
1054 }(pConfigAniStateAFsm)
1055 }
1056}
1057
dbainbri4d3a0dc2020-12-02 00:33:42 +00001058func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
1059 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001060 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001061
mpagenko3dbcdd22020-07-22 07:38:45 +00001062 pConfigAniStateAFsm := oFsm.pAdaptFsm
1063 if pConfigAniStateAFsm != nil {
1064 // abort running message processing
1065 fsmAbortMsg := Message{
1066 Type: TestMsg,
1067 Data: TestMessage{
1068 TestMessageVal: AbortMessageProcessing,
1069 },
1070 }
1071 pConfigAniStateAFsm.commChan <- fsmAbortMsg
1072
1073 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +05301074 go func(aPAFsm *AdapterFsm) {
1075 if aPAFsm != nil && aPAFsm.pFsm != nil {
1076 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +00001077 }
1078 }(pConfigAniStateAFsm)
1079 }
1080}
1081
dbainbri4d3a0dc2020-12-02 00:33:42 +00001082func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
1083 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001084 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001085 oFsm.mutexPLastTxMeInstance.Lock()
1086 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001087 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +00001088}
1089
dbainbri4d3a0dc2020-12-02 00:33:42 +00001090func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
1091 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001092loop:
1093 for {
mpagenko3dbcdd22020-07-22 07:38:45 +00001094 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001095 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001096 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301097 message, ok := <-oFsm.pAdaptFsm.commChan
1098 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001099 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301100 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1101 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1102 break loop
1103 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001104 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301105
1106 switch message.Type {
1107 case TestMsg:
1108 msg, _ := message.Data.(TestMessage)
1109 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001110 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001111 break loop
1112 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001113 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301114 case OMCI:
1115 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001116 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301117 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001118 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301119 "message.Type": message.Type})
1120 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001121
Himani Chawla4d908332020-08-31 12:30:20 +05301122 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001123 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301124}
1125
dbainbri4d3a0dc2020-12-02 00:33:42 +00001126func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301127 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
1128 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001129 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001130 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301131 return
1132 }
1133 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1134 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001135 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001136 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301137 return
1138 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001139 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +00001140 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1141 //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 +00001142 oFsm.mutexPLastTxMeInstance.RLock()
1143 if oFsm.pLastTxMeInstance != nil {
1144 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1145 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1146 // maybe we can use just the same eventName for different state transitions like "forward"
1147 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1148 switch oFsm.pLastTxMeInstance.GetName() {
1149 case "Ieee8021PMapperServiceProfile":
1150 { // let the FSM proceed ...
1151 oFsm.mutexPLastTxMeInstance.RUnlock()
1152 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1153 }
1154 case "MacBridgePortConfigurationData":
1155 { // let the FSM proceed ...
1156 oFsm.mutexPLastTxMeInstance.RUnlock()
1157 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1158 }
1159 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1160 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1161 oFsm.mutexPLastTxMeInstance.RUnlock()
1162 oFsm.omciMIdsResponseReceived <- true
1163 }
1164 default:
1165 {
1166 oFsm.mutexPLastTxMeInstance.RUnlock()
1167 logger.Warnw(ctx, "Unsupported ME name received!",
1168 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1169 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001170 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001171 } else {
1172 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001173 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001174 } else {
1175 oFsm.mutexPLastTxMeInstance.RUnlock()
1176 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001177 }
1178 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001179 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1180 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301181 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1182 return
1183 }
Himani Chawla4d908332020-08-31 12:30:20 +05301184}
1185
dbainbri4d3a0dc2020-12-02 00:33:42 +00001186func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301187 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1188 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001189 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001190 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301191 return
1192 }
1193 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1194 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001195 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001196 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301197 return
1198 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001199 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301200 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001201 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001202 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301203 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1204 return
1205 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001206 oFsm.mutexPLastTxMeInstance.RLock()
1207 if oFsm.pLastTxMeInstance != nil {
1208 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1209 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1210 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1211 // if, then something like:
1212 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301213
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001214 switch oFsm.pLastTxMeInstance.GetName() {
1215 case "TCont":
1216 { // let the FSM proceed ...
1217 oFsm.mutexPLastTxMeInstance.RUnlock()
1218 if oFsm.requestEventOffset == 0 { //from TCont config request
1219 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1220 } else { // from T-Cont reset request
1221 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1222 }
1223 }
1224 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1225 { // let the PrioQueue init proceed by stopping the wait function
1226 oFsm.mutexPLastTxMeInstance.RUnlock()
1227 oFsm.omciMIdsResponseReceived <- true
1228 }
1229 case "Ieee8021PMapperServiceProfile":
1230 { // let the FSM proceed ...
1231 oFsm.mutexPLastTxMeInstance.RUnlock()
1232 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1233 }
1234 default:
1235 {
1236 oFsm.mutexPLastTxMeInstance.RUnlock()
1237 logger.Warnw(ctx, "Unsupported ME name received!",
1238 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001239 }
Himani Chawla4d908332020-08-31 12:30:20 +05301240 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001241 } else {
1242 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301243 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001244 } else {
1245 oFsm.mutexPLastTxMeInstance.RUnlock()
1246 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301247 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001248}
1249
dbainbri4d3a0dc2020-12-02 00:33:42 +00001250func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001251 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1252 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001253 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001254 log.Fields{"device-id": oFsm.deviceID})
1255 return
1256 }
1257 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1258 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001259 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001260 log.Fields{"device-id": oFsm.deviceID})
1261 return
1262 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001263 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001264 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001265 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001266 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1267 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1268 // store error for mgmt display?
1269 return
1270 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001271 oFsm.mutexPLastTxMeInstance.RLock()
1272 if oFsm.pLastTxMeInstance != nil {
1273 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1274 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1275 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1276 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001277
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001278 switch oFsm.pLastTxMeInstance.GetName() {
1279 case "GemInterworkingTerminationPoint":
1280 { // let the FSM proceed ...
1281 oFsm.mutexPLastTxMeInstance.RUnlock()
1282 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1283 }
1284 case "GemPortNetworkCtp":
1285 { // let the FSM proceed ...
1286 oFsm.mutexPLastTxMeInstance.RUnlock()
1287 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1288 }
1289 case "Ieee8021PMapperServiceProfile":
1290 { // let the FSM proceed ...
1291 oFsm.mutexPLastTxMeInstance.RUnlock()
1292 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1293 }
1294 case "MacBridgePortConfigurationData":
1295 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1296 oFsm.mutexPLastTxMeInstance.RUnlock()
1297 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1298 }
1299 default:
1300 {
1301 oFsm.mutexPLastTxMeInstance.RUnlock()
1302 logger.Warnw(ctx, "Unsupported ME name received!",
1303 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1304 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001305 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001306 } else {
1307 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001308 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001309 } else {
1310 oFsm.mutexPLastTxMeInstance.RUnlock()
1311 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001312 }
1313}
1314
dbainbri4d3a0dc2020-12-02 00:33:42 +00001315func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1316 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001317 "msgType": msg.OmciMsg.MessageType})
1318
1319 switch msg.OmciMsg.MessageType {
1320 case omci.CreateResponseType:
1321 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001322 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301323
mpagenko3dbcdd22020-07-22 07:38:45 +00001324 } //CreateResponseType
1325 case omci.SetResponseType:
1326 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001327 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001328
mpagenko3dbcdd22020-07-22 07:38:45 +00001329 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001330 case omci.DeleteResponseType:
1331 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001332 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001333
1334 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001335 default:
1336 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001337 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001338 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001339 return
1340 }
1341 }
1342}
1343
dbainbri4d3a0dc2020-12-02 00:33:42 +00001344func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001345 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1346 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001347 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001348 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1349 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001350 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001351 meParams := me.ParamData{
1352 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1353 Attributes: me.AttributeValueMap{
1354 "PortId": gemPortAttribs.gemPortID,
1355 "TContPointer": oFsm.tcont0ID,
1356 "Direction": gemPortAttribs.direction,
1357 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1358 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1359 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1360 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1361 },
1362 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001363 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001364 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001365 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001366 if err != nil {
1367 oFsm.mutexPLastTxMeInstance.Unlock()
1368 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1369 log.Fields{"device-id": oFsm.deviceID})
1370 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1371 return
1372 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001373 //accept also nil as (error) return value for writing to LastTx
1374 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001375 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001376 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001377 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001378 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001379 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001380 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001381 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301382 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001383 return
1384 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001385 // Mark the gem port to be removed for Performance History monitoring
1386 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001387 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001388 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001389 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001390
1391 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001392 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301393 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001394}
1395
dbainbri4d3a0dc2020-12-02 00:33:42 +00001396func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001397 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1398 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001399 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001400 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1401 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001402 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001403
ozgecanetsia4b232302020-11-11 10:58:10 +03001404 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1405 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001406
1407 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001408 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001409 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001410 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001411 "InterworkingOption": 0, // Don't Care
1412 "ServiceProfilePointer": 0, // Don't Care
1413 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001414 },
1415 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001416 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001417 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001418 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001419 if err != nil {
1420 oFsm.mutexPLastTxMeInstance.Unlock()
1421 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1422 log.Fields{"device-id": oFsm.deviceID})
1423 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1424 return
1425
1426 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001427 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001428 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001429 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001430 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001431 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001432 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001433 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1434 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1435 return
1436 }
1437 ipv4MulticastTable := make([]uint8, 12)
1438 //Gem Port ID
1439 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1440 //Secondary Key
1441 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1442 // Multicast IP range start This is the 224.0.0.1 address
1443 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1444 // MulticastIp range stop
1445 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1446
1447 meIPV4MCTableParams := me.ParamData{
1448 EntityID: gemPortAttribs.multicastGemID,
1449 Attributes: me.AttributeValueMap{
1450 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1451 },
1452 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001453 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001454 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001455 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001456 if err != nil {
1457 oFsm.mutexPLastTxMeInstance.Unlock()
1458 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1459 log.Fields{"device-id": oFsm.deviceID})
1460 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1461 return
1462 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001463 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001464 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001465
1466 } else {
1467 meParams := me.ParamData{
1468 EntityID: gemPortAttribs.gemPortID,
1469 Attributes: me.AttributeValueMap{
1470 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1471 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1472 "ServiceProfilePointer": oFsm.mapperSP0ID,
1473 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1474 "GalProfilePointer": galEthernetEID,
1475 },
1476 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001477 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001478 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001479 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001480 if err != nil {
1481 oFsm.mutexPLastTxMeInstance.Unlock()
1482 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1483 log.Fields{"device-id": oFsm.deviceID})
1484 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1485 return
1486 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001487 //accept also nil as (error) return value for writing to LastTx
1488 // - this avoids misinterpretation of new received OMCI messages
1489 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001490 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001491 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001492 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001493 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001494 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001495 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001496 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301497 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001498 return
1499 }
1500 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001501
1502 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001503 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301504 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001505}
1506
dbainbri4d3a0dc2020-12-02 00:33:42 +00001507func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001508 const cu16StrictPrioWeight uint16 = 0xFFFF
1509 //find all upstream PrioQueues related to this T-Cont
1510 loQueueMap := ordered_map.NewOrderedMap()
1511 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001512 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001513 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001514 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1515 "prioString": gemPortAttribs.pbitString})
1516 continue
1517 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001518 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301519 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001520 //key does not yet exist
1521 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1522 }
1523 } else {
1524 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1525 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001526 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001527
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001528 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1529 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1530 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1531 // or even be finished without correct SP/WRR setting
1532
1533 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1534 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1535 // even though its T-Cont seems to be wrong ...
1536 loTrafficSchedulerEID := 0x8000
1537 //for all found queues
1538 iter := loQueueMap.IterFunc()
1539 for kv, ok := iter(); ok; kv, ok = iter() {
1540 queueIndex := (kv.Key).(uint16)
1541 meParams := me.ParamData{
1542 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301543 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001544 }
1545 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1546 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001547 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001548 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001549 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001550 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1551 } else {
1552 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001553 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001554 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1555 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001556 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001557 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1558 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1559 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001560 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001561 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001562 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001563 if err != nil {
1564 oFsm.mutexPLastTxMeInstance.Unlock()
1565 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1566 log.Fields{"device-id": oFsm.deviceID})
1567 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1568 return
1569 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001570 //accept also nil as (error) return value for writing to LastTx
1571 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001572 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001573 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001574
1575 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001576 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001577 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001578 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001579 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301580 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001581 return
1582 }
1583
1584 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1585 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1586 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1587 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1588
1589 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001590
1591 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001592 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301593 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001594}
1595
dbainbri4d3a0dc2020-12-02 00:33:42 +00001596func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001597 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001598 if oFsm.isCanceled {
1599 // FSM already canceled before entering wait
1600 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1601 oFsm.mutexIsAwaitingResponse.Unlock()
1602 return fmt.Errorf(cErrWaitAborted)
1603 }
mpagenko7d6bb022021-03-11 15:07:55 +00001604 oFsm.isAwaitingResponse = true
1605 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001606 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301607 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001608 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001609 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001610 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 +00001611 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001612 oFsm.mutexIsAwaitingResponse.Lock()
1613 oFsm.isAwaitingResponse = false
1614 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001615 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001616 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301617 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001618 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001619 oFsm.mutexIsAwaitingResponse.Lock()
1620 oFsm.isAwaitingResponse = false
1621 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001622 return nil
1623 }
mpagenko7d6bb022021-03-11 15:07:55 +00001624 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001625 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001626 oFsm.mutexIsAwaitingResponse.Lock()
1627 oFsm.isAwaitingResponse = false
1628 oFsm.mutexIsAwaitingResponse.Unlock()
1629 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001630 }
1631}