blob: a53b115bbae7fc0c27d1626938116a16d5f039b8 [file] [log] [blame]
mpagenkodff5dda2020-08-28 11:52:01 +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"
22 "encoding/binary"
Andrea Campanella6515c582020-10-05 11:25:00 +020023 "fmt"
ozgecanetsiab5000ef2020-11-27 14:38:20 +030024 "net"
mpagenkodff5dda2020-08-28 11:52:01 +000025 "strconv"
Holger Hildebrandt394c5522020-09-11 11:23:01 +000026 "sync"
mpagenkodff5dda2020-08-28 11:52:01 +000027 "time"
28
mpagenko01e726e2020-10-23 09:45:29 +000029 gp "github.com/google/gopacket"
mpagenkodff5dda2020-08-28 11:52:01 +000030 "github.com/looplab/fsm"
31 "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 of "github.com/opencord/voltha-protos/v4/go/openflow_13"
mpagenkodff5dda2020-08-28 11:52:01 +000035)
36
37const (
38 // internal predefined values
mpagenkof1fc3862021-02-16 10:09:52 +000039 cWaitForCookieDeletion = 3 //seconds
mpagenkodff5dda2020-08-28 11:52:01 +000040 cDefaultDownstreamMode = 0
41 cDefaultTpid = 0x8100
mpagenko01e726e2020-10-23 09:45:29 +000042 cVtfdTableSize = 12 //as per G.988
43 cMaxAllowedFlows = cVtfdTableSize //which might be under discussion, for the moment connected to limit of VLAN's within VTFD
mpagenkodff5dda2020-08-28 11:52:01 +000044)
45
46const (
mpagenkof1fc3862021-02-16 10:09:52 +000047 // internal offsets for requestEvent according to definition in onu_device_entry::OnuDeviceEvent
48 cDeviceEventOffsetAddWithKvStore = 0 //OmciVlanFilterAddDone - OmciVlanFilterAddDone cannot use because of lint
49 cDeviceEventOffsetAddNoKvStore = OmciVlanFilterAddDoneNoKvStore - OmciVlanFilterAddDone
50 cDeviceEventOffsetRemoveWithKvStore = OmciVlanFilterRemDone - OmciVlanFilterAddDone
51 cDeviceEventOffsetRemoveNoKvStore = OmciVlanFilterRemDoneNoKvStore - OmciVlanFilterAddDone
52)
53
54const (
mpagenkodff5dda2020-08-28 11:52:01 +000055 // bit mask offsets for EVTOCD VlanTaggingOperationTable related to 32 bits (4 bytes)
56 cFilterPrioOffset = 28
57 cFilterVidOffset = 15
58 cFilterTpidOffset = 12
59 cFilterEtherTypeOffset = 0
60 cTreatTTROffset = 30
61 cTreatPrioOffset = 16
62 cTreatVidOffset = 3
63 cTreatTpidOffset = 0
64)
65const (
66 // byte offsets for EVTOCD VlanTaggingOperationTable related to overall 16 byte size with slice byte 0 as first Byte (MSB)
67 cFilterOuterOffset = 0
68 cFilterInnerOffset = 4
69 cTreatOuterOffset = 8
70 cTreatInnerOffset = 12
71)
72const (
73 // basic values used within EVTOCD VlanTaggingOperationTable in respect to their bitfields
74 cPrioIgnoreTag uint32 = 15
75 cPrioDefaultFilter uint32 = 14
76 cPrioDoNotFilter uint32 = 8
77 cDoNotFilterVid uint32 = 4096
78 cDoNotFilterTPID uint32 = 0
79 cDoNotFilterEtherType uint32 = 0
80 cDoNotAddPrio uint32 = 15
81 cCopyPrioFromInner uint32 = 8
Himani Chawla4d908332020-08-31 12:30:20 +053082 //cDontCarePrio uint32 = 0
mpagenkodff5dda2020-08-28 11:52:01 +000083 cDontCareVid uint32 = 0
84 cDontCareTpid uint32 = 0
85 cSetOutputTpidCopyDei uint32 = 4
86)
87
88const (
Holger Hildebrandt10d98192021-01-27 15:29:31 +000089 // events of config UNI port VLAN FSM
mpagenko535d6ef2021-02-26 13:15:34 +000090 vlanEvStart = "vlanEvStart"
91 vlanEvWaitTechProf = "vlanEvWaitTechProf"
92 vlanEvCancelOutstandingConfig = "vlanEvCancelOutstandingConfig"
93 vlanEvContinueConfig = "vlanEvContinueConfig"
94 vlanEvStartConfig = "vlanEvStartConfig"
95 vlanEvRxConfigVtfd = "vlanEvRxConfigVtfd"
96 vlanEvRxConfigEvtocd = "vlanEvRxConfigEvtocd"
97 vlanEvWaitTPIncr = "vlanEvWaitTPIncr"
98 vlanEvIncrFlowConfig = "vlanEvIncrFlowConfig"
99 vlanEvRenew = "vlanEvRenew"
100 vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
101 vlanEvRemFlowDone = "vlanEvRemFlowDone"
102 vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000103 //vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
104 //vlanEvTimeoutMids = "vlanEvTimeoutMids"
Himani Chawla4d908332020-08-31 12:30:20 +0530105 vlanEvReset = "vlanEvReset"
106 vlanEvRestart = "vlanEvRestart"
mpagenkodff5dda2020-08-28 11:52:01 +0000107)
mpagenko01e726e2020-10-23 09:45:29 +0000108
mpagenkodff5dda2020-08-28 11:52:01 +0000109const (
Holger Hildebrandt10d98192021-01-27 15:29:31 +0000110 // states of config UNI port VLAN FSM
mpagenkodff5dda2020-08-28 11:52:01 +0000111 vlanStDisabled = "vlanStDisabled"
112 vlanStStarting = "vlanStStarting"
113 vlanStWaitingTechProf = "vlanStWaitingTechProf"
114 vlanStConfigVtfd = "vlanStConfigVtfd"
115 vlanStConfigEvtocd = "vlanStConfigEvtocd"
116 vlanStConfigDone = "vlanStConfigDone"
mpagenko551a4d42020-12-08 18:09:20 +0000117 vlanStIncrFlowWaitTP = "vlanStIncrFlowWaitTP"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000118 vlanStConfigIncrFlow = "vlanStConfigIncrFlow"
mpagenko01e726e2020-10-23 09:45:29 +0000119 vlanStRemoveFlow = "vlanStRemoveFlow"
mpagenkodff5dda2020-08-28 11:52:01 +0000120 vlanStCleanupDone = "vlanStCleanupDone"
121 vlanStResetting = "vlanStResetting"
122)
mpagenkof1fc3862021-02-16 10:09:52 +0000123const cVlanFsmIdleState = vlanStConfigDone // state where no OMCI activity is done (for a longer time)
124const cVlanFsmConfiguredState = vlanStConfigDone // state that indicates that at least some valid user related VLAN configuration should exist
mpagenkodff5dda2020-08-28 11:52:01 +0000125
mpagenko01e726e2020-10-23 09:45:29 +0000126type uniVlanRuleParams struct {
mpagenko551a4d42020-12-08 18:09:20 +0000127 TpID uint8 `json:"tp_id"`
mpagenko01e726e2020-10-23 09:45:29 +0000128 MatchVid uint32 `json:"match_vid"` //use uint32 types for allowing immediate bitshifting
129 MatchPcp uint32 `json:"match_pcp"`
130 TagsToRemove uint32 `json:"tags_to_remove"`
131 SetVid uint32 `json:"set_vid"`
132 SetPcp uint32 `json:"set_pcp"`
133}
134
135type uniVlanFlowParams struct {
136 CookieSlice []uint64 `json:"cookie_slice"`
137 VlanRuleParams uniVlanRuleParams `json:"vlan_rule_params"`
138}
139
140type uniRemoveVlanFlowParams struct {
141 cookie uint64 //just the last cookie valid for removal
142 vlanRuleParams uniVlanRuleParams
143}
144
mpagenkodff5dda2020-08-28 11:52:01 +0000145//UniVlanConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
146type UniVlanConfigFsm struct {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530147 pDeviceHandler *deviceHandler
mpagenko01e726e2020-10-23 09:45:29 +0000148 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530149 pOmciCC *omciCC
150 pOnuUniPort *onuUniPort
151 pUniTechProf *onuUniTechProf
152 pOnuDB *onuDeviceDB
mpagenkodff5dda2020-08-28 11:52:01 +0000153 requestEvent OnuDeviceEvent
154 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
155 pAdaptFsm *AdapterFsm
156 acceptIncrementalEvtoOption bool
mpagenko2418ab02020-11-12 12:58:06 +0000157 clearPersistency bool
mpagenko551a4d42020-12-08 18:09:20 +0000158 mutexFlowParams sync.RWMutex
mpagenkof1fc3862021-02-16 10:09:52 +0000159 chCookieDeleted chan bool //channel to indicate that a specificly indicated cookie was deleted
mpagenko9a304ea2020-12-16 15:54:01 +0000160 actualUniVlanConfigRule uniVlanRuleParams
mpagenko01e726e2020-10-23 09:45:29 +0000161 uniVlanFlowParamsSlice []uniVlanFlowParams
162 uniRemoveFlowsSlice []uniRemoveVlanFlowParams
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000163 numUniFlows uint8 // expected number of flows should be less than 12
164 configuredUniFlow uint8
mpagenko01e726e2020-10-23 09:45:29 +0000165 numRemoveFlows uint8
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000166 numVlanFilterEntries uint8
mpagenko01e726e2020-10-23 09:45:29 +0000167 vlanFilterList [cVtfdTableSize]uint16
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000168 evtocdID uint16
mpagenko01e726e2020-10-23 09:45:29 +0000169 pLastTxMeInstance *me.ManagedEntity
mpagenkofc4f56e2020-11-04 17:17:49 +0000170 requestEventOffset uint8
mpagenko551a4d42020-12-08 18:09:20 +0000171 TpIDWaitingFor uint8
mpagenkof1fc3862021-02-16 10:09:52 +0000172 //cookie value that indicates that a rule to add is delayed by waiting for deletion of some other existing rule with the same cookie
173 delayNewRuleCookie uint64
mpagenkodff5dda2020-08-28 11:52:01 +0000174}
175
mpagenko01e726e2020-10-23 09:45:29 +0000176//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
177// of ONU UNI ports via OMCI
dbainbri4d3a0dc2020-12-02 00:33:42 +0000178func NewUniVlanConfigFsm(ctx context.Context, apDeviceHandler *deviceHandler, apDevOmciCC *omciCC, apUniPort *onuUniPort,
mpagenko551a4d42020-12-08 18:09:20 +0000179 apUniTechProf *onuUniTechProf, apOnuDB *onuDeviceDB, aTechProfileID uint8,
mpagenko01e726e2020-10-23 09:45:29 +0000180 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message, aAcceptIncrementalEvto bool,
181 aCookieSlice []uint64, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) *UniVlanConfigFsm {
mpagenkodff5dda2020-08-28 11:52:01 +0000182 instFsm := &UniVlanConfigFsm{
183 pDeviceHandler: apDeviceHandler,
mpagenko01e726e2020-10-23 09:45:29 +0000184 deviceID: apDeviceHandler.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000185 pOmciCC: apDevOmciCC,
186 pOnuUniPort: apUniPort,
187 pUniTechProf: apUniTechProf,
188 pOnuDB: apOnuDB,
mpagenkodff5dda2020-08-28 11:52:01 +0000189 requestEvent: aRequestEvent,
190 acceptIncrementalEvtoOption: aAcceptIncrementalEvto,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000191 numUniFlows: 0,
192 configuredUniFlow: 0,
mpagenko01e726e2020-10-23 09:45:29 +0000193 numRemoveFlows: 0,
mpagenko2418ab02020-11-12 12:58:06 +0000194 clearPersistency: true,
mpagenkodff5dda2020-08-28 11:52:01 +0000195 }
196
mpagenko01e726e2020-10-23 09:45:29 +0000197 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenkodff5dda2020-08-28 11:52:01 +0000198 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000199 logger.Errorw(ctx, "UniVlanConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000200 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000201 return nil
202 }
mpagenkodff5dda2020-08-28 11:52:01 +0000203 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
204 vlanStDisabled,
205 fsm.Events{
206 {Name: vlanEvStart, Src: []string{vlanStDisabled}, Dst: vlanStStarting},
207 {Name: vlanEvWaitTechProf, Src: []string{vlanStStarting}, Dst: vlanStWaitingTechProf},
mpagenko535d6ef2021-02-26 13:15:34 +0000208 {Name: vlanEvCancelOutstandingConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000209 {Name: vlanEvContinueConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigVtfd},
210 {Name: vlanEvStartConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigVtfd},
211 {Name: vlanEvRxConfigVtfd, Src: []string{vlanStConfigVtfd}, Dst: vlanStConfigEvtocd},
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000212 {Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
213 Dst: vlanStConfigDone},
mpagenko551a4d42020-12-08 18:09:20 +0000214 {Name: vlanEvRenew, Src: []string{vlanStConfigDone}, Dst: vlanStStarting},
215 {Name: vlanEvWaitTPIncr, Src: []string{vlanStConfigDone}, Dst: vlanStIncrFlowWaitTP},
216 {Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone, vlanStIncrFlowWaitTP},
217 Dst: vlanStConfigIncrFlow},
mpagenko01e726e2020-10-23 09:45:29 +0000218 {Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
219 {Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
220 {Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000221 /*
222 {Name: vlanEvTimeoutSimple, Src: []string{
223 vlanStCreatingDot1PMapper, vlanStCreatingMBPCD, vlanStSettingTconts, vlanStSettingDot1PMapper}, Dst: vlanStStarting},
224 {Name: vlanEvTimeoutMids, Src: []string{
225 vlanStCreatingGemNCTPs, vlanStCreatingGemIWs, vlanStSettingPQs}, Dst: vlanStStarting},
226 */
227 // exceptional treatment for all states except vlanStResetting
228 {Name: vlanEvReset, Src: []string{vlanStStarting, vlanStWaitingTechProf,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000229 vlanStConfigVtfd, vlanStConfigEvtocd, vlanStConfigDone, vlanStConfigIncrFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000230 vlanStRemoveFlow, vlanStCleanupDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000231 Dst: vlanStResetting},
232 // the only way to get to resource-cleared disabled state again is via "resseting"
233 {Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
234 },
mpagenkodff5dda2020-08-28 11:52:01 +0000235 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000236 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
237 "enter_" + vlanStStarting: func(e *fsm.Event) { instFsm.enterConfigStarting(ctx, e) },
238 "enter_" + vlanStConfigVtfd: func(e *fsm.Event) { instFsm.enterConfigVtfd(ctx, e) },
239 "enter_" + vlanStConfigEvtocd: func(e *fsm.Event) { instFsm.enterConfigEvtocd(ctx, e) },
240 "enter_" + vlanStConfigDone: func(e *fsm.Event) { instFsm.enterVlanConfigDone(ctx, e) },
241 "enter_" + vlanStConfigIncrFlow: func(e *fsm.Event) { instFsm.enterConfigIncrFlow(ctx, e) },
242 "enter_" + vlanStRemoveFlow: func(e *fsm.Event) { instFsm.enterRemoveFlow(ctx, e) },
243 "enter_" + vlanStCleanupDone: func(e *fsm.Event) { instFsm.enterVlanCleanupDone(ctx, e) },
244 "enter_" + vlanStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
245 "enter_" + vlanStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
mpagenkodff5dda2020-08-28 11:52:01 +0000246 },
247 )
248 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000249 logger.Errorw(ctx, "UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000250 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000251 return nil
252 }
253
dbainbri4d3a0dc2020-12-02 00:33:42 +0000254 _ = instFsm.initUniFlowParams(ctx, aTechProfileID, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000255
dbainbri4d3a0dc2020-12-02 00:33:42 +0000256 logger.Debugw(ctx, "UniVlanConfigFsm created", log.Fields{"device-id": instFsm.deviceID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000257 "accIncrEvto": instFsm.acceptIncrementalEvtoOption})
mpagenkodff5dda2020-08-28 11:52:01 +0000258 return instFsm
259}
260
mpagenko01e726e2020-10-23 09:45:29 +0000261//initUniFlowParams is a simplified form of SetUniFlowParams() used for first flow parameters configuration
mpagenko551a4d42020-12-08 18:09:20 +0000262func (oFsm *UniVlanConfigFsm) initUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000263 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
264 loRuleParams := uniVlanRuleParams{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000265 TpID: aTpID,
266 MatchVid: uint32(aMatchVlan),
267 SetVid: uint32(aSetVlan),
268 SetPcp: uint32(aSetPcp),
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000269 }
270 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
mpagenko01e726e2020-10-23 09:45:29 +0000271 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
272 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000273
mpagenko01e726e2020-10-23 09:45:29 +0000274 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000275 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000276 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000277 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
278 } else {
279 if !oFsm.acceptIncrementalEvtoOption {
280 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000281 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000282 }
283 }
284
mpagenko01e726e2020-10-23 09:45:29 +0000285 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000286 // no prio/vid filtering requested
mpagenko01e726e2020-10-23 09:45:29 +0000287 loRuleParams.TagsToRemove = 0 //no tag pop action
288 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
289 if loRuleParams.SetPcp == cCopyPrioFromInner {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000290 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
291 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
292 // might collide with NoMatchVid/CopyPrio(/setVid) setting
293 // this was some precondition setting taken over from py adapter ..
mpagenko01e726e2020-10-23 09:45:29 +0000294 loRuleParams.SetPcp = 0
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000295 }
296 }
mpagenko01e726e2020-10-23 09:45:29 +0000297
298 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
299 loFlowParams.CookieSlice = make([]uint64, 0)
300 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
301
302 //no mutex protection is required for initial access and adding the first flow is always possible
303 oFsm.uniVlanFlowParamsSlice = make([]uniVlanFlowParams, 0)
304 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000305 logger.Debugw(ctx, "first UniVlanConfigFsm flow added", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000306 "Cookies": oFsm.uniVlanFlowParamsSlice[0].CookieSlice,
307 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
308 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
309 "SetPcp": loRuleParams.SetPcp,
310 "device-id": oFsm.deviceID})
311 oFsm.numUniFlows = 1
312 oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
313
314 //permanently store flow config for reconcile case
dbainbri4d3a0dc2020-12-02 00:33:42 +0000315 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
mpagenkof1fc3862021-02-16 10:09:52 +0000316 &oFsm.uniVlanFlowParamsSlice, true); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000317 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000318 return err
319 }
320
321 return nil
322}
323
mpagenko551a4d42020-12-08 18:09:20 +0000324//GetWaitingTpID returns the TpId that the FSM might be waiting for continuation (0 if none)
325func (oFsm *UniVlanConfigFsm) GetWaitingTpID() uint8 {
326 //mutex protection is required for possible concurrent access to FSM members
327 oFsm.mutexFlowParams.RLock()
328 defer oFsm.mutexFlowParams.RUnlock()
329 return oFsm.TpIDWaitingFor
330}
331
mpagenko2418ab02020-11-12 12:58:06 +0000332//RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
333func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
334 //mutex protection is required for possible concurrent access to FSM members
mpagenko551a4d42020-12-08 18:09:20 +0000335 oFsm.mutexFlowParams.RLock()
336 defer oFsm.mutexFlowParams.RUnlock()
mpagenko2418ab02020-11-12 12:58:06 +0000337 oFsm.clearPersistency = aClear
338}
339
mpagenko01e726e2020-10-23 09:45:29 +0000340//SetUniFlowParams verifies on existence of flow parameters to be configured,
341// optionally udates the cookie list or appends a new flow if there is space
342// if possible the FSM is trigggerd to start with the processing
mpagenko551a4d42020-12-08 18:09:20 +0000343// ignore complexity by now
344// nolint: gocyclo
345func (oFsm *UniVlanConfigFsm) SetUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000346 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
347 loRuleParams := uniVlanRuleParams{
348 TpID: aTpID,
349 MatchVid: uint32(aMatchVlan),
350 SetVid: uint32(aSetVlan),
351 SetPcp: uint32(aSetPcp),
352 }
353 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
354 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
355 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
356
357 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
358 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
359 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
360 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
361 } else {
362 if !oFsm.acceptIncrementalEvtoOption {
363 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
364 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
365 }
366 }
367
368 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
369 // no prio/vid filtering requested
370 loRuleParams.TagsToRemove = 0 //no tag pop action
371 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
372 if loRuleParams.SetPcp == cCopyPrioFromInner {
373 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
374 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
375 // might collide with NoMatchVid/CopyPrio(/setVid) setting
376 // this was some precondition setting taken over from py adapter ..
377 loRuleParams.SetPcp = 0
378 }
379 }
380
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000381 flowEntryMatch := false
mpagenko01e726e2020-10-23 09:45:29 +0000382 flowCookieModify := false
mpagenkof1fc3862021-02-16 10:09:52 +0000383 requestAppendRule := false
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000384 //mutex protection is required for possible concurrent access to FSM members
385 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +0000386 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
387 //TODO: Verify if using e.g. hashes for the structures here for comparison may generate
388 // countable run time optimization (perhaps with including the hash in kvStore storage?)
389 if storedUniFlowParams.VlanRuleParams == loRuleParams {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000390 flowEntryMatch = true
dbainbri4d3a0dc2020-12-02 00:33:42 +0000391 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - rule already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000392 "device-id": oFsm.deviceID})
393 var cookieMatch bool
394 for _, newCookie := range aCookieSlice { // for all cookies available in the arguments
395 cookieMatch = false
396 for _, cookie := range storedUniFlowParams.CookieSlice {
397 if cookie == newCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000398 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - and cookie already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000399 "device-id": oFsm.deviceID, "cookie": cookie})
400 cookieMatch = true
401 break //found new cookie - no further search for this requested cookie
402 }
403 }
404 if !cookieMatch {
mpagenkof1fc3862021-02-16 10:09:52 +0000405 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
406 if delayedCookie != 0 {
407 //a delay for adding the cookie to this rule is requested
408 // take care of the mutex which is already locked here, need to unlock/lock accordingly to prevent deadlock in suspension
409 oFsm.mutexFlowParams.Unlock()
410 oFsm.suspendNewRule(ctx)
411 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
412 oFsm.mutexFlowParams.Lock()
413 } else {
414 logger.Debugw(ctx, "UniVlanConfigFsm flow setting -adding new cookie", log.Fields{
415 "device-id": oFsm.deviceID, "cookie": newCookie})
416 //as range works with copies of the slice we have to write to the original slice!!
417 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
418 newCookie)
419 flowCookieModify = true
420 }
mpagenko01e726e2020-10-23 09:45:29 +0000421 }
422 } //for all new cookies
423 break // found rule - no further rule search
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000424 }
425 }
mpagenkof1fc3862021-02-16 10:09:52 +0000426 oFsm.mutexFlowParams.Unlock()
427
428 if !flowEntryMatch { //it is (was) a new rule
429 delayedCookie := oFsm.suspendIfRequiredNewRule(ctx, aCookieSlice)
430 requestAppendRule = true //default assumption here is that rule is to be appended
431 flowCookieModify = true //and that the the flow data base is to be updated
432 if delayedCookie != 0 { //it was suspended
433 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
434 }
435 }
436 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
437 if requestAppendRule {
438 oFsm.mutexFlowParams.Lock()
439 defer oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000440 if oFsm.numUniFlows < cMaxAllowedFlows {
mpagenko01e726e2020-10-23 09:45:29 +0000441 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
442 loFlowParams.CookieSlice = make([]uint64, 0)
443 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
444 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000445 logger.Debugw(ctx, "UniVlanConfigFsm flow add", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000446 "Cookies": oFsm.uniVlanFlowParamsSlice[oFsm.numUniFlows].CookieSlice,
447 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
448 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800449 "SetPcp": loRuleParams.SetPcp, "numberofFlows": oFsm.numUniFlows + 1,
mpagenko01e726e2020-10-23 09:45:29 +0000450 "device-id": oFsm.deviceID})
451
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000452 oFsm.numUniFlows++
mpagenko01e726e2020-10-23 09:45:29 +0000453 // note: theoretical it would be possible to clear the same rule from the remove slice
454 // (for entries that have not yet been started with removal)
455 // but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
456 // anyway the precondition here is that the FSM checks for rules to delete first and adds new rules afterwards
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000457
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000458 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
459 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
460 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
mpagenko551a4d42020-12-08 18:09:20 +0000461 if oFsm.configuredUniFlow == 0 {
462 // this is a restart with a complete new flow, we can re-use the initial flow config control
463 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000464 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000465 go func(a_pBaseFsm *fsm.FSM) {
466 _ = a_pBaseFsm.Event(vlanEvRenew)
467 }(pConfigVlanStateBaseFsm)
468 } else {
469 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000470 //store the actual rule that shall be worked upon in the following transient states
471 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000472 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000473 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000474 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
475 oFsm.TpIDWaitingFor = tpID
mpagenko9a304ea2020-12-16 15:54:01 +0000476 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request (on setConfig)", log.Fields{
477 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
478 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
479
mpagenko551a4d42020-12-08 18:09:20 +0000480 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
481 if aTechProfDone {
482 // let the vlan processing continue with next rule
483 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
484 } else {
485 // set to waiting for Techprofile
486 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
487 }
488 }(pConfigVlanStateBaseFsm, loTechProfDone)
489 }
mpagenko01e726e2020-10-23 09:45:29 +0000490 } // if not in the appropriate state a new entry will be automatically considered later
491 // when the configDone state is reached
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000492 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000493 logger.Errorw(ctx, "UniVlanConfigFsm flow limit exceeded", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000494 "device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
495 return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
496 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000497 } else {
498 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000499 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenkofc4f56e2020-11-04 17:17:49 +0000500 if oFsm.numUniFlows == oFsm.configuredUniFlow {
501 //all requested rules really have been configured
502 // state transition notification is checked in deviceHandler
503 if oFsm.pDeviceHandler != nil {
504 //also the related TechProfile was already configured
dbainbri4d3a0dc2020-12-02 00:33:42 +0000505 logger.Debugw(ctx, "UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +0000506 "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000507 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
508 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetAddNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000509 }
510 } else {
511 // avoid device reason update as the rule config connected to this flow may still be in progress
512 // and the device reason should only be updated on success of rule config
dbainbri4d3a0dc2020-12-02 00:33:42 +0000513 logger.Debugw(ctx, "UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
mpagenkofc4f56e2020-11-04 17:17:49 +0000514 log.Fields{"device-id": oFsm.deviceID,
515 "NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
516 }
517 }
mpagenko01e726e2020-10-23 09:45:29 +0000518
mpagenkof1fc3862021-02-16 10:09:52 +0000519 if flowCookieModify { // some change was done to the flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000520 //permanently store flow config for reconcile case
mpagenkof1fc3862021-02-16 10:09:52 +0000521 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
522 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000523 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000524 return err
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000525 }
526 }
527 return nil
528}
529
mpagenkof1fc3862021-02-16 10:09:52 +0000530// VOL-3828 flow config sequence workaround ########### start ##########
531func (oFsm *UniVlanConfigFsm) delayNewRuleForCookie(ctx context.Context, aCookieSlice []uint64) uint64 {
532 //assumes mutexFlowParams.Lock() protection from caller!
533 if oFsm.delayNewRuleCookie == 0 && len(aCookieSlice) == 1 {
534 // if not already waiting, limitation for this workaround is to just have one overlapping cookie/rule
535 // suspend check is done only of there is only one cookie in the request
536 // background: more elements only expected in reconcile use case, where no conflicting sequence is to be expected
537 newCookie := aCookieSlice[0]
538 for _, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
539 for _, cookie := range storedUniFlowParams.CookieSlice {
540 if cookie == newCookie {
541 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - new cookie still exists for some rule", log.Fields{
542 "device-id": oFsm.deviceID, "cookie": cookie, "exists with SetVlan": storedUniFlowParams.VlanRuleParams.SetVid})
543 oFsm.delayNewRuleCookie = newCookie
544 return newCookie //found new cookie in some existing rule
545 }
546 } // for all stored cookies of the actual inspected rule
547 } //for all rules
548 }
549 return 0 //no delay requested
550}
551func (oFsm *UniVlanConfigFsm) suspendNewRule(ctx context.Context) {
552 oFsm.mutexFlowParams.RLock()
553 logger.Infow(ctx, "Need to suspend adding this rule as long as the cookie is still connected to some other rule", log.Fields{
554 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
555 oFsm.mutexFlowParams.RUnlock()
556 select {
557 case <-oFsm.chCookieDeleted:
558 logger.Infow(ctx, "resume adding this rule after having deleted cookie in some other rule", log.Fields{
559 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
560 case <-time.After(time.Duration(cWaitForCookieDeletion) * time.Second):
561 logger.Errorw(ctx, "timeout waiting for deletion of cookie in some other rule, just try to continue", log.Fields{
562 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
563 }
564 oFsm.mutexFlowParams.Lock()
565 oFsm.delayNewRuleCookie = 0
566 oFsm.mutexFlowParams.Unlock()
567}
568func (oFsm *UniVlanConfigFsm) suspendIfRequiredNewRule(ctx context.Context, aCookieSlice []uint64) uint64 {
569 oFsm.mutexFlowParams.Lock()
570 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
571 oFsm.mutexFlowParams.Unlock()
572
573 if delayedCookie != 0 {
574 oFsm.suspendNewRule(ctx)
575 }
576 return delayedCookie
577}
578
579//returns flowModified, RuleAppendRequest
580func (oFsm *UniVlanConfigFsm) reviseFlowConstellation(ctx context.Context, aCookie uint64, aUniVlanRuleParams uniVlanRuleParams) (bool, bool) {
581 flowEntryMatch := false
582 oFsm.mutexFlowParams.Lock()
583 defer oFsm.mutexFlowParams.Unlock()
584 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
585 if storedUniFlowParams.VlanRuleParams == aUniVlanRuleParams {
586 flowEntryMatch = true
587 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - rule already exists", log.Fields{
588 "device-id": oFsm.deviceID})
589 cookieMatch := false
590 for _, cookie := range storedUniFlowParams.CookieSlice {
591 if cookie == aCookie {
592 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - and cookie already exists", log.Fields{
593 "device-id": oFsm.deviceID, "cookie": cookie})
594 cookieMatch = true
595 break //found new cookie - no further search for this requested cookie
596 }
597 }
598 if !cookieMatch {
599 logger.Debugw(ctx, "UniVlanConfigFsm flow revise -adding new cookie", log.Fields{
600 "device-id": oFsm.deviceID, "cookie": aCookie})
601 //as range works with copies of the slice we have to write to the original slice!!
602 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
603 aCookie)
604 return true, false //flowModified, NoRuleAppend
605 }
606 break // found rule - no further rule search
607 }
608 }
609 if !flowEntryMatch { //it is a new rule
610 return true, true //flowModified, RuleAppend
611 }
612 return false, false //flowNotModified, NoRuleAppend
613}
614
615// VOL-3828 flow config sequence workaround ########### end ##########
616
mpagenko01e726e2020-10-23 09:45:29 +0000617//RemoveUniFlowParams verifies on existence of flow cookie,
618// if found removes cookie from flow cookie list and if this is empty
619// initiates removal of the flow related configuration from the ONU (via OMCI)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000620func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(ctx context.Context, aCookie uint64) error {
mpagenkof1fc3862021-02-16 10:09:52 +0000621 var deletedCookie uint64
mpagenko01e726e2020-10-23 09:45:29 +0000622 flowCookieMatch := false
623 //mutex protection is required for possible concurrent access to FSM members
624 oFsm.mutexFlowParams.Lock()
625 defer oFsm.mutexFlowParams.Unlock()
mpagenkof1fc3862021-02-16 10:09:52 +0000626remove_loop:
mpagenko01e726e2020-10-23 09:45:29 +0000627 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
628 for i, cookie := range storedUniFlowParams.CookieSlice {
629 if cookie == aCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000630 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - cookie found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000631 "device-id": oFsm.deviceID, "cookie": cookie})
632 flowCookieMatch = true
mpagenkof1fc3862021-02-16 10:09:52 +0000633 deletedCookie = aCookie
634 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
mpagenko01e726e2020-10-23 09:45:29 +0000635 //remove the cookie from the cookie slice and verify it is getting empty
636 if len(storedUniFlowParams.CookieSlice) == 1 {
mpagenko535d6ef2021-02-26 13:15:34 +0000637 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
638 var cancelPendingConfig bool = false
639 var loRemoveParams uniRemoveVlanFlowParams = uniRemoveVlanFlowParams{}
dbainbri4d3a0dc2020-12-02 00:33:42 +0000640 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - full flow removal", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000641 "device-id": oFsm.deviceID})
mpagenko535d6ef2021-02-26 13:15:34 +0000642 //rwCore flow recovery may be the reson for this delete, in which case the flowToBeDeleted may be the same
643 // as the one still waiting in the FSM as toAdd but waiting for TechProfileConfig
644 // so we have to to check that here in in this case have to abort the outstanding AddRequest and regard the current DelRequest as done
645 // if the Fsm is in some other transient (config) state, we will reach the DelRequest later and correctly process it then
646 if pConfigVlanStateBaseFsm.Is(vlanStWaitingTechProf) {
647 logger.Debugw(ctx, "UniVlanConfigFsm was waiting for TechProf config with this rule, aborting the outstanding config",
648 log.Fields{"device-id": oFsm.deviceID})
649 cancelPendingConfig = true
650 } else {
651 //create a new element for the removeVlanFlow slice
652 loRemoveParams = uniRemoveVlanFlowParams{
653 vlanRuleParams: storedUniFlowParams.VlanRuleParams,
654 cookie: aCookie,
655 }
656 oFsm.uniRemoveFlowsSlice = append(oFsm.uniRemoveFlowsSlice, loRemoveParams)
mpagenko01e726e2020-10-23 09:45:29 +0000657 }
mpagenko01e726e2020-10-23 09:45:29 +0000658
659 //and remove the actual element from the addVlanFlow slice
660 // oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = nil //automatically done by garbage collector
661 if len(oFsm.uniVlanFlowParamsSlice) <= 1 {
662 oFsm.numUniFlows = 0 //no more flows
663 oFsm.configuredUniFlow = 0 //no more flows configured
664 oFsm.uniVlanFlowParamsSlice = nil //reset the slice
mpagenko2418ab02020-11-12 12:58:06 +0000665 //at this point it is evident that no flow anymore refers to a still possibly active Techprofile
mpagenko535d6ef2021-02-26 13:15:34 +0000666 //request that this profile gets deleted before a new flow add is allowed (except for some aborted add)
667 if !cancelPendingConfig {
668 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, loRemoveParams.vlanRuleParams.TpID, true)
669 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000670 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - no more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000671 "device-id": oFsm.deviceID})
672 } else {
673 oFsm.numUniFlows--
674 if oFsm.configuredUniFlow > 0 {
675 oFsm.configuredUniFlow--
676 //TODO!! might be needed to consider still outstanding configure requests ..
677 // so a flow at removal might still not be configured !?!
678 }
mpagenko2418ab02020-11-12 12:58:06 +0000679 usedTpID := storedUniFlowParams.VlanRuleParams.TpID
mpagenko01e726e2020-10-23 09:45:29 +0000680 //cut off the requested flow by slicing out this element
681 oFsm.uniVlanFlowParamsSlice = append(
682 oFsm.uniVlanFlowParamsSlice[:flow], oFsm.uniVlanFlowParamsSlice[flow+1:]...)
mpagenko2418ab02020-11-12 12:58:06 +0000683 //here we have to check, if there are still other flows referencing to the actual ProfileId
684 // before we can request that this profile gets deleted before a new flow add is allowed
mpagenkof1fc3862021-02-16 10:09:52 +0000685 // (needed to extract to function due to lint complexity)
mpagenko535d6ef2021-02-26 13:15:34 +0000686 if !cancelPendingConfig {
687 oFsm.updateTechProfileToDelete(ctx, usedTpID)
688 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000689 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow removed from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000690 "device-id": oFsm.deviceID})
691 }
692 //trigger the FSM to remove the relevant rule
mpagenko535d6ef2021-02-26 13:15:34 +0000693 if cancelPendingConfig {
694 oFsm.requestEventOffset = uint8(cDeviceEventOffsetRemoveWithKvStore) //offset for last flow-remove activity (with kvStore request)
mpagenko01e726e2020-10-23 09:45:29 +0000695 go func(a_pBaseFsm *fsm.FSM) {
mpagenko535d6ef2021-02-26 13:15:34 +0000696 _ = a_pBaseFsm.Event(vlanEvCancelOutstandingConfig)
mpagenko01e726e2020-10-23 09:45:29 +0000697 }(pConfigVlanStateBaseFsm)
mpagenko535d6ef2021-02-26 13:15:34 +0000698 } else {
699 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
700 logger.Debugw(ctx, "UniVlanConfigFsm rule removal request", log.Fields{
701 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
702 "tp-id": loRemoveParams.vlanRuleParams.TpID,
703 "set-Vlan": loRemoveParams.vlanRuleParams.SetVid})
704 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
705 // Can't call FSM Event directly, decoupling it
706 go func(a_pBaseFsm *fsm.FSM) {
707 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
708 }(pConfigVlanStateBaseFsm)
709 } // if not in the appropriate state a new entry will be automatically considered later
710 // when the configDone state is reached
711 }
mpagenko01e726e2020-10-23 09:45:29 +0000712 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000713 //cut off the requested cookie by slicing out this element
714 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
715 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
716 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
mpagenkofc4f56e2020-11-04 17:17:49 +0000717 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000718 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenkofc4f56e2020-11-04 17:17:49 +0000719 // state transition notification is checked in deviceHandler
720 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000721 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
722 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000723 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000724 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - rule persists with still valid cookies", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000725 "device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
mpagenkof1fc3862021-02-16 10:09:52 +0000726 if deletedCookie == oFsm.delayNewRuleCookie {
727 //the delayedNewCookie is the one that is currently deleted, but the rule still exist with other cookies
728 //as long as there are further cookies for this rule indicate there is still some cookie to be deleted
729 //simply use the first one
730 oFsm.delayNewRuleCookie = oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[0]
731 logger.Debugw(ctx, "UniVlanConfigFsm remaining cookie awaited for deletion before new rule add", log.Fields{
732 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
733 }
mpagenko01e726e2020-10-23 09:45:29 +0000734 }
mpagenko01e726e2020-10-23 09:45:29 +0000735 //permanently store the modified flow config for reconcile case
mpagenkofc4f56e2020-11-04 17:17:49 +0000736 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000737 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
738 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000739 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000740 return err
741 }
mpagenko01e726e2020-10-23 09:45:29 +0000742 }
mpagenkof1fc3862021-02-16 10:09:52 +0000743 break remove_loop //found the cookie - no further search for this requested cookie
mpagenko01e726e2020-10-23 09:45:29 +0000744 }
745 }
mpagenko01e726e2020-10-23 09:45:29 +0000746 } //search all flows
747 if !flowCookieMatch { //some cookie remove-request for a cookie that does not exist in the FSM data
dbainbri4d3a0dc2020-12-02 00:33:42 +0000748 logger.Warnw(ctx, "UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000749 "device-id": oFsm.deviceID, "remove-cookie": aCookie})
750 // but accept the request with success as no such cookie (flow) does exist
mpagenkofc4f56e2020-11-04 17:17:49 +0000751 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
752 // state transition notification is checked in deviceHandler
753 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000754 // success indication without the need to write to kvStore (no change)
755 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000756 }
mpagenko01e726e2020-10-23 09:45:29 +0000757 return nil
758 } //unknown cookie
759
760 return nil
761}
762
mpagenkof1fc3862021-02-16 10:09:52 +0000763func (oFsm *UniVlanConfigFsm) updateTechProfileToDelete(ctx context.Context, usedTpID uint8) {
764 //here we have to check, if there are still other flows referencing to the actual ProfileId
765 // before we can request that this profile gets deleted before a new flow add is allowed
766 tpIDInOtherFlows := false
767 for _, tpUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
768 if tpUniFlowParams.VlanRuleParams.TpID == usedTpID {
769 tpIDInOtherFlows = true
770 break // search loop can be left
771 }
772 }
773 if tpIDInOtherFlows {
774 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is still used in other flows", log.Fields{
775 "device-id": oFsm.deviceID, "tp-id": usedTpID})
776 } else {
777 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is not used anymore", log.Fields{
778 "device-id": oFsm.deviceID, "tp-id": usedTpID})
779 //request that this profile gets deleted before a new flow add is allowed
780 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, usedTpID, true)
781 }
782}
783
dbainbri4d3a0dc2020-12-02 00:33:42 +0000784func (oFsm *UniVlanConfigFsm) enterConfigStarting(ctx context.Context, e *fsm.Event) {
785 logger.Debugw(ctx, "UniVlanConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000786 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000787
788 // this FSM is not intended for re-start, needs always new creation for a new run
mpagenko01e726e2020-10-23 09:45:29 +0000789 // (self-destroying - compare enterDisabled())
mpagenkodff5dda2020-08-28 11:52:01 +0000790 oFsm.omciMIdsResponseReceived = make(chan bool)
mpagenkof1fc3862021-02-16 10:09:52 +0000791 oFsm.chCookieDeleted = make(chan bool)
mpagenkodff5dda2020-08-28 11:52:01 +0000792 // start go routine for processing of LockState messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000793 go oFsm.processOmciVlanMessages(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +0000794 //let the state machine run forward from here directly
795 pConfigVlanStateAFsm := oFsm.pAdaptFsm
796 if pConfigVlanStateAFsm != nil {
mpagenko551a4d42020-12-08 18:09:20 +0000797 oFsm.mutexFlowParams.Lock()
mpagenko9a304ea2020-12-16 15:54:01 +0000798
799 //possibly the entry is not valid anymore based on intermediate delete requests
800 //just a basic protection ...
801 if len(oFsm.uniVlanFlowParamsSlice) == 0 {
802 oFsm.mutexFlowParams.Unlock()
803 logger.Debugw(ctx, "UniVlanConfigFsm start: no rule entry anymore available", log.Fields{
804 "device-id": oFsm.deviceID})
805 // Can't call FSM Event directly, decoupling it
806 go func(a_pAFsm *AdapterFsm) {
807 _ = a_pAFsm.pFsm.Event(vlanEvReset)
808 }(pConfigVlanStateAFsm)
809 return
810 }
811
812 //access to uniVlanFlowParamsSlice is done on first element only here per definition
813 //store the actual rule that shall be worked upon in the following transient states
814 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams
mpagenko9a304ea2020-12-16 15:54:01 +0000815 tpID := oFsm.actualUniVlanConfigRule.TpID
816 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000817 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID))
mpagenko9a304ea2020-12-16 15:54:01 +0000818 logger.Debugw(ctx, "UniVlanConfigFsm - start with first rule", log.Fields{
819 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
820 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
mpagenko551a4d42020-12-08 18:09:20 +0000821 //cmp also usage in EVTOCDE create in omci_cc
822 oFsm.evtocdID = macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
mpagenko535d6ef2021-02-26 13:15:34 +0000823 oFsm.mutexFlowParams.Unlock()
mpagenko9a304ea2020-12-16 15:54:01 +0000824 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000825 go func(aPAFsm *AdapterFsm, aTechProfDone bool) {
826 if aPAFsm != nil && aPAFsm.pFsm != nil {
827 if aTechProfDone {
mpagenkodff5dda2020-08-28 11:52:01 +0000828 // let the vlan processing begin
mpagenko551a4d42020-12-08 18:09:20 +0000829 _ = aPAFsm.pFsm.Event(vlanEvStartConfig)
mpagenkodff5dda2020-08-28 11:52:01 +0000830 } else {
831 // set to waiting for Techprofile
mpagenko551a4d42020-12-08 18:09:20 +0000832 _ = aPAFsm.pFsm.Event(vlanEvWaitTechProf)
mpagenkodff5dda2020-08-28 11:52:01 +0000833 }
834 }
mpagenko551a4d42020-12-08 18:09:20 +0000835 }(pConfigVlanStateAFsm, loTechProfDone)
836 } else {
837 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
838 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
839 //should never happen, else: recovery would be needed from outside the FSM
840 return
mpagenkodff5dda2020-08-28 11:52:01 +0000841 }
842}
843
dbainbri4d3a0dc2020-12-02 00:33:42 +0000844func (oFsm *UniVlanConfigFsm) enterConfigVtfd(ctx context.Context, e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000845 //mutex protection is required for possible concurrent access to FSM members
846 oFsm.mutexFlowParams.Lock()
mpagenko551a4d42020-12-08 18:09:20 +0000847 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
mpagenko9a304ea2020-12-16 15:54:01 +0000848 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000849 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000850 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000851 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000852 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000853 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
mpagenkodff5dda2020-08-28 11:52:01 +0000854 pConfigVlanStateAFsm := oFsm.pAdaptFsm
mpagenko9a304ea2020-12-16 15:54:01 +0000855 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +0000856 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530857 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000858 }(pConfigVlanStateAFsm)
859 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300860 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
861 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +0000862 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000863 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300864 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000865 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
866 // setVid is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +0000867 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000868 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000869 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000870 vtfdFilterList[0] = oFsm.vlanFilterList[0]
871 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000872 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300873 EntityID: vtfdID,
mpagenkodff5dda2020-08-28 11:52:01 +0000874 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000875 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
876 "ForwardOperation": uint8(0x10), //VID investigation
877 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000878 },
879 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000880 logger.Debugw(ctx, "UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000881 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000882 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +0000883 oFsm.pAdaptFsm.commChan, meParams)
884 //accept also nil as (error) return value for writing to LastTx
885 // - this avoids misinterpretation of new received OMCI messages
886 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
887 // send shall return (dual format) error code that can be used here for immediate error treatment
888 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000889 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000890 }
891}
892
dbainbri4d3a0dc2020-12-02 00:33:42 +0000893func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(ctx context.Context, e *fsm.Event) {
894 logger.Debugw(ctx, "UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000895 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000896 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300897 go func() {
mpagenko9a304ea2020-12-16 15:54:01 +0000898 //using the first element in the slice because it's the first flow per definition here
899 errEvto := oFsm.performConfigEvtocdEntries(ctx, 0)
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300900 //This is correct passing scenario
901 if errEvto == nil {
mpagenko9a304ea2020-12-16 15:54:01 +0000902 tpID := oFsm.actualUniVlanConfigRule.TpID
903 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +0000904 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
905 logger.Infow(ctx, "Setting multicast MEs, with first flow", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300906 "techProfile": tpID, "gemPort": gemPort, "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000907 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300908 vlanID)
909 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000910 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300911 log.Fields{"device-id": oFsm.deviceID})
912 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
913 }
914 }
915 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
916 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
917 }
918 }()
mpagenkodff5dda2020-08-28 11:52:01 +0000919}
920
dbainbri4d3a0dc2020-12-02 00:33:42 +0000921func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(ctx context.Context, e *fsm.Event) {
mpagenko9a304ea2020-12-16 15:54:01 +0000922 oFsm.mutexFlowParams.RLock()
923 defer oFsm.mutexFlowParams.RUnlock()
924
mpagenkof1fc3862021-02-16 10:09:52 +0000925 logger.Infow(ctx, "UniVlanConfigFsm config done - checking on more flows", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000926 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
927 "overall-uni-rules": oFsm.numUniFlows, "configured-uni-rules": oFsm.configuredUniFlow})
928 pConfigVlanStateAFsm := oFsm.pAdaptFsm
929 if pConfigVlanStateAFsm == nil {
mpagenko551a4d42020-12-08 18:09:20 +0000930 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
931 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
932 //should never happen, else: recovery would be needed from outside the FSM
933 return
934 }
935 pConfigVlanStateBaseFsm := pConfigVlanStateAFsm.pFsm
mpagenko01e726e2020-10-23 09:45:29 +0000936 if len(oFsm.uniRemoveFlowsSlice) > 0 {
937 //some further flows are to be removed, removal always starts with the first element
mpagenko9a304ea2020-12-16 15:54:01 +0000938 logger.Debugw(ctx, "UniVlanConfigFsm rule removal from ConfigDone", log.Fields{
939 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
940 "tp-id": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.TpID,
941 "set-Vlan": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.SetVid})
942 // Can't call FSM Event directly, decoupling it
mpagenko01e726e2020-10-23 09:45:29 +0000943 go func(a_pBaseFsm *fsm.FSM) {
944 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
945 }(pConfigVlanStateBaseFsm)
946 return
947 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000948 if oFsm.numUniFlows > oFsm.configuredUniFlow {
mpagenko551a4d42020-12-08 18:09:20 +0000949 if oFsm.configuredUniFlow == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000950 // this is a restart with a complete new flow, we can re-use the initial flow config control
951 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000952 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000953 go func(a_pBaseFsm *fsm.FSM) {
954 _ = a_pBaseFsm.Event(vlanEvRenew)
955 }(pConfigVlanStateBaseFsm)
956 return
957 }
958
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000959 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000960 //store the actual rule that shall be worked upon in the following transient states
961 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000962 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000963 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000964 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000965 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
mpagenko9a304ea2020-12-16 15:54:01 +0000966 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request", log.Fields{
967 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
968 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
969 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000970 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
971 if aTechProfDone {
972 // let the vlan processing continue with next rule
973 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
974 } else {
975 // set to waiting for Techprofile
976 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
977 }
978 }(pConfigVlanStateBaseFsm, loTechProfDone)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000979 return
980 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000981 logger.Debugw(ctx, "UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000982 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000983 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
984 // state transition notification is checked in deviceHandler
mpagenko551a4d42020-12-08 18:09:20 +0000985 // note: 'flowPushed' event is only generated if all 'pending' rules are configured
mpagenkodff5dda2020-08-28 11:52:01 +0000986 if oFsm.pDeviceHandler != nil {
mpagenkofc4f56e2020-11-04 17:17:49 +0000987 //making use of the add->remove successor enum assumption/definition
dbainbri4d3a0dc2020-12-02 00:33:42 +0000988 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(uint8(oFsm.requestEvent)+oFsm.requestEventOffset))
mpagenkodff5dda2020-08-28 11:52:01 +0000989 }
990}
991
dbainbri4d3a0dc2020-12-02 00:33:42 +0000992func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(ctx context.Context, e *fsm.Event) {
993 logger.Debugw(ctx, "UniVlanConfigFsm - start config further incremental flow", log.Fields{
Girish Gowdra041dcb32020-11-16 16:54:30 -0800994 "in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000995 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000996 oFsm.mutexFlowParams.Lock()
mpagenko551a4d42020-12-08 18:09:20 +0000997 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000998
mpagenko9a304ea2020-12-16 15:54:01 +0000999 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001000 // meaning transparent setup - no specific VTFD setting required
1001 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001002 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001003 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001004 } else {
1005 if oFsm.numVlanFilterEntries == 0 {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001006 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
1007 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +00001008 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001009 //no VTFD yet created
dbainbri4d3a0dc2020-12-02 00:33:42 +00001010 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001011 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001012 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001013 // 'SetVid' below is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +00001014 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001015
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001016 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001017 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001018 vtfdFilterList[0] = oFsm.vlanFilterList[0]
1019 oFsm.numVlanFilterEntries = 1
1020 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001021 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001022 Attributes: me.AttributeValueMap{
1023 "VlanFilterList": vtfdFilterList,
1024 "ForwardOperation": uint8(0x10), //VID investigation
1025 "NumberOfEntries": oFsm.numVlanFilterEntries,
1026 },
1027 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001028 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001029 oFsm.pAdaptFsm.commChan, meParams)
1030 //accept also nil as (error) return value for writing to LastTx
1031 // - this avoids misinterpretation of new received OMCI messages
1032 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1033 // send shall return (dual format) error code that can be used here for immediate error treatment
1034 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001035 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001036 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001037 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
1038 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko551a4d42020-12-08 18:09:20 +00001039 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID +
mpagenko9a304ea2020-12-16 15:54:01 +00001040 uint16(oFsm.actualUniVlanConfigRule.TpID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001041
dbainbri4d3a0dc2020-12-02 00:33:42 +00001042 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001043 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001044 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001045 // setVid is assumed to be masked already by the caller to 12 bit
1046 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko9a304ea2020-12-16 15:54:01 +00001047 uint16(oFsm.actualUniVlanConfigRule.SetVid)
mpagenko01e726e2020-10-23 09:45:29 +00001048 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001049
1050 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
1051 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
1052 // new vlan associated with a different TP.
mpagenko9a304ea2020-12-16 15:54:01 +00001053 vtfdFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001054 oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001055
1056 oFsm.numVlanFilterEntries++
1057 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001058 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001059 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001060 "VlanFilterList": vtfdFilterList,
1061 "ForwardOperation": uint8(0x10), //VID investigation
1062 "NumberOfEntries": oFsm.numVlanFilterEntries,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001063 },
1064 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001065 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001066 oFsm.pAdaptFsm.commChan, meParams)
1067 //accept also nil as (error) return value for writing to LastTx
1068 // - this avoids misinterpretation of new received OMCI messages
1069 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1070 // send shall return (dual format) error code that can be used here for immediate error treatment
1071 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001072 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001073 }
1074 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001075 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001076 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001077 logger.Errorw(ctx, "VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001078 log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001079 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
mpagenko9a304ea2020-12-16 15:54:01 +00001080 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001081 go func(a_pBaseFsm *fsm.FSM) {
1082 _ = a_pBaseFsm.Event(vlanEvReset)
1083 }(pConfigVlanStateBaseFsm)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001084 return
1085 }
1086 }
mpagenkof1fc3862021-02-16 10:09:52 +00001087 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001088 go func() {
mpagenko9a304ea2020-12-16 15:54:01 +00001089 tpID := oFsm.actualUniVlanConfigRule.TpID
dbainbri4d3a0dc2020-12-02 00:33:42 +00001090 errEvto := oFsm.performConfigEvtocdEntries(ctx, oFsm.configuredUniFlow)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001091 //This is correct passing scenario
1092 if errEvto == nil {
1093 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
dbainbri4d3a0dc2020-12-02 00:33:42 +00001094 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
mpagenko9a304ea2020-12-16 15:54:01 +00001095 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +00001096 logger.Infow(ctx, "Setting multicast MEs for additional flows", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001097 "techProfile": tpID, "gemPort": gemPort,
1098 "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
dbainbri4d3a0dc2020-12-02 00:33:42 +00001099 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001100 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001101 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001102 log.Fields{"device-id": oFsm.deviceID})
1103 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1104 }
1105 }
1106 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
1107 }
1108 }()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001109}
1110
dbainbri4d3a0dc2020-12-02 00:33:42 +00001111func (oFsm *UniVlanConfigFsm) enterRemoveFlow(ctx context.Context, e *fsm.Event) {
mpagenko551a4d42020-12-08 18:09:20 +00001112 oFsm.mutexFlowParams.RLock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001113 logger.Debugw(ctx, "UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001114 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
1115 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001116
mpagenkofc4f56e2020-11-04 17:17:49 +00001117 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
1118 loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
mpagenko01e726e2020-10-23 09:45:29 +00001119 loVlanEntryClear := uint8(0)
1120 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
1121 //shallow copy is sufficient as no reference variables are used within struct
1122 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +00001123 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001124 logger.Debugw(ctx, "UniVlanConfigFsm - remove-flow parameters are", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001125 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
1126 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
1127 "device-id": oFsm.deviceID})
1128
1129 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1130 // meaning transparent setup - no specific VTFD setting required
dbainbri4d3a0dc2020-12-02 00:33:42 +00001131 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001132 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
1133 } else {
1134 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
1135 if oFsm.numVlanFilterEntries == 1 {
mpagenko551a4d42020-12-08 18:09:20 +00001136 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001137 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
1138 // so we can just delete the VTFD entry
dbainbri4d3a0dc2020-12-02 00:33:42 +00001139 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD delete (no more vlan filters)",
mpagenko01e726e2020-10-23 09:45:29 +00001140 log.Fields{"current vlan list": oFsm.vlanFilterList,
1141 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001142 loVlanEntryClear = 1 //full VlanFilter clear request
1143 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001144 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001145 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001146 oFsm.pLastTxMeInstance = meInstance
1147 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001148 logger.Debugw(ctx, "UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001149 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenkofc4f56e2020-11-04 17:17:49 +00001150 }
mpagenko01e726e2020-10-23 09:45:29 +00001151 } else {
1152 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
1153 // by updating the VTFD per set command with new valid list
dbainbri4d3a0dc2020-12-02 00:33:42 +00001154 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
mpagenko01e726e2020-10-23 09:45:29 +00001155 log.Fields{"current vlan list": oFsm.vlanFilterList,
1156 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
1157 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1158 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
1159 loVlanEntryRmPos = i
1160 break //abort search
1161 }
1162 }
1163 if loVlanEntryRmPos < cVtfdTableSize {
mpagenko551a4d42020-12-08 18:09:20 +00001164 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001165 //valid entry was found - to be eclipsed
1166 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
1167 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1168 if i < loVlanEntryRmPos {
1169 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
1170 } else if i < (cVtfdTableSize - 1) {
1171 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
1172 } else {
1173 vtfdFilterList[i] = 0 //set last byte if needed
1174 }
1175 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001176 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001177 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001178 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
1179
mpagenkofc4f56e2020-11-04 17:17:49 +00001180 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001181 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
dbainbri4d3a0dc2020-12-02 00:33:42 +00001182 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001183 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001184 oFsm.pLastTxMeInstance = meInstance
1185 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001186 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001187 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenko01e726e2020-10-23 09:45:29 +00001188 }
mpagenko01e726e2020-10-23 09:45:29 +00001189 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001190 logger.Warnw(ctx, "UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
mpagenko01e726e2020-10-23 09:45:29 +00001191 log.Fields{"device-id": oFsm.deviceID})
1192 }
1193 }
1194 if loVlanEntryClear > 0 {
mpagenkofc4f56e2020-11-04 17:17:49 +00001195 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
1196 //waiting on response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001197 err := oFsm.waitforOmciResponse(ctx)
mpagenkofc4f56e2020-11-04 17:17:49 +00001198 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001199 logger.Errorw(ctx, "VTFD delete/reset failed, aborting VlanConfig FSM!",
mpagenkofc4f56e2020-11-04 17:17:49 +00001200 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001201 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001202 go func(a_pBaseFsm *fsm.FSM) {
1203 _ = a_pBaseFsm.Event(vlanEvReset)
1204 }(pConfigVlanStateBaseFsm)
1205 return
1206 }
mpagenko01e726e2020-10-23 09:45:29 +00001207 }
1208
1209 if loVlanEntryClear == 1 {
1210 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
1211 oFsm.numVlanFilterEntries = 0
1212 } else if loVlanEntryClear == 2 {
1213 // new VlanFilterList should be one entry smaller now - copy from last configured entry
1214 // this loop now includes the 0 element on previous last valid entry
1215 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
1216 oFsm.vlanFilterList[i] = vtfdFilterList[i]
1217 }
1218 oFsm.numVlanFilterEntries--
1219 }
1220 }
1221 }
1222
mpagenkofc4f56e2020-11-04 17:17:49 +00001223 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001224 go oFsm.removeEvtocdEntries(ctx, loRuleParams)
mpagenkofc4f56e2020-11-04 17:17:49 +00001225 } else {
1226 // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001227 logger.Debugw(ctx, "UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +00001228 "device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001229 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001230 go func(a_pBaseFsm *fsm.FSM) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001231 _ = a_pBaseFsm.Event(vlanEvRemFlowDone, loRuleParams.TpID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001232 }(pConfigVlanStateBaseFsm)
1233 }
mpagenkodff5dda2020-08-28 11:52:01 +00001234}
1235
dbainbri4d3a0dc2020-12-02 00:33:42 +00001236func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(ctx context.Context, e *fsm.Event) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001237 var tpID uint8
1238 // Extract the tpID
1239 if len(e.Args) > 0 {
1240 tpID = e.Args[0].(uint8)
1241 logger.Debugw(ctx, "UniVlanConfigFsm - flow removed for tp id", log.Fields{"device-id": oFsm.deviceID, "tpID": e.Args[0].(uint8)})
1242 } else {
1243 logger.Warnw(ctx, "UniVlanConfigFsm - tp id not available", log.Fields{"device-id": oFsm.deviceID})
1244 }
mpagenko01e726e2020-10-23 09:45:29 +00001245 oFsm.mutexFlowParams.Lock()
mpagenkof1fc3862021-02-16 10:09:52 +00001246 deletedCookie := oFsm.uniRemoveFlowsSlice[0].cookie
1247 logger.Debugw(ctx, "UniVlanConfigFsm - removing the removal data", log.Fields{
1248 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
1249 "removed cookie": deletedCookie, "waitForDeleteCookie": oFsm.delayNewRuleCookie})
1250
mpagenko01e726e2020-10-23 09:45:29 +00001251 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
1252 oFsm.uniRemoveFlowsSlice = nil //reset the slice
dbainbri4d3a0dc2020-12-02 00:33:42 +00001253 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001254 "device-id": oFsm.deviceID})
1255 } else {
1256 //cut off the actual flow by slicing out the first element
1257 oFsm.uniRemoveFlowsSlice = append(
1258 oFsm.uniRemoveFlowsSlice[:0],
1259 oFsm.uniRemoveFlowsSlice[1:]...)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001260 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001261 "device-id": oFsm.deviceID})
1262 }
1263 oFsm.mutexFlowParams.Unlock()
1264
mpagenkof1fc3862021-02-16 10:09:52 +00001265 oFsm.requestEventOffset = uint8(cDeviceEventOffsetRemoveWithKvStore) //offset for last flow-remove activity (with kvStore request)
mpagenko01e726e2020-10-23 09:45:29 +00001266 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +00001267 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1268 if pConfigVlanStateAFsm != nil {
mpagenko9a304ea2020-12-16 15:54:01 +00001269 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001270 go func(a_pAFsm *AdapterFsm) {
1271 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001272 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +00001273 }
1274 }(pConfigVlanStateAFsm)
1275 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001276
1277 oFsm.mutexFlowParams.RLock()
1278 noOfFlowRem := len(oFsm.uniRemoveFlowsSlice)
mpagenkof1fc3862021-02-16 10:09:52 +00001279 if deletedCookie == oFsm.delayNewRuleCookie {
1280 // flush the channel CookieDeleted to ensure it is not lingering from some previous (aborted) activity
1281 select {
1282 case <-oFsm.chCookieDeleted:
1283 logger.Debug(ctx, "flushed CookieDeleted")
1284 default:
1285 }
1286 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue
1287 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001288 oFsm.mutexFlowParams.RUnlock()
1289 // If all pending flow removes are completed and TP ID is valid, processing any pending TP delete
1290 if noOfFlowRem == 0 && tpID > 0 {
1291 logger.Debugw(ctx, "processing pending tp delete", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID})
1292 // If we are here then all flows are removed.
1293 oFsm.pDeviceHandler.ProcessPendingTpDelete(ctx, oFsm.pOnuUniPort, tpID)
1294 }
mpagenkodff5dda2020-08-28 11:52:01 +00001295}
1296
dbainbri4d3a0dc2020-12-02 00:33:42 +00001297func (oFsm *UniVlanConfigFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1298 logger.Debugw(ctx, "UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001299
1300 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1301 if pConfigVlanStateAFsm != nil {
1302 // abort running message processing
1303 fsmAbortMsg := Message{
1304 Type: TestMsg,
1305 Data: TestMessage{
1306 TestMessageVal: AbortMessageProcessing,
1307 },
1308 }
1309 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
1310
mpagenko9a304ea2020-12-16 15:54:01 +00001311 //try to restart the FSM to 'disabled'
1312 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001313 go func(a_pAFsm *AdapterFsm) {
1314 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301315 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +00001316 }
1317 }(pConfigVlanStateAFsm)
1318 }
1319}
1320
dbainbri4d3a0dc2020-12-02 00:33:42 +00001321func (oFsm *UniVlanConfigFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1322 logger.Debugw(ctx, "UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001323 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +00001324 if oFsm.pDeviceHandler != nil {
mpagenko2418ab02020-11-12 12:58:06 +00001325 //TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
1326 // current code removes the complete FSM including all flow/rule configuration done so far
1327 // this might be a bit to much, it would require fully new flow config from rwCore (at least on OnuDown/up)
1328 // maybe a more sophisticated approach is possible without clearing the data
mpagenko9a304ea2020-12-16 15:54:01 +00001329 oFsm.mutexFlowParams.RLock()
mpagenko2418ab02020-11-12 12:58:06 +00001330 if oFsm.clearPersistency {
1331 //permanently remove possibly stored persistent data
1332 if len(oFsm.uniVlanFlowParamsSlice) > 0 {
1333 var emptySlice = make([]uniVlanFlowParams, 0)
mpagenkof1fc3862021-02-16 10:09:52 +00001334 _ = oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID, &emptySlice, true) //ignore errors
mpagenko2418ab02020-11-12 12:58:06 +00001335 }
1336 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001337 logger.Debugw(ctx, "UniVlanConfigFsm persistency data not cleared", log.Fields{"device-id": oFsm.deviceID})
mpagenko2418ab02020-11-12 12:58:06 +00001338 }
mpagenkof1fc3862021-02-16 10:09:52 +00001339 if oFsm.delayNewRuleCookie != 0 {
1340 // looks like the waiting AddFlow is stuck
1341 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue/treminate
1342 }
mpagenko9a304ea2020-12-16 15:54:01 +00001343 oFsm.mutexFlowParams.RUnlock()
mpagenko2418ab02020-11-12 12:58:06 +00001344 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001345 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(ctx, oFsm.pOnuUniPort)
mpagenkodff5dda2020-08-28 11:52:01 +00001346 }
1347}
1348
dbainbri4d3a0dc2020-12-02 00:33:42 +00001349func (oFsm *UniVlanConfigFsm) processOmciVlanMessages(ctx context.Context) { //ctx context.Context?
1350 logger.Debugw(ctx, "Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001351loop:
1352 for {
mpagenkodff5dda2020-08-28 11:52:01 +00001353 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00001354 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001355 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301356 message, ok := <-oFsm.pAdaptFsm.commChan
1357 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001358 logger.Info(ctx, "UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301359 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1360 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1361 break loop
1362 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001363 logger.Debugw(ctx, "UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301364
1365 switch message.Type {
1366 case TestMsg:
1367 msg, _ := message.Data.(TestMessage)
1368 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001369 logger.Infow(ctx, "UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001370 break loop
1371 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001372 logger.Warnw(ctx, "UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301373 case OMCI:
1374 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001375 oFsm.handleOmciVlanConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301376 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001377 logger.Warn(ctx, "UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301378 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +00001379 }
1380 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001381 logger.Infow(ctx, "End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001382}
1383
dbainbri4d3a0dc2020-12-02 00:33:42 +00001384func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(ctx context.Context, msg OmciMessage) {
1385 logger.Debugw(ctx, "Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001386 "msgType": msg.OmciMsg.MessageType})
1387
1388 switch msg.OmciMsg.MessageType {
1389 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001390 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001391 if err := oFsm.handleOmciCreateResponseMessage(ctx, msg.OmciPacket); err != nil {
1392 logger.Warnw(ctx, "CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +00001393 return
1394 }
mpagenkodff5dda2020-08-28 11:52:01 +00001395 } //CreateResponseType
1396 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001397 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +00001398 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1399 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001400 logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001401 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001402 return
1403 }
1404 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1405 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001406 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001407 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001408 return
1409 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001410 logger.Debugw(ctx, "UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +00001411 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001412 logger.Errorw(ctx, "UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001413 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +00001414 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1415 return
1416 }
mpagenko01e726e2020-10-23 09:45:29 +00001417 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1418 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1419 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001420 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData", "MulticastOperationsProfile":
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001421 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +00001422 oFsm.omciMIdsResponseReceived <- true
1423 }
1424 }
1425 }
1426 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +00001427 case omci.DeleteResponseType:
1428 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001429 if err := oFsm.handleOmciDeleteResponseMessage(ctx, msg.OmciPacket); err != nil {
1430 logger.Warnw(ctx, "DeleteResponse handling aborted", log.Fields{"err": err})
mpagenko01e726e2020-10-23 09:45:29 +00001431 return
1432 }
1433 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +00001434 default:
1435 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001436 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001437 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001438 return
1439 }
1440 }
1441}
1442
dbainbri4d3a0dc2020-12-02 00:33:42 +00001443func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001444 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
1445 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001446 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001447 log.Fields{"device-id": oFsm.deviceID})
1448 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
1449 oFsm.deviceID)
1450 }
1451 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1452 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001453 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001454 log.Fields{"device-id": oFsm.deviceID})
1455 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
1456 oFsm.deviceID)
1457 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001458 logger.Debugw(ctx, "UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001459 if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001460 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
mpagenko01e726e2020-10-23 09:45:29 +00001461 "Error": msgObj.Result})
1462 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1463 return fmt.Errorf("omci CreateResponse Error for device-id %x",
1464 oFsm.deviceID)
1465 }
1466 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1467 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1468 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
1469 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001470 case "VlanTaggingFilterData", "MulticastOperationsProfile",
1471 "MulticastSubscriberConfigInfo", "MacBridgePortConfigurationData",
1472 "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001473 {
1474 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
1475 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
1476 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
1477 } else { // let the MultiEntity config proceed by stopping the wait function
1478 oFsm.omciMIdsResponseReceived <- true
1479 }
1480 }
1481 }
1482 }
1483 return nil
1484}
1485
dbainbri4d3a0dc2020-12-02 00:33:42 +00001486func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001487 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1488 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001489 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001490 log.Fields{"device-id": oFsm.deviceID})
1491 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1492 oFsm.deviceID)
1493 }
1494 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1495 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001496 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001497 log.Fields{"device-id": oFsm.deviceID})
1498 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1499 oFsm.deviceID)
1500 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001501 logger.Debugw(ctx, "UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko01e726e2020-10-23 09:45:29 +00001502 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001503 logger.Errorw(ctx, "UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001504 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1505 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1506 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1507 oFsm.deviceID)
1508 }
1509 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1510 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1511 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001512 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001513 { // let the MultiEntity config proceed by stopping the wait function
1514 oFsm.omciMIdsResponseReceived <- true
1515 }
1516 }
1517 }
1518 return nil
1519}
1520
dbainbri4d3a0dc2020-12-02 00:33:42 +00001521func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(ctx context.Context, aFlowEntryNo uint8) error {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001522 if aFlowEntryNo == 0 {
1523 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001524 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1525 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
dbainbri4d3a0dc2020-12-02 00:33:42 +00001526 logger.Debugw(ctx, "UniVlanConfigFsm Tx Create::EVTOCD", log.Fields{
mpagenkodff5dda2020-08-28 11:52:01 +00001527 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1528 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001529 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001530 associationType := 2 // default to uniPPTP
1531 if oFsm.pOnuUniPort.portType == uniVEIP {
1532 associationType = 10
1533 }
1534 // Create the EVTOCD ME
mpagenkodff5dda2020-08-28 11:52:01 +00001535 meParams := me.ParamData{
1536 EntityID: oFsm.evtocdID,
1537 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001538 "AssociationType": uint8(associationType),
1539 "AssociatedMePointer": oFsm.pOnuUniPort.entityID,
mpagenkodff5dda2020-08-28 11:52:01 +00001540 },
1541 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001542 meInstance := oFsm.pOmciCC.sendCreateEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001543 oFsm.pAdaptFsm.commChan, meParams)
1544 //accept also nil as (error) return value for writing to LastTx
1545 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001546 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001547
1548 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001549 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001550 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001551 logger.Errorw(ctx, "Evtocd create failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001552 log.Fields{"device-id": oFsm.deviceID})
1553 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1554 return fmt.Errorf("evtocd create failed %s, error %s", oFsm.deviceID, err)
1555 }
1556
1557 // Set the EVTOCD ME default params
1558 meParams = me.ParamData{
1559 EntityID: oFsm.evtocdID,
1560 Attributes: me.AttributeValueMap{
1561 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1562 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1563 "DownstreamMode": uint8(cDefaultDownstreamMode),
1564 },
1565 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001566 meInstance = oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001567 oFsm.pAdaptFsm.commChan, meParams)
1568 //accept also nil as (error) return value for writing to LastTx
1569 // - this avoids misinterpretation of new received OMCI messages
1570 oFsm.pLastTxMeInstance = meInstance
1571
1572 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001573 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001574 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001575 logger.Errorw(ctx, "Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001576 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301577 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001578 return fmt.Errorf("evtocd set TPID failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001579 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001580 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001581
mpagenko551a4d42020-12-08 18:09:20 +00001582 oFsm.mutexFlowParams.RLock()
mpagenko9a304ea2020-12-16 15:54:01 +00001583 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001584 //transparent transmission required
mpagenko551a4d42020-12-08 18:09:20 +00001585 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001586 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001587 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001588 sliceEvtocdRule := make([]uint8, 16)
1589 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1590 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1591 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1592 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1593 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1594
1595 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1596 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1597 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1598 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1599 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1600
1601 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1602 0<<cTreatTTROffset| // Do not pop any tags
1603 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1604 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1605 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1606
1607 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1608 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1609 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1610 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1611
1612 meParams := me.ParamData{
1613 EntityID: oFsm.evtocdID,
1614 Attributes: me.AttributeValueMap{
1615 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1616 },
1617 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001618 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001619 oFsm.pAdaptFsm.commChan, meParams)
1620 //accept also nil as (error) return value for writing to LastTx
1621 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001622 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001623
1624 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001625 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001626 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001627 logger.Errorw(ctx, "Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001628 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301629 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001630 return fmt.Errorf("evtocd set transparent singletagged rule failed %s, error %s", oFsm.deviceID, err)
1631
mpagenkodff5dda2020-08-28 11:52:01 +00001632 }
1633 } else {
1634 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1635 if oFsm.acceptIncrementalEvtoOption {
mpagenko9a304ea2020-12-16 15:54:01 +00001636 matchPcp := oFsm.actualUniVlanConfigRule.MatchPcp
1637 matchVid := oFsm.actualUniVlanConfigRule.MatchVid
1638 setPcp := oFsm.actualUniVlanConfigRule.SetPcp
1639 setVid := oFsm.actualUniVlanConfigRule.SetVid
mpagenkodff5dda2020-08-28 11:52:01 +00001640 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001641 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001642 "match-pcp": matchPcp, "match-vid": matchVid, "set-pcp": setPcp, "set-vid:": setVid, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001643 sliceEvtocdRule := make([]uint8, 16)
1644 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1645 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1646 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1647 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1648 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1649
1650 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001651 oFsm.actualUniVlanConfigRule.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1652 oFsm.actualUniVlanConfigRule.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001653 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1654 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1655
1656 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001657 oFsm.actualUniVlanConfigRule.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001658 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1659 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1660 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1661
1662 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001663 oFsm.actualUniVlanConfigRule.SetPcp<<cTreatPrioOffset| // as configured in flow
1664 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001665 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001666 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001667
1668 meParams := me.ParamData{
1669 EntityID: oFsm.evtocdID,
1670 Attributes: me.AttributeValueMap{
1671 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1672 },
1673 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001674 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001675 oFsm.pAdaptFsm.commChan, meParams)
1676 //accept also nil as (error) return value for writing to LastTx
1677 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001678 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001679
1680 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001681 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001682 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001683 logger.Errorw(ctx, "Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001684 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301685 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001686 return fmt.Errorf("evtocd set singletagged translation rule failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001687 }
1688 } else {
1689 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1690 { // just for local var's
1691 // this defines stacking scenario: untagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001692 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001693 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001694 sliceEvtocdRule := make([]uint8, 16)
1695 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1696 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1697 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1698 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1699 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1700
1701 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1702 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1703 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1704 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1705 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1706
1707 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1708 0<<cTreatTTROffset| // Do not pop any tags
1709 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1710 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1711 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1712
1713 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1714 0<<cTreatPrioOffset| // vlan prio set to 0
1715 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko9a304ea2020-12-16 15:54:01 +00001716 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001717 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1718
mpagenko551a4d42020-12-08 18:09:20 +00001719 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001720 meParams := me.ParamData{
1721 EntityID: oFsm.evtocdID,
1722 Attributes: me.AttributeValueMap{
1723 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1724 },
1725 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001726 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001727 oFsm.pAdaptFsm.commChan, meParams)
1728 //accept also nil as (error) return value for writing to LastTx
1729 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001730 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001731
1732 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001733 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001734 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001735 logger.Errorw(ctx, "Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001736 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301737 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001738 return fmt.Errorf("evtocd set untagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1739
mpagenkodff5dda2020-08-28 11:52:01 +00001740 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001741 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001742 { // just for local var's
1743 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001744 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001745 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001746 sliceEvtocdRule := make([]uint8, 16)
1747 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1748 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1749 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1750 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1751 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1752
1753 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1754 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1755 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1756 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1757 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1758
1759 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1760 1<<cTreatTTROffset| // pop the prio-tag
1761 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1762 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1763 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1764
mpagenko551a4d42020-12-08 18:09:20 +00001765 oFsm.mutexFlowParams.RLock()
mpagenkodff5dda2020-08-28 11:52:01 +00001766 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1767 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1768 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko9a304ea2020-12-16 15:54:01 +00001769 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001770 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001771 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001772
1773 meParams := me.ParamData{
1774 EntityID: oFsm.evtocdID,
1775 Attributes: me.AttributeValueMap{
1776 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1777 },
1778 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001779 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001780 oFsm.pAdaptFsm.commChan, meParams)
1781 //accept also nil as (error) return value for writing to LastTx
1782 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001783 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001784
1785 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001786 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001787 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001788 logger.Errorw(ctx, "Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001789 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301790 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001791 return fmt.Errorf("evtocd set priotagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1792
mpagenkodff5dda2020-08-28 11:52:01 +00001793 }
1794 } //just for local var's
1795 }
1796 }
1797
mpagenkofc4f56e2020-11-04 17:17:49 +00001798 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001799 logger.Debugw(ctx, "EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001800 oFsm.configuredUniFlow++ // one (more) flow configured
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001801 return nil
mpagenkodff5dda2020-08-28 11:52:01 +00001802}
1803
dbainbri4d3a0dc2020-12-02 00:33:42 +00001804func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(ctx context.Context, aRuleParams uniVlanRuleParams) {
mpagenko01e726e2020-10-23 09:45:29 +00001805 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1806 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1807 //transparent transmission was set
1808 //perhaps the config is not needed for removal,
1809 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
dbainbri4d3a0dc2020-12-02 00:33:42 +00001810 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001811 "device-id": oFsm.deviceID})
1812 sliceEvtocdRule := make([]uint8, 16)
1813 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1814 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1815 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1816 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1817 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1818
1819 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1820 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1821 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1822 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1823 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1824
1825 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1826 0<<cTreatTTROffset| // Do not pop any tags
1827 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1828 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1829 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1830
1831 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1832 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1833 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1834 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1835
1836 meParams := me.ParamData{
1837 EntityID: oFsm.evtocdID,
1838 Attributes: me.AttributeValueMap{
1839 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1840 },
1841 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001842 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001843 oFsm.pAdaptFsm.commChan, meParams)
1844 //accept also nil as (error) return value for writing to LastTx
1845 // - this avoids misinterpretation of new received OMCI messages
1846 oFsm.pLastTxMeInstance = meInstance
1847
1848 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001849 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001850 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001851 logger.Errorw(ctx, "Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001852 log.Fields{"device-id": oFsm.deviceID})
1853 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1854 return
1855 }
1856 } else {
1857 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1858 if oFsm.acceptIncrementalEvtoOption {
1859 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001860 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001861 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1862 sliceEvtocdRule := make([]uint8, 16)
1863 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1864 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1865 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1866 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1867 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1868
1869 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1870 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1871 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1872 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1873 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1874
1875 // delete indication for the indicated Filter
1876 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1877 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1878
1879 meParams := me.ParamData{
1880 EntityID: oFsm.evtocdID,
1881 Attributes: me.AttributeValueMap{
1882 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1883 },
1884 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001885 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001886 oFsm.pAdaptFsm.commChan, meParams)
1887 //accept also nil as (error) return value for writing to LastTx
1888 // - this avoids misinterpretation of new received OMCI messages
1889 oFsm.pLastTxMeInstance = meInstance
1890
1891 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001892 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001893 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001894 logger.Errorw(ctx, "Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001895 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1896 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1897 return
1898 }
1899 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001900 // VOL-3685
1901 // NOTE: With ALPHA ONUs it was seen that just resetting a particular entry in the EVTOCD table
1902 // and re-configuring a new entry would not work. The old entry is removed and new entry is created
1903 // indeed, but the traffic landing upstream would carry old vlan sometimes.
1904 // This is only a WORKAROUND which basically deletes the entire EVTOCD ME and re-creates it again
1905 // later when the flow is being re-installed.
1906 // Of course this is applicable to case only where single service (or single tcont) is in use and
1907 // there is only one service vlan (oFsm.acceptIncrementalEvtoOption is false in this case).
1908 // Interstingly this problem has not been observed in multi-tcont (or multi-service) scenario (in
1909 // which case the oFsm.acceptIncrementalEvtoOption is set to true).
1910 if oFsm.configuredUniFlow == 0 && !oFsm.acceptIncrementalEvtoOption {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001911 logger.Debugw(ctx, "UniVlanConfigFsm Tx Remove::EVTOCD", log.Fields{"device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001912 // When there are no more EVTOCD vlan configurations on the ONU and acceptIncrementalEvtoOption
1913 // is not enabled, delete the EVTOCD ME.
mpagenko01e726e2020-10-23 09:45:29 +00001914 meParams := me.ParamData{
1915 EntityID: oFsm.evtocdID,
mpagenko01e726e2020-10-23 09:45:29 +00001916 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001917 meInstance := oFsm.pOmciCC.sendDeleteEvtocd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001918 oFsm.pAdaptFsm.commChan, meParams)
1919 //accept also nil as (error) return value for writing to LastTx
1920 // - this avoids misinterpretation of new received OMCI messages
1921 oFsm.pLastTxMeInstance = meInstance
1922
1923 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001924 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001925 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001926 logger.Errorw(ctx, "Evtocd delete rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001927 log.Fields{"device-id": oFsm.deviceID})
1928 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1929 return
1930 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001931 } else {
1932 // NOTE : We should ideally never ether this section when oFsm.acceptIncrementalEvtoOption is set to false
1933 // This is true for only ATT/DT workflow
dbainbri4d3a0dc2020-12-02 00:33:42 +00001934 logger.Debugw(ctx, "UniVlanConfigFsm: Remove EVTOCD set operation",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001935 log.Fields{"configured-flow": oFsm.configuredUniFlow, "incremental-evto": oFsm.acceptIncrementalEvtoOption})
1936 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1937 { // just for local var's
1938 // this defines stacking scenario: untagged->singletagged
1939 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1940 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1941 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1942 // delete now assumes there is only one such rule!
dbainbri4d3a0dc2020-12-02 00:33:42 +00001943 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001944 "device-id": oFsm.deviceID})
1945 sliceEvtocdRule := make([]uint8, 16)
1946 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1947 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1948 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1949 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1950 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
mpagenko01e726e2020-10-23 09:45:29 +00001951
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001952 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1953 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1954 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1955 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1956 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
mpagenko01e726e2020-10-23 09:45:29 +00001957
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001958 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1959 0<<cTreatTTROffset| // Do not pop any tags
1960 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1961 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1962 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
mpagenko01e726e2020-10-23 09:45:29 +00001963
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001964 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1965 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1966 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1967 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
mpagenko01e726e2020-10-23 09:45:29 +00001968
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001969 meParams := me.ParamData{
1970 EntityID: oFsm.evtocdID,
1971 Attributes: me.AttributeValueMap{
1972 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1973 },
1974 }
1975 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1976 oFsm.pAdaptFsm.commChan, meParams)
1977 //accept also nil as (error) return value for writing to LastTx
1978 // - this avoids misinterpretation of new received OMCI messages
1979 oFsm.pLastTxMeInstance = meInstance
1980
1981 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001982 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001983 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001984 logger.Errorw(ctx, "Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001985 log.Fields{"device-id": oFsm.deviceID})
1986 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1987 return
1988 }
1989 } // just for local var's
1990 { // just for local var's
1991 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001992 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001993 "device-id": oFsm.deviceID})
1994 sliceEvtocdRule := make([]uint8, 16)
1995 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1996 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1997 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1998 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1999 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
2000
2001 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
2002 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
2003 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
2004 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
2005 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
2006
2007 // delete indication for the indicated Filter
2008 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
2009 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
2010
2011 meParams := me.ParamData{
2012 EntityID: oFsm.evtocdID,
2013 Attributes: me.AttributeValueMap{
2014 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
2015 },
2016 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00002017 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002018 oFsm.pAdaptFsm.commChan, meParams)
2019 //accept also nil as (error) return value for writing to LastTx
2020 // - this avoids misinterpretation of new received OMCI messages
2021 oFsm.pLastTxMeInstance = meInstance
2022
2023 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002024 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002025 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002026 logger.Errorw(ctx, "Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002027 log.Fields{"device-id": oFsm.deviceID})
2028 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
2029 return
2030 }
mpagenko01e726e2020-10-23 09:45:29 +00002031 }
2032 } //just for local var's
2033 }
2034 }
2035
mpagenkofc4f56e2020-11-04 17:17:49 +00002036 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00002037 logger.Debugw(ctx, "EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra26a40922021-01-29 17:14:34 -08002038 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone, aRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00002039}
2040
dbainbri4d3a0dc2020-12-02 00:33:42 +00002041func (oFsm *UniVlanConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenkodff5dda2020-08-28 11:52:01 +00002042 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05302043 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00002044 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00002045 // logger.Infow(ctx,"LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00002046 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
dbainbri4d3a0dc2020-12-02 00:33:42 +00002047 logger.Warnw(ctx, "UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002048 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002049 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05302050 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002051 logger.Debug(ctx, "UniVlanConfigFsm multi entity response received")
mpagenkodff5dda2020-08-28 11:52:01 +00002052 return nil
2053 }
2054 // should not happen so far
dbainbri4d3a0dc2020-12-02 00:33:42 +00002055 logger.Warnw(ctx, "UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002056 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002057 }
2058}
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002059
mpagenko551a4d42020-12-08 18:09:20 +00002060func (oFsm *UniVlanConfigFsm) performSettingMulticastME(ctx context.Context, tpID uint8, multicastGemPortID uint16, vlanID uint32) error {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002061 logger.Debugw(ctx, "Setting Multicast MEs", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002062 "multicastGemPortID": multicastGemPortID, "vlanID": vlanID})
dbainbri4d3a0dc2020-12-02 00:33:42 +00002063 errCreateMOP := oFsm.performCreatingMulticastOperationProfile(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002064 if errCreateMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002065 logger.Errorw(ctx, "MulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002066 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002067 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002068 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMOP)
2069 }
2070
dbainbri4d3a0dc2020-12-02 00:33:42 +00002071 errSettingMOP := oFsm.performSettingMulticastOperationProfile(ctx, multicastGemPortID, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002072 if errSettingMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002073 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002074 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002075 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002076 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errSettingMOP)
2077 }
2078
dbainbri4d3a0dc2020-12-02 00:33:42 +00002079 errCreateMSCI := oFsm.performCreatingMulticastSubscriberConfigInfo(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002080 if errCreateMSCI != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002081 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002082 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002083 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002084 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMSCI)
2085 }
2086
2087 meParams := me.ParamData{
2088 EntityID: macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2089 Attributes: me.AttributeValueMap{
2090 "BridgeIdPointer": macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2091 "PortNum": 0xf0, //fixed unique ANI side indication
2092 "TpType": 6, //MCGemIWTP
2093 "TpPointer": multicastGemPortID,
2094 },
2095 }
2096 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
2097 oFsm.pAdaptFsm.commChan, meParams)
2098 //accept also nil as (error) return value for writing to LastTx
2099 // - this avoids misinterpretation of new received OMCI messages
2100 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002101 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002102 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002103 logger.Errorw(ctx, "CreateMBPConfigData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002104 log.Fields{"device-id": oFsm.deviceID, "MBPConfigDataID": macBridgeServiceProfileEID})
mpagenko9a304ea2020-12-16 15:54:01 +00002105 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002106 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, err)
2107 }
2108
2109 // ==> Start creating VTFD for mcast vlan
2110
2111 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
2112 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
2113 mcastVtfdID := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
2114
dbainbri4d3a0dc2020-12-02 00:33:42 +00002115 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD for mcast", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002116 "EntitytId": strconv.FormatInt(int64(mcastVtfdID), 16), "mcastVlanID": vlanID,
2117 "in state": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
2118 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
2119
2120 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
2121 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
2122 // new vlan associated with a different TP.
2123 vtfdFilterList[0] = uint16(vlanID)
2124
2125 meParams = me.ParamData{
2126 EntityID: mcastVtfdID,
2127 Attributes: me.AttributeValueMap{
2128 "VlanFilterList": vtfdFilterList,
2129 "ForwardOperation": uint8(0x10), //VID investigation
2130 "NumberOfEntries": oFsm.numVlanFilterEntries,
2131 },
2132 }
2133 meInstance = oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
2134 oFsm.pAdaptFsm.commChan, meParams)
2135 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002136 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002137 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002138 logger.Errorw(ctx, "CreateMcastVlanFilterData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002139 log.Fields{"device-id": oFsm.deviceID, "mcastVtfdID": mcastVtfdID})
mpagenko9a304ea2020-12-16 15:54:01 +00002140 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002141 return fmt.Errorf("createMcastVlanFilterData responseError %s, error %s", oFsm.deviceID, err)
2142 }
2143
2144 return nil
2145}
2146
dbainbri4d3a0dc2020-12-02 00:33:42 +00002147func (oFsm *UniVlanConfigFsm) performCreatingMulticastSubscriberConfigInfo(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002148 instID, err := oFsm.pDeviceHandler.getUniPortMEEntityID(oFsm.pOnuUniPort.portNo)
2149 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002150 logger.Errorw(ctx, "error fetching uni port me instance",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002151 log.Fields{"device-id": oFsm.deviceID, "portNo": oFsm.pOnuUniPort.portNo})
2152 return err
2153 }
2154 meParams := me.ParamData{
2155 EntityID: instID,
2156 Attributes: me.AttributeValueMap{
2157 "MeType": 0,
2158 //Direct reference to the Operation profile
2159 //TODO ANI side used on UNI side, not the clearest option.
2160 "MulticastOperationsProfilePointer": macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo),
2161 },
2162 }
2163 meInstance := oFsm.pOmciCC.sendCreateMulticastSubConfigInfoVar(context.TODO(), ConstDefaultOmciTimeout, true,
2164 oFsm.pAdaptFsm.commChan, meParams)
2165 //accept also nil as (error) return value for writing to LastTx
2166 // - this avoids misinterpretation of new received OMCI messages
2167 oFsm.pLastTxMeInstance = meInstance
2168 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002169 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002170 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002171 logger.Errorw(ctx, "CreateMulticastSubConfigInfo create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002172 log.Fields{"device-id": oFsm.deviceID, "MulticastSubConfigInfo": instID})
2173 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s", oFsm.deviceID)
2174 }
2175 return nil
2176}
2177
dbainbri4d3a0dc2020-12-02 00:33:42 +00002178func (oFsm *UniVlanConfigFsm) performCreatingMulticastOperationProfile(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002179 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2180 meParams := me.ParamData{
2181 EntityID: instID,
2182 Attributes: me.AttributeValueMap{
2183 "IgmpVersion": 2,
2184 "IgmpFunction": 0,
2185 //0 means false
2186 "ImmediateLeave": 0,
2187 "Robustness": 2,
2188 "QuerierIp": 0,
2189 "QueryInterval": 125,
2190 "QuerierMaxResponseTime": 100,
2191 "LastMemberResponseTime": 10,
2192 //0 means false
2193 "UnauthorizedJoinBehaviour": 0,
2194 },
2195 }
2196 meInstance := oFsm.pOmciCC.sendCreateMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2197 oFsm.pAdaptFsm.commChan, meParams)
2198 //accept also nil as (error) return value for writing to LastTx
2199 // - this avoids misinterpretation of new received OMCI messages
2200 oFsm.pLastTxMeInstance = meInstance
2201 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002202 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002203 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002204 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002205 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2206 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2207 }
2208 return nil
2209}
2210
dbainbri4d3a0dc2020-12-02 00:33:42 +00002211func (oFsm *UniVlanConfigFsm) performSettingMulticastOperationProfile(ctx context.Context, multicastGemPortID uint16, vlanID uint32) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002212 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2213 //TODO check that this is correct
2214 // Table control
2215 //setCtrl = 1
2216 //rowPartId = 0
2217 //test = 0
2218 //rowKey = 0
2219 tableCtrlStr := "0100000000000000"
2220 tableCtrl := AsByteSlice(tableCtrlStr)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002221 dynamicAccessCL := make([]uint8, 24)
2222 copy(dynamicAccessCL, tableCtrl)
2223 //Multicast GemPortId
2224 binary.BigEndian.PutUint16(dynamicAccessCL[2:], multicastGemPortID)
2225 // python version waits for installation of flows, see line 723 onward of
2226 // brcm_openomci_onu_handler.py
2227 binary.BigEndian.PutUint16(dynamicAccessCL[4:], uint16(vlanID))
2228 //Source IP all to 0
2229 binary.BigEndian.PutUint32(dynamicAccessCL[6:], IPToInt32(net.IPv4(0, 0, 0, 0)))
2230 //TODO start and end are hardcoded, get from TP
2231 // Destination IP address start of range
2232 binary.BigEndian.PutUint32(dynamicAccessCL[10:], IPToInt32(net.IPv4(225, 0, 0, 0)))
2233 // Destination IP address end of range
2234 binary.BigEndian.PutUint32(dynamicAccessCL[14:], IPToInt32(net.IPv4(239, 255, 255, 255)))
2235 //imputed group bandwidth
2236 binary.BigEndian.PutUint16(dynamicAccessCL[18:], 0)
2237
2238 meParams := me.ParamData{
2239 EntityID: instID,
2240 Attributes: me.AttributeValueMap{
2241 "DynamicAccessControlListTable": dynamicAccessCL,
2242 },
2243 }
2244 meInstance := oFsm.pOmciCC.sendSetMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2245 oFsm.pAdaptFsm.commChan, meParams)
2246 //accept also nil as (error) return value for writing to LastTx
2247 // - this avoids misinterpretation of new received OMCI messages
2248 oFsm.pLastTxMeInstance = meInstance
2249 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002250 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002251 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002252 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002253 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2254 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2255 }
2256 return nil
2257}
Girish Gowdra26a40922021-01-29 17:14:34 -08002258
2259// IsFlowRemovePending returns true if there are pending flows to remove, else false.
2260func (oFsm *UniVlanConfigFsm) IsFlowRemovePending() bool {
2261 oFsm.mutexFlowParams.RLock()
2262 defer oFsm.mutexFlowParams.RUnlock()
2263 return len(oFsm.uniRemoveFlowsSlice) > 0
2264}