blob: 2453f85052f878603ad9593d5c8d1961a30d8b23 [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 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000790
791 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID] != nil {
792 if oFsm.pDeviceHandler.UniVlanConfigFsmMap[oFsm.pOnuUniPort.uniID].IsFlowRemovePending(oFsm.waitFlowDeleteChannel) {
793 oFsm.pUniTechProf.mutexTPState.Unlock()
794 logger.Debugw(ctx, "flow remove pending - wait before processing gem port delete",
795 log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
796 // if flow remove is pending then wait for flow remove to finish first before proceeding with gem port delete
797 pConfigAniStateAFsm := oFsm.pAdaptFsm
798 if pConfigAniStateAFsm != nil {
799 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
800 go func(aPAFsm *AdapterFsm) {
801 if aPAFsm != nil && aPAFsm.pFsm != nil {
802 _ = aPAFsm.pFsm.Event(aniEvWaitFlowRem)
803 }
804 }(pConfigAniStateAFsm)
805 } else {
806 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{"device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
807 }
808 return
Girish Gowdra26a40922021-01-29 17:14:34 -0800809 }
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000810 } else {
811 logger.Debugw(ctx, "uni vlan config doesn't exist - no flow remove could be pending",
812 log.Fields{"device-id": oFsm.deviceID, "techProfile-id": oFsm.techProfileID})
Girish Gowdra26a40922021-01-29 17:14:34 -0800813 }
814
mpagenko8b07c1b2020-11-26 10:36:31 +0000815 // get the related GemPort entity Id from pUniTechProf, OMCI Gem* entityID is set to be equal to GemPortId!
mpagenko8b07c1b2020-11-26 10:36:31 +0000816 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
817 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000818 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemIwTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000819 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
820 "GemIwTp-entity-id": loGemPortID})
821 oFsm.requestEventOffset = 1 //offset 1 to indicate last activity = remove
822
823 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000824 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300825 meInstance, err := oFsm.pOmciCC.sendDeleteGemIWTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000826 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300827 if err != nil {
828 logger.Errorw(ctx, "GemIWTP delete failed, aborting uniPonAniConfigFsm!",
829 log.Fields{"device-id": oFsm.deviceID})
830 pConfigAniStateAFsm := oFsm.pAdaptFsm
831 if pConfigAniStateAFsm != nil {
832 oFsm.mutexPLastTxMeInstance.Unlock()
833 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
834 go func(aPAFsm *AdapterFsm) {
835 if aPAFsm != nil && aPAFsm.pFsm != nil {
836 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
837 }
838 }(pConfigAniStateAFsm)
839 return
840 }
841 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000842 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300843 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000844}
845
mpagenkobb47bc22021-04-20 13:29:09 +0000846func (oFsm *uniPonAniConfigFsm) enterWaitingFlowRem(ctx context.Context, e *fsm.Event) {
847 oFsm.mutexIsAwaitingResponse.Lock()
848 oFsm.isWaitingForFlowDelete = true
849 oFsm.mutexIsAwaitingResponse.Unlock()
850 select {
851 // maybe be also some outside cancel (but no context modeled for the moment ...)
852 // case <-ctx.Done():
853 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +0000854 case <-time.After(2 * oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //give flow processing enough time to finish (but try to be less than rwCore flow timeouts)
mpagenkobb47bc22021-04-20 13:29:09 +0000855 logger.Warnw(ctx, "uniPonAniConfigFsm WaitingFlowRem timeout", log.Fields{
856 "for device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
857 oFsm.mutexIsAwaitingResponse.Lock()
858 oFsm.isWaitingForFlowDelete = false
859 oFsm.mutexIsAwaitingResponse.Unlock()
860 //if the flow is not removed as expected we just try to continue with GemPort removal and hope things are clearing up afterwards
861 pConfigAniStateAFsm := oFsm.pAdaptFsm
862 if pConfigAniStateAFsm != nil {
863 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
864 go func(aPAFsm *AdapterFsm) {
865 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300866 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000867 }
868 }(pConfigAniStateAFsm)
869 } else {
870 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
871 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
872 }
873 return
874
875 case success := <-oFsm.waitFlowDeleteChannel:
876 if success {
877 logger.Debugw(ctx, "uniPonAniConfigFsm flow removed info received", log.Fields{
878 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
879 oFsm.mutexIsAwaitingResponse.Lock()
880 oFsm.isWaitingForFlowDelete = false
881 oFsm.mutexIsAwaitingResponse.Unlock()
882 pConfigAniStateAFsm := oFsm.pAdaptFsm
883 if pConfigAniStateAFsm != nil {
884 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
885 go func(aPAFsm *AdapterFsm) {
886 if aPAFsm != nil && aPAFsm.pFsm != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300887 _ = aPAFsm.pFsm.Event(aniEvFlowRemDone)
mpagenkobb47bc22021-04-20 13:29:09 +0000888 }
889 }(pConfigAniStateAFsm)
890 } else {
891 logger.Errorw(ctx, "pConfigAniStateAFsm is nil", log.Fields{
892 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
893 }
894 return
895 }
896 // waiting was aborted (probably on external request)
897 logger.Debugw(ctx, "uniPonAniConfigFsm WaitingFlowRem aborted", log.Fields{
898 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID, "techProfile-id": oFsm.techProfileID})
899 oFsm.mutexIsAwaitingResponse.Lock()
900 oFsm.isWaitingForFlowDelete = false
901 oFsm.mutexIsAwaitingResponse.Unlock()
902 //to be sure we can just generate the reset-event to ensure leaving this state towards 'reset'
903 pConfigAniStateAFsm := oFsm.pAdaptFsm
904 if pConfigAniStateAFsm != nil {
905 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
906 go func(aPAFsm *AdapterFsm) {
907 if aPAFsm != nil && aPAFsm.pFsm != nil {
908 _ = aPAFsm.pFsm.Event(aniEvReset)
909 }
910 }(pConfigAniStateAFsm)
911 }
912 return
913 }
914}
915
dbainbri4d3a0dc2020-12-02 00:33:42 +0000916func (oFsm *uniPonAniConfigFsm) enterRemovingGemNCTP(ctx context.Context, e *fsm.Event) {
mpagenko8b07c1b2020-11-26 10:36:31 +0000917 oFsm.pUniTechProf.mutexTPState.Lock()
918 loGemPortID := (*(oFsm.pUniTechProf.mapRemoveGemEntry[oFsm.uniTpKey])).gemPortID
919 oFsm.pUniTechProf.mutexTPState.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000920 logger.Debugw(ctx, "uniPonAniConfigFsm - start removing one GemNCTP", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000921 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
922 "GemNCTP-entity-id": loGemPortID})
923 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000924 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300925 meInstance, err := oFsm.pOmciCC.sendDeleteGemNCTP(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000926 oFsm.pAdaptFsm.commChan, loGemPortID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300927 if err != nil {
928 logger.Errorw(ctx, "GemNCTP delete failed, aborting uniPonAniConfigFsm!",
929 log.Fields{"device-id": oFsm.deviceID})
930 pConfigAniStateAFsm := oFsm.pAdaptFsm
931 if pConfigAniStateAFsm != nil {
932 oFsm.mutexPLastTxMeInstance.Unlock()
933 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
934 go func(aPAFsm *AdapterFsm) {
935 if aPAFsm != nil && aPAFsm.pFsm != nil {
936 _ = aPAFsm.pFsm.Event(aniEvReset)
937 }
938 }(pConfigAniStateAFsm)
939 return
940 }
941 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000942 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000943 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300944
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800945 // Mark the gem port to be removed for Performance History monitoring
946 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -0700947 oFsm.pDeviceHandler.pOnuMetricsMgr.RemoveGemPortForPerfMonitoring(ctx, loGemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800948 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000949}
950
dbainbri4d3a0dc2020-12-02 00:33:42 +0000951func (oFsm *uniPonAniConfigFsm) enterResettingTcont(ctx context.Context, e *fsm.Event) {
952 logger.Debugw(ctx, "uniPonAniConfigFsm - start resetting the TCont", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000953 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
954
955 oFsm.requestEventOffset = 1 //offset 1 for last remove activity
956 // this state entry is only expected in a suitable state (checked outside in onu_uni_tp)
957 meParams := me.ParamData{
958 EntityID: oFsm.tcont0ID,
959 Attributes: me.AttributeValueMap{
960 "AllocId": unusedTcontAllocID,
961 },
962 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000963 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300964 meInstance, err := oFsm.pOmciCC.sendSetTcontVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000965 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300966 if err != nil {
967 logger.Errorw(ctx, "TcontVar set failed, aborting uniPonAniConfigFsm!",
968 log.Fields{"device-id": oFsm.deviceID})
969 pConfigAniStateAFsm := oFsm.pAdaptFsm
970 if pConfigAniStateAFsm != nil {
971 oFsm.mutexPLastTxMeInstance.Unlock()
972 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
973 go func(aPAFsm *AdapterFsm) {
974 if aPAFsm != nil && aPAFsm.pFsm != nil {
975 _ = aPAFsm.pFsm.Event(aniEvReset)
976 }
977 }(pConfigAniStateAFsm)
978 return
979 }
980 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000981 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +0300982 oFsm.mutexPLastTxMeInstance.Unlock()
983
mpagenko8b07c1b2020-11-26 10:36:31 +0000984}
985
dbainbri4d3a0dc2020-12-02 00:33:42 +0000986func (oFsm *uniPonAniConfigFsm) enterRemoving1pMapper(ctx context.Context, e *fsm.Event) {
987 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the .1pMapper", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +0000988 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
989
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +0000990 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +0300991 meInstance, err := oFsm.pOmciCC.sendDeleteDot1PMapper(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +0000992 oFsm.pAdaptFsm.commChan, oFsm.mapperSP0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300993 if err != nil {
994 logger.Errorw(ctx, "Dot1Mapper delete failed, aborting uniPonAniConfigFsm!",
995 log.Fields{"device-id": oFsm.deviceID})
996 pConfigAniStateAFsm := oFsm.pAdaptFsm
997 if pConfigAniStateAFsm != nil {
998 oFsm.mutexPLastTxMeInstance.Unlock()
999 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1000 go func(aPAFsm *AdapterFsm) {
1001 if aPAFsm != nil && aPAFsm.pFsm != nil {
1002 _ = aPAFsm.pFsm.Event(aniEvReset)
1003 }
1004 }(pConfigAniStateAFsm)
1005 return
1006 }
1007 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001008 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001009 oFsm.mutexPLastTxMeInstance.Unlock()
1010
mpagenko8b07c1b2020-11-26 10:36:31 +00001011}
1012
dbainbri4d3a0dc2020-12-02 00:33:42 +00001013func (oFsm *uniPonAniConfigFsm) enterRemovingAniBPCD(ctx context.Context, e *fsm.Event) {
1014 logger.Debugw(ctx, "uniPonAniConfigFsm - start deleting the ANI MBCD", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001015 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1016
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001017 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001018 meInstance, err := oFsm.pOmciCC.sendDeleteMBPConfigData(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
mpagenko8b07c1b2020-11-26 10:36:31 +00001019 oFsm.pAdaptFsm.commChan, oFsm.macBPCD0ID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001020 if err != nil {
1021 logger.Errorw(ctx, "MBPConfigData delete failed, aborting uniPonAniConfigFsm!",
1022 log.Fields{"device-id": oFsm.deviceID})
1023 pConfigAniStateAFsm := oFsm.pAdaptFsm
1024 if pConfigAniStateAFsm != nil {
1025 oFsm.mutexPLastTxMeInstance.Unlock()
1026 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1027 go func(aPAFsm *AdapterFsm) {
1028 if aPAFsm != nil && aPAFsm.pFsm != nil {
1029 _ = aPAFsm.pFsm.Event(aniEvReset)
1030 }
1031 }(pConfigAniStateAFsm)
1032 return
1033 }
1034 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001035 oFsm.pLastTxMeInstance = meInstance
ozgecanetsiab36ed572021-04-01 10:38:48 +03001036 oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001037}
1038
dbainbri4d3a0dc2020-12-02 00:33:42 +00001039func (oFsm *uniPonAniConfigFsm) enterAniRemoveDone(ctx context.Context, e *fsm.Event) {
1040 logger.Debugw(ctx, "uniPonAniConfigFsm ani removal done", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001041 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
1042 //use DeviceHandler event notification directly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001043 oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
mpagenko8b07c1b2020-11-26 10:36:31 +00001044 if oFsm.chanSet {
1045 // indicate processing done to the caller
dbainbri4d3a0dc2020-12-02 00:33:42 +00001046 logger.Debugw(ctx, "uniPonAniConfigFsm processingDone on channel", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001047 "ProcessingStep": oFsm.procStep, "from_State": e.FSM.Current(), "device-id": oFsm.deviceID})
1048 oFsm.chSuccess <- oFsm.procStep
1049 oFsm.chanSet = false //reset the internal channel state
1050 }
1051
1052 //let's reset the state machine in order to release all resources now
1053 pConfigAniStateAFsm := oFsm.pAdaptFsm
1054 if pConfigAniStateAFsm != nil {
1055 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
1056 go func(aPAFsm *AdapterFsm) {
1057 if aPAFsm != nil && aPAFsm.pFsm != nil {
1058 _ = aPAFsm.pFsm.Event(aniEvReset)
1059 }
1060 }(pConfigAniStateAFsm)
1061 }
1062}
1063
dbainbri4d3a0dc2020-12-02 00:33:42 +00001064func (oFsm *uniPonAniConfigFsm) enterResettingState(ctx context.Context, e *fsm.Event) {
1065 logger.Debugw(ctx, "uniPonAniConfigFsm resetting", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001066 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001067
mpagenko3dbcdd22020-07-22 07:38:45 +00001068 pConfigAniStateAFsm := oFsm.pAdaptFsm
1069 if pConfigAniStateAFsm != nil {
1070 // abort running message processing
1071 fsmAbortMsg := Message{
1072 Type: TestMsg,
1073 Data: TestMessage{
1074 TestMessageVal: AbortMessageProcessing,
1075 },
1076 }
1077 pConfigAniStateAFsm.commChan <- fsmAbortMsg
1078
1079 //try to restart the FSM to 'disabled', decouple event transfer
Himani Chawla26e555c2020-08-31 12:30:20 +05301080 go func(aPAFsm *AdapterFsm) {
1081 if aPAFsm != nil && aPAFsm.pFsm != nil {
1082 _ = aPAFsm.pFsm.Event(aniEvRestart)
mpagenko3dbcdd22020-07-22 07:38:45 +00001083 }
1084 }(pConfigAniStateAFsm)
1085 }
1086}
1087
dbainbri4d3a0dc2020-12-02 00:33:42 +00001088func (oFsm *uniPonAniConfigFsm) enterDisabledState(ctx context.Context, e *fsm.Event) {
1089 logger.Debugw(ctx, "uniPonAniConfigFsm enters disabled state", log.Fields{
mpagenko8b07c1b2020-11-26 10:36:31 +00001090 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001091 oFsm.mutexPLastTxMeInstance.Lock()
1092 defer oFsm.mutexPLastTxMeInstance.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001093 oFsm.pLastTxMeInstance = nil
mpagenko1cc3cb42020-07-27 15:24:38 +00001094}
1095
dbainbri4d3a0dc2020-12-02 00:33:42 +00001096func (oFsm *uniPonAniConfigFsm) processOmciAniMessages(ctx context.Context) {
1097 logger.Debugw(ctx, "Start uniPonAniConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001098loop:
1099 for {
mpagenko3dbcdd22020-07-22 07:38:45 +00001100 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001101 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001102 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301103 message, ok := <-oFsm.pAdaptFsm.commChan
1104 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001105 logger.Info(ctx, "UniPonAniConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301106 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1107 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1108 break loop
1109 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001110 logger.Debugw(ctx, "UniPonAniConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301111
1112 switch message.Type {
1113 case TestMsg:
1114 msg, _ := message.Data.(TestMessage)
1115 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001116 logger.Infow(ctx, "UniPonAniConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001117 break loop
1118 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001119 logger.Warnw(ctx, "UniPonAniConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301120 case OMCI:
1121 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001122 oFsm.handleOmciAniConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301123 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001124 logger.Warn(ctx, "UniPonAniConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301125 "message.Type": message.Type})
1126 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001127
Himani Chawla4d908332020-08-31 12:30:20 +05301128 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001129 logger.Infow(ctx, "End uniPonAniConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301130}
1131
dbainbri4d3a0dc2020-12-02 00:33:42 +00001132func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigCreateResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301133 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
1134 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001135 logger.Errorw(ctx, "Omci Msg layer could not be detected 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 }
1139 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1140 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001141 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001142 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301143 return
1144 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001145 logger.Debugw(ctx, "CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkofc4f56e2020-11-04 17:17:49 +00001146 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
1147 //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 +00001148 oFsm.mutexPLastTxMeInstance.RLock()
1149 if oFsm.pLastTxMeInstance != nil {
1150 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1151 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1152 // maybe we can use just the same eventName for different state transitions like "forward"
1153 // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
1154 switch oFsm.pLastTxMeInstance.GetName() {
1155 case "Ieee8021PMapperServiceProfile":
1156 { // let the FSM proceed ...
1157 oFsm.mutexPLastTxMeInstance.RUnlock()
1158 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
1159 }
1160 case "MacBridgePortConfigurationData":
1161 { // let the FSM proceed ...
1162 oFsm.mutexPLastTxMeInstance.RUnlock()
1163 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
1164 }
1165 case "GemPortNetworkCtp", "GemInterworkingTerminationPoint", "MulticastGemInterworkingTerminationPoint":
1166 { // let aniConfig Multi-Id processing proceed by stopping the wait function
1167 oFsm.mutexPLastTxMeInstance.RUnlock()
1168 oFsm.omciMIdsResponseReceived <- true
1169 }
1170 default:
1171 {
1172 oFsm.mutexPLastTxMeInstance.RUnlock()
1173 logger.Warnw(ctx, "Unsupported ME name received!",
1174 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1175 }
mpagenkofc4f56e2020-11-04 17:17:49 +00001176 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001177 } else {
1178 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +00001179 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001180 } else {
1181 oFsm.mutexPLastTxMeInstance.RUnlock()
1182 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001183 }
1184 } else {
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001185 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?",
1186 log.Fields{"Error": msgObj.Result, "device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301187 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1188 return
1189 }
Himani Chawla4d908332020-08-31 12:30:20 +05301190}
1191
dbainbri4d3a0dc2020-12-02 00:33:42 +00001192func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(ctx context.Context, msg OmciMessage) {
Himani Chawla4d908332020-08-31 12:30:20 +05301193 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1194 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001195 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected 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 }
1199 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1200 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001201 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001202 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301203 return
1204 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001205 logger.Debugw(ctx, "UniPonAniConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
Himani Chawla4d908332020-08-31 12:30:20 +05301206 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001207 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001208 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
Himani Chawla4d908332020-08-31 12:30:20 +05301209 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1210 return
1211 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001212 oFsm.mutexPLastTxMeInstance.RLock()
1213 if oFsm.pLastTxMeInstance != nil {
1214 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1215 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1216 //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
1217 // if, then something like:
1218 //oFsm.pOnuDB.StoreMe(msgObj)
Himani Chawla4d908332020-08-31 12:30:20 +05301219
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001220 switch oFsm.pLastTxMeInstance.GetName() {
1221 case "TCont":
1222 { // let the FSM proceed ...
1223 oFsm.mutexPLastTxMeInstance.RUnlock()
1224 if oFsm.requestEventOffset == 0 { //from TCont config request
1225 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxTcontsResp)
1226 } else { // from T-Cont reset request
1227 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxResetTcontResp)
1228 }
1229 }
1230 case "PriorityQueue", "MulticastGemInterworkingTerminationPoint":
1231 { // let the PrioQueue init proceed by stopping the wait function
1232 oFsm.mutexPLastTxMeInstance.RUnlock()
1233 oFsm.omciMIdsResponseReceived <- true
1234 }
1235 case "Ieee8021PMapperServiceProfile":
1236 { // let the FSM proceed ...
1237 oFsm.mutexPLastTxMeInstance.RUnlock()
1238 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapSResp)
1239 }
1240 default:
1241 {
1242 oFsm.mutexPLastTxMeInstance.RUnlock()
1243 logger.Warnw(ctx, "Unsupported ME name received!",
1244 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001245 }
Himani Chawla4d908332020-08-31 12:30:20 +05301246 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001247 } else {
1248 oFsm.mutexPLastTxMeInstance.RUnlock()
Himani Chawla4d908332020-08-31 12:30:20 +05301249 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001250 } else {
1251 oFsm.mutexPLastTxMeInstance.RUnlock()
1252 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301253 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001254}
1255
dbainbri4d3a0dc2020-12-02 00:33:42 +00001256func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigDeleteResponseMessage(ctx context.Context, msg OmciMessage) {
mpagenko8b07c1b2020-11-26 10:36:31 +00001257 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
1258 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001259 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001260 log.Fields{"device-id": oFsm.deviceID})
1261 return
1262 }
1263 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1264 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001265 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko8b07c1b2020-11-26 10:36:31 +00001266 log.Fields{"device-id": oFsm.deviceID})
1267 return
1268 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001269 logger.Debugw(ctx, "UniPonAniConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko8b07c1b2020-11-26 10:36:31 +00001270 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001271 logger.Errorw(ctx, "UniPonAniConfigFsm - Omci DeleteResponse Error",
mpagenko8b07c1b2020-11-26 10:36:31 +00001272 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1273 //TODO: - later: possibly force FSM into abort or ignore some errors for some messages?
1274 // store error for mgmt display?
1275 return
1276 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001277 oFsm.mutexPLastTxMeInstance.RLock()
1278 if oFsm.pLastTxMeInstance != nil {
1279 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1280 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1281 //remove ME from DB //TODO??? obviously the Python code does not store/remove the config ...
1282 // if, then something like: oFsm.pOnuDB.XyyMe(msgObj)
mpagenko8b07c1b2020-11-26 10:36:31 +00001283
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001284 switch oFsm.pLastTxMeInstance.GetName() {
1285 case "GemInterworkingTerminationPoint":
1286 { // let the FSM proceed ...
1287 oFsm.mutexPLastTxMeInstance.RUnlock()
1288 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemiwResp)
1289 }
1290 case "GemPortNetworkCtp":
1291 { // let the FSM proceed ...
1292 oFsm.mutexPLastTxMeInstance.RUnlock()
1293 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemGemntpResp)
1294 }
1295 case "Ieee8021PMapperServiceProfile":
1296 { // let the FSM proceed ...
1297 oFsm.mutexPLastTxMeInstance.RUnlock()
1298 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRem1pMapperResp)
1299 }
1300 case "MacBridgePortConfigurationData":
1301 { // this is the last event of the T-Cont cleanup procedure, FSM may be reset here
1302 oFsm.mutexPLastTxMeInstance.RUnlock()
1303 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxRemAniBPCDResp)
1304 }
1305 default:
1306 {
1307 oFsm.mutexPLastTxMeInstance.RUnlock()
1308 logger.Warnw(ctx, "Unsupported ME name received!",
1309 log.Fields{"ME name": oFsm.pLastTxMeInstance.GetName(), "device-id": oFsm.deviceID})
1310 }
mpagenko8b07c1b2020-11-26 10:36:31 +00001311 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001312 } else {
1313 oFsm.mutexPLastTxMeInstance.RUnlock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001314 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001315 } else {
1316 oFsm.mutexPLastTxMeInstance.RUnlock()
1317 logger.Warnw(ctx, "Pointer to last Tx MeInstance is nil!", log.Fields{"device-id": oFsm.deviceID})
mpagenko8b07c1b2020-11-26 10:36:31 +00001318 }
1319}
1320
dbainbri4d3a0dc2020-12-02 00:33:42 +00001321func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigMessage(ctx context.Context, msg OmciMessage) {
1322 logger.Debugw(ctx, "Rx OMCI UniPonAniConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenko3dbcdd22020-07-22 07:38:45 +00001323 "msgType": msg.OmciMsg.MessageType})
1324
1325 switch msg.OmciMsg.MessageType {
1326 case omci.CreateResponseType:
1327 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001328 oFsm.handleOmciAniConfigCreateResponseMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301329
mpagenko3dbcdd22020-07-22 07:38:45 +00001330 } //CreateResponseType
1331 case omci.SetResponseType:
1332 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001333 oFsm.handleOmciAniConfigSetResponseMessage(ctx, msg)
mpagenko3dbcdd22020-07-22 07:38:45 +00001334
mpagenko3dbcdd22020-07-22 07:38:45 +00001335 } //SetResponseType
mpagenko8b07c1b2020-11-26 10:36:31 +00001336 case omci.DeleteResponseType:
1337 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001338 oFsm.handleOmciAniConfigDeleteResponseMessage(ctx, msg)
mpagenko8b07c1b2020-11-26 10:36:31 +00001339
1340 } //SetResponseType
mpagenko3dbcdd22020-07-22 07:38:45 +00001341 default:
1342 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001343 logger.Errorw(ctx, "uniPonAniConfigFsm - Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001344 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001345 return
1346 }
1347 }
1348}
1349
dbainbri4d3a0dc2020-12-02 00:33:42 +00001350func (oFsm *uniPonAniConfigFsm) performCreatingGemNCTPs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001351 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1352 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001353 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemNWCtp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001354 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1355 "TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001356 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001357 meParams := me.ParamData{
1358 EntityID: gemPortAttribs.gemPortID, //unique, same as PortId
1359 Attributes: me.AttributeValueMap{
1360 "PortId": gemPortAttribs.gemPortID,
1361 "TContPointer": oFsm.tcont0ID,
1362 "Direction": gemPortAttribs.direction,
1363 //ONU-G.TrafficManagementOption dependency ->PrioQueue or TCont
1364 // TODO!! verify dependency and QueueId in case of Multi-GemPort setup!
1365 "TrafficManagementPointerForUpstream": gemPortAttribs.upQueueID, //might be different in wrr-only Setup - tcont0ID
1366 "PriorityQueuePointerForDownStream": gemPortAttribs.downQueueID,
1367 },
1368 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001369 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001370 meInstance, err := oFsm.pOmciCC.sendCreateGemNCTPVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001371 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001372 if err != nil {
1373 oFsm.mutexPLastTxMeInstance.Unlock()
1374 logger.Errorw(ctx, "GemNCTPVar create failed, aborting uniPonAniConfigFsm!",
1375 log.Fields{"device-id": oFsm.deviceID})
1376 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1377 return
1378 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001379 //accept also nil as (error) return value for writing to LastTx
1380 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001381 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001382 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001383 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001384 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001385 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001386 logger.Errorw(ctx, "GemNWCtp create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001387 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301388 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001389 return
1390 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001391 // Mark the gem port to be removed for Performance History monitoring
1392 if oFsm.pDeviceHandler.pOnuMetricsMgr != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07001393 oFsm.pDeviceHandler.pOnuMetricsMgr.AddGemPortForPerfMonitoring(ctx, gemPortAttribs.gemPortID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001394 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001395 } //for all GemPorts of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001396
1397 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001398 logger.Debugw(ctx, "GemNWCtp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301399 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemntcpsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001400}
1401
dbainbri4d3a0dc2020-12-02 00:33:42 +00001402func (oFsm *uniPonAniConfigFsm) performCreatingGemIWs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001403 // for all GemPorts of this T-Cont as given by the size of set gemPortAttribsSlice
1404 for gemIndex, gemPortAttribs := range oFsm.gemPortAttribsSlice {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001405 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Create::GemIwTp", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001406 "EntitytId": strconv.FormatInt(int64(gemPortAttribs.gemPortID), 16),
1407 "SPPtr": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001408 "device-id": oFsm.deviceID})
mpagenko3dbcdd22020-07-22 07:38:45 +00001409
ozgecanetsia4b232302020-11-11 10:58:10 +03001410 //TODO if the port has only downstream direction the isMulticast flag can be removed.
1411 if gemPortAttribs.isMulticast {
ozgecanetsia4b232302020-11-11 10:58:10 +03001412
1413 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001414 EntityID: gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001415 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001416 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.multicastGemID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001417 "InterworkingOption": 0, // Don't Care
1418 "ServiceProfilePointer": 0, // Don't Care
1419 "GalProfilePointer": galEthernetEID,
ozgecanetsia4b232302020-11-11 10:58:10 +03001420 },
1421 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001422 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001423 meInstance, err := oFsm.pOmciCC.sendCreateMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsia4b232302020-11-11 10:58:10 +03001424 true, oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001425 if err != nil {
1426 oFsm.mutexPLastTxMeInstance.Unlock()
1427 logger.Errorw(ctx, "MulticastGemIWTPVar create failed, aborting uniPonAniConfigFsm!",
1428 log.Fields{"device-id": oFsm.deviceID})
1429 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1430 return
1431
1432 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001433 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001434 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001435 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001436 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001437 if err != nil {
ozgecanetsiab36ed572021-04-01 10:38:48 +03001438 logger.Errorw(ctx, "MulticastGemIWTP create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001439 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
1440 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1441 return
1442 }
1443 ipv4MulticastTable := make([]uint8, 12)
1444 //Gem Port ID
1445 binary.BigEndian.PutUint16(ipv4MulticastTable[0:], gemPortAttribs.multicastGemID)
1446 //Secondary Key
1447 binary.BigEndian.PutUint16(ipv4MulticastTable[2:], 0)
1448 // Multicast IP range start This is the 224.0.0.1 address
1449 binary.BigEndian.PutUint32(ipv4MulticastTable[4:], IPToInt32(net.IPv4(224, 0, 0, 0)))
1450 // MulticastIp range stop
1451 binary.BigEndian.PutUint32(ipv4MulticastTable[8:], IPToInt32(net.IPv4(239, 255, 255, 255)))
1452
1453 meIPV4MCTableParams := me.ParamData{
1454 EntityID: gemPortAttribs.multicastGemID,
1455 Attributes: me.AttributeValueMap{
1456 "Ipv4MulticastAddressTable": ipv4MulticastTable,
1457 },
1458 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001459 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001460 meIPV4MCTableInstance, err := oFsm.pOmciCC.sendSetMulticastGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001461 true, oFsm.pAdaptFsm.commChan, meIPV4MCTableParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001462 if err != nil {
1463 oFsm.mutexPLastTxMeInstance.Unlock()
1464 logger.Errorw(ctx, "MulticastGemIWTPVar set failed, aborting uniPonAniConfigFsm!",
1465 log.Fields{"device-id": oFsm.deviceID})
1466 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1467 return
1468 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001469 oFsm.pLastTxMeInstance = meIPV4MCTableInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001470 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001471
1472 } else {
1473 meParams := me.ParamData{
1474 EntityID: gemPortAttribs.gemPortID,
1475 Attributes: me.AttributeValueMap{
1476 "GemPortNetworkCtpConnectivityPointer": gemPortAttribs.gemPortID, //same as EntityID, see above
1477 "InterworkingOption": 5, //fixed model:: G.998 .1pMapper
1478 "ServiceProfilePointer": oFsm.mapperSP0ID,
1479 "InterworkingTerminationPointPointer": 0, //not used with .1PMapper Mac bridge
1480 "GalProfilePointer": galEthernetEID,
1481 },
1482 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001483 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001484 meInstance, err := oFsm.pOmciCC.sendCreateGemIWTPVar(context.TODO(), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
ozgecanetsia4b232302020-11-11 10:58:10 +03001485 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001486 if err != nil {
1487 oFsm.mutexPLastTxMeInstance.Unlock()
1488 logger.Errorw(ctx, "GEMIWTPVar create failed, aborting uniPonAniConfigFsm!",
1489 log.Fields{"device-id": oFsm.deviceID})
1490 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1491 return
1492 }
ozgecanetsia4b232302020-11-11 10:58:10 +03001493 //accept also nil as (error) return value for writing to LastTx
1494 // - this avoids misinterpretation of new received OMCI messages
1495 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001496 oFsm.mutexPLastTxMeInstance.Unlock()
ozgecanetsia4b232302020-11-11 10:58:10 +03001497 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001498 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001499 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001500 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001501 logger.Errorw(ctx, "GemTP create failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001502 log.Fields{"device-id": oFsm.deviceID, "GemIndex": gemIndex})
Himani Chawla4d908332020-08-31 12:30:20 +05301503 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001504 return
1505 }
1506 } //for all GemPort's of this T-Cont
mpagenko3dbcdd22020-07-22 07:38:45 +00001507
1508 // if Config has been done for all GemPort instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001509 logger.Debugw(ctx, "GemIwTp create loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301510 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxGemiwsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001511}
1512
dbainbri4d3a0dc2020-12-02 00:33:42 +00001513func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001514 const cu16StrictPrioWeight uint16 = 0xFFFF
1515 //find all upstream PrioQueues related to this T-Cont
1516 loQueueMap := ordered_map.NewOrderedMap()
1517 for _, gemPortAttribs := range oFsm.gemPortAttribsSlice {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001518 if gemPortAttribs.isMulticast {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001519 logger.Debugw(ctx, "uniPonAniConfigFsm Port is Multicast, ignoring PQs", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001520 "device-id": oFsm.deviceID, "GemPort": gemPortAttribs.gemPortID,
1521 "prioString": gemPortAttribs.pbitString})
1522 continue
1523 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001524 if gemPortAttribs.qosPolicy == "WRR" {
Himani Chawla4d908332020-08-31 12:30:20 +05301525 if _, ok := loQueueMap.Get(gemPortAttribs.upQueueID); !ok {
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001526 //key does not yet exist
1527 loQueueMap.Set(gemPortAttribs.upQueueID, uint16(gemPortAttribs.weight))
1528 }
1529 } else {
1530 loQueueMap.Set(gemPortAttribs.upQueueID, cu16StrictPrioWeight) //use invalid weight value to indicate SP
1531 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001532 }
mpagenko3dbcdd22020-07-22 07:38:45 +00001533
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001534 //TODO: assumption here is that ONU data uses SP setting in the T-Cont and WRR in the TrafficScheduler
1535 // if that is not the case, the reverse case could be checked and reacted accordingly or if the
1536 // complete chain is not valid, then some error should be thrown and configuration can be aborted
1537 // or even be finished without correct SP/WRR setting
1538
1539 //TODO: search for the (WRR)trafficScheduler related to the T-Cont of this queue
1540 //By now assume fixed value 0x8000, which is the only announce BBSIM TrafficScheduler,
1541 // even though its T-Cont seems to be wrong ...
1542 loTrafficSchedulerEID := 0x8000
1543 //for all found queues
1544 iter := loQueueMap.IterFunc()
1545 for kv, ok := iter(); ok; kv, ok = iter() {
1546 queueIndex := (kv.Key).(uint16)
1547 meParams := me.ParamData{
1548 EntityID: queueIndex,
Himani Chawla4d908332020-08-31 12:30:20 +05301549 Attributes: make(me.AttributeValueMap),
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001550 }
1551 if (kv.Value).(uint16) == cu16StrictPrioWeight {
1552 //StrictPrio indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001553 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to StrictPrio", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001554 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001555 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001556 meParams.Attributes["TrafficSchedulerPointer"] = 0 //ensure T-Cont defined StrictPrio scheduling
1557 } else {
1558 //WRR indication
dbainbri4d3a0dc2020-12-02 00:33:42 +00001559 logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::PrioQueue to WRR", log.Fields{
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001560 "EntitytId": strconv.FormatInt(int64(queueIndex), 16),
1561 "Weight": kv.Value,
mpagenko01e726e2020-10-23 09:45:29 +00001562 "device-id": oFsm.deviceID})
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001563 meParams.Attributes["TrafficSchedulerPointer"] = loTrafficSchedulerEID //ensure assignment of the relevant trafficScheduler
1564 meParams.Attributes["Weight"] = uint8(kv.Value.(uint16))
1565 }
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001566 oFsm.mutexPLastTxMeInstance.Lock()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001567 meInstance, err := oFsm.pOmciCC.sendSetPrioQueueVar(log.WithSpanFromContext(context.TODO(), ctx), oFsm.pDeviceHandler.pOpenOnuAc.omciTimeout, true,
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001568 oFsm.pAdaptFsm.commChan, meParams)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001569 if err != nil {
1570 oFsm.mutexPLastTxMeInstance.Unlock()
1571 logger.Errorw(ctx, "PrioQueueVar set failed, aborting uniPonAniConfigFsm!",
1572 log.Fields{"device-id": oFsm.deviceID})
1573 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
1574 return
1575 }
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001576 //accept also nil as (error) return value for writing to LastTx
1577 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001578 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt9902b2b2021-04-21 14:52:32 +00001579 oFsm.mutexPLastTxMeInstance.Unlock()
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001580
1581 //verify response
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 err = oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001583 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001584 logger.Errorw(ctx, "PrioQueue set failed, aborting AniConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001585 log.Fields{"device-id": oFsm.deviceID, "QueueId": strconv.FormatInt(int64(queueIndex), 16)})
Himani Chawla4d908332020-08-31 12:30:20 +05301586 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvReset)
Holger Hildebrandt9ca8b132020-08-07 14:45:03 +00001587 return
1588 }
1589
1590 //TODO: In case of WRR setting of the GemPort/PrioQueue it might further be necessary to
1591 // write the assigned trafficScheduler with the requested Prio to be considered in the StrictPrio scheduling
1592 // of the (next upstream) assigned T-Cont, which is f(prioQueue[priority]) - in relation to other SP prioQueues
1593 // not yet done because of BBSIM TrafficScheduler issues (and not done in py code as well)
1594
1595 } //for all upstream prioQueues
mpagenko3dbcdd22020-07-22 07:38:45 +00001596
1597 // if Config has been done for all PrioQueue instances let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001598 logger.Debugw(ctx, "PrioQueue set loop finished", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301599 _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxPrioqsResp)
mpagenko3dbcdd22020-07-22 07:38:45 +00001600}
1601
dbainbri4d3a0dc2020-12-02 00:33:42 +00001602func (oFsm *uniPonAniConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenko7d6bb022021-03-11 15:07:55 +00001603 oFsm.mutexIsAwaitingResponse.Lock()
mpagenkocf48e452021-04-23 09:23:00 +00001604 if oFsm.isCanceled {
1605 // FSM already canceled before entering wait
1606 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted (on enter)", log.Fields{"for device-id": oFsm.deviceID})
1607 oFsm.mutexIsAwaitingResponse.Unlock()
1608 return fmt.Errorf(cErrWaitAborted)
1609 }
mpagenko7d6bb022021-03-11 15:07:55 +00001610 oFsm.isAwaitingResponse = true
1611 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001612 select {
Himani Chawla4d908332020-08-31 12:30:20 +05301613 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenko3dbcdd22020-07-22 07:38:45 +00001614 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001615 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
Holger Hildebrandt366ef192021-05-05 11:07:44 +00001616 case <-time.After(oFsm.pOmciCC.GetMaxOmciTimeoutWithRetries() * time.Second): //3s was detected to be to less in 8*8 bbsim test with debug Info/Debug
dbainbri4d3a0dc2020-12-02 00:33:42 +00001617 logger.Warnw(ctx, "UniPonAniConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001618 oFsm.mutexIsAwaitingResponse.Lock()
1619 oFsm.isAwaitingResponse = false
1620 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001621 return fmt.Errorf("uniPonAniConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenko3dbcdd22020-07-22 07:38:45 +00001622 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301623 if success {
mpagenkocf48e452021-04-23 09:23:00 +00001624 logger.Debugw(ctx, "uniPonAniConfigFsm multi entity response received", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001625 oFsm.mutexIsAwaitingResponse.Lock()
1626 oFsm.isAwaitingResponse = false
1627 oFsm.mutexIsAwaitingResponse.Unlock()
mpagenko3dbcdd22020-07-22 07:38:45 +00001628 return nil
1629 }
mpagenko7d6bb022021-03-11 15:07:55 +00001630 // waiting was aborted (probably on external request)
mpagenkocf48e452021-04-23 09:23:00 +00001631 logger.Debugw(ctx, "uniPonAniConfigFsm wait-for-multi-entity-response aborted", log.Fields{"for device-id": oFsm.deviceID})
mpagenko7d6bb022021-03-11 15:07:55 +00001632 oFsm.mutexIsAwaitingResponse.Lock()
1633 oFsm.isAwaitingResponse = false
1634 oFsm.mutexIsAwaitingResponse.Unlock()
1635 return fmt.Errorf(cErrWaitAborted)
mpagenko3dbcdd22020-07-22 07:38:45 +00001636 }
1637}