blob: b8605e041d6d0f298903ff133dc4941543877175 [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"
mpagenkodff5dda2020-08-28 11:52:01 +000024 "strconv"
Holger Hildebrandt394c5522020-09-11 11:23:01 +000025 "sync"
mpagenkodff5dda2020-08-28 11:52:01 +000026 "time"
27
mpagenko01e726e2020-10-23 09:45:29 +000028 gp "github.com/google/gopacket"
mpagenkodff5dda2020-08-28 11:52:01 +000029 "github.com/looplab/fsm"
30 "github.com/opencord/omci-lib-go"
31 me "github.com/opencord/omci-lib-go/generated"
32 "github.com/opencord/voltha-lib-go/v3/pkg/log"
33 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
34)
35
36const (
37 // internal predefined values
38 cDefaultDownstreamMode = 0
39 cDefaultTpid = 0x8100
mpagenko01e726e2020-10-23 09:45:29 +000040 cVtfdTableSize = 12 //as per G.988
41 cMaxAllowedFlows = cVtfdTableSize //which might be under discussion, for the moment connected to limit of VLAN's within VTFD
mpagenkodff5dda2020-08-28 11:52:01 +000042)
43
44const (
45 // bit mask offsets for EVTOCD VlanTaggingOperationTable related to 32 bits (4 bytes)
46 cFilterPrioOffset = 28
47 cFilterVidOffset = 15
48 cFilterTpidOffset = 12
49 cFilterEtherTypeOffset = 0
50 cTreatTTROffset = 30
51 cTreatPrioOffset = 16
52 cTreatVidOffset = 3
53 cTreatTpidOffset = 0
54)
55const (
56 // byte offsets for EVTOCD VlanTaggingOperationTable related to overall 16 byte size with slice byte 0 as first Byte (MSB)
57 cFilterOuterOffset = 0
58 cFilterInnerOffset = 4
59 cTreatOuterOffset = 8
60 cTreatInnerOffset = 12
61)
62const (
63 // basic values used within EVTOCD VlanTaggingOperationTable in respect to their bitfields
64 cPrioIgnoreTag uint32 = 15
65 cPrioDefaultFilter uint32 = 14
66 cPrioDoNotFilter uint32 = 8
67 cDoNotFilterVid uint32 = 4096
68 cDoNotFilterTPID uint32 = 0
69 cDoNotFilterEtherType uint32 = 0
70 cDoNotAddPrio uint32 = 15
71 cCopyPrioFromInner uint32 = 8
Himani Chawla4d908332020-08-31 12:30:20 +053072 //cDontCarePrio uint32 = 0
mpagenkodff5dda2020-08-28 11:52:01 +000073 cDontCareVid uint32 = 0
74 cDontCareTpid uint32 = 0
75 cSetOutputTpidCopyDei uint32 = 4
76)
77
78const (
79 // events of config PON ANI port FSM
mpagenko01e726e2020-10-23 09:45:29 +000080 vlanEvStart = "vlanEvStart"
81 vlanEvWaitTechProf = "vlanEvWaitTechProf"
82 vlanEvContinueConfig = "vlanEvContinueConfig"
83 vlanEvStartConfig = "vlanEvStartConfig"
84 vlanEvRxConfigVtfd = "vlanEvRxConfigVtfd"
85 vlanEvRxConfigEvtocd = "vlanEvRxConfigEvtocd"
86 vlanEvIncrFlowConfig = "vlanEvIncrFlowConfig"
87 vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
88 vlanEvRemFlowDone = "vlanEvRemFlowDone"
89 vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
Holger Hildebrandt394c5522020-09-11 11:23:01 +000090 //vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
91 //vlanEvTimeoutMids = "vlanEvTimeoutMids"
Himani Chawla4d908332020-08-31 12:30:20 +053092 vlanEvReset = "vlanEvReset"
93 vlanEvRestart = "vlanEvRestart"
mpagenkodff5dda2020-08-28 11:52:01 +000094)
mpagenko01e726e2020-10-23 09:45:29 +000095
mpagenkodff5dda2020-08-28 11:52:01 +000096const (
97 // states of config PON ANI port FSM
98 vlanStDisabled = "vlanStDisabled"
99 vlanStStarting = "vlanStStarting"
100 vlanStWaitingTechProf = "vlanStWaitingTechProf"
101 vlanStConfigVtfd = "vlanStConfigVtfd"
102 vlanStConfigEvtocd = "vlanStConfigEvtocd"
103 vlanStConfigDone = "vlanStConfigDone"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000104 vlanStConfigIncrFlow = "vlanStConfigIncrFlow"
mpagenko01e726e2020-10-23 09:45:29 +0000105 vlanStRemoveFlow = "vlanStRemoveFlow"
mpagenkodff5dda2020-08-28 11:52:01 +0000106 vlanStCleanupDone = "vlanStCleanupDone"
107 vlanStResetting = "vlanStResetting"
108)
109
mpagenko01e726e2020-10-23 09:45:29 +0000110type uniVlanRuleParams struct {
111 TpID uint16 `json:"tp_id"`
112 MatchVid uint32 `json:"match_vid"` //use uint32 types for allowing immediate bitshifting
113 MatchPcp uint32 `json:"match_pcp"`
114 TagsToRemove uint32 `json:"tags_to_remove"`
115 SetVid uint32 `json:"set_vid"`
116 SetPcp uint32 `json:"set_pcp"`
117}
118
119type uniVlanFlowParams struct {
120 CookieSlice []uint64 `json:"cookie_slice"`
121 VlanRuleParams uniVlanRuleParams `json:"vlan_rule_params"`
122}
123
124type uniRemoveVlanFlowParams struct {
125 cookie uint64 //just the last cookie valid for removal
126 vlanRuleParams uniVlanRuleParams
127}
128
mpagenkodff5dda2020-08-28 11:52:01 +0000129//UniVlanConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
130type UniVlanConfigFsm struct {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530131 pDeviceHandler *deviceHandler
mpagenko01e726e2020-10-23 09:45:29 +0000132 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530133 pOmciCC *omciCC
134 pOnuUniPort *onuUniPort
135 pUniTechProf *onuUniTechProf
136 pOnuDB *onuDeviceDB
mpagenkodff5dda2020-08-28 11:52:01 +0000137 techProfileID uint16
138 requestEvent OnuDeviceEvent
139 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
140 pAdaptFsm *AdapterFsm
141 acceptIncrementalEvtoOption bool
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000142 mutexFlowParams sync.Mutex
mpagenko01e726e2020-10-23 09:45:29 +0000143 uniVlanFlowParamsSlice []uniVlanFlowParams
144 uniRemoveFlowsSlice []uniRemoveVlanFlowParams
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000145 numUniFlows uint8 // expected number of flows should be less than 12
146 configuredUniFlow uint8
mpagenko01e726e2020-10-23 09:45:29 +0000147 numRemoveFlows uint8
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000148 numVlanFilterEntries uint8
mpagenko01e726e2020-10-23 09:45:29 +0000149 vlanFilterList [cVtfdTableSize]uint16
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000150 vtfdID uint16
151 evtocdID uint16
mpagenko01e726e2020-10-23 09:45:29 +0000152 pLastTxMeInstance *me.ManagedEntity
mpagenkodff5dda2020-08-28 11:52:01 +0000153}
154
mpagenko01e726e2020-10-23 09:45:29 +0000155//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
156// of ONU UNI ports via OMCI
157func NewUniVlanConfigFsm(apDeviceHandler *deviceHandler, apDevOmciCC *omciCC, apUniPort *onuUniPort,
158 apUniTechProf *onuUniTechProf, apOnuDB *onuDeviceDB, aTechProfileID uint16,
159 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message, aAcceptIncrementalEvto bool,
160 aCookieSlice []uint64, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) *UniVlanConfigFsm {
mpagenkodff5dda2020-08-28 11:52:01 +0000161 instFsm := &UniVlanConfigFsm{
162 pDeviceHandler: apDeviceHandler,
mpagenko01e726e2020-10-23 09:45:29 +0000163 deviceID: apDeviceHandler.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000164 pOmciCC: apDevOmciCC,
165 pOnuUniPort: apUniPort,
166 pUniTechProf: apUniTechProf,
167 pOnuDB: apOnuDB,
168 techProfileID: aTechProfileID,
169 requestEvent: aRequestEvent,
170 acceptIncrementalEvtoOption: aAcceptIncrementalEvto,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000171 numUniFlows: 0,
172 configuredUniFlow: 0,
mpagenko01e726e2020-10-23 09:45:29 +0000173 numRemoveFlows: 0,
mpagenkodff5dda2020-08-28 11:52:01 +0000174 }
175
mpagenko01e726e2020-10-23 09:45:29 +0000176 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenkodff5dda2020-08-28 11:52:01 +0000177 if instFsm.pAdaptFsm == nil {
178 logger.Errorw("UniVlanConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000179 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000180 return nil
181 }
mpagenkodff5dda2020-08-28 11:52:01 +0000182 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
183 vlanStDisabled,
184 fsm.Events{
185 {Name: vlanEvStart, Src: []string{vlanStDisabled}, Dst: vlanStStarting},
186 {Name: vlanEvWaitTechProf, Src: []string{vlanStStarting}, Dst: vlanStWaitingTechProf},
187 {Name: vlanEvContinueConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigVtfd},
188 {Name: vlanEvStartConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigVtfd},
189 {Name: vlanEvRxConfigVtfd, Src: []string{vlanStConfigVtfd}, Dst: vlanStConfigEvtocd},
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000190 {Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
191 Dst: vlanStConfigDone},
192 {Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStConfigIncrFlow},
mpagenko01e726e2020-10-23 09:45:29 +0000193 {Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
194 {Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
195 {Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000196 /*
197 {Name: vlanEvTimeoutSimple, Src: []string{
198 vlanStCreatingDot1PMapper, vlanStCreatingMBPCD, vlanStSettingTconts, vlanStSettingDot1PMapper}, Dst: vlanStStarting},
199 {Name: vlanEvTimeoutMids, Src: []string{
200 vlanStCreatingGemNCTPs, vlanStCreatingGemIWs, vlanStSettingPQs}, Dst: vlanStStarting},
201 */
202 // exceptional treatment for all states except vlanStResetting
203 {Name: vlanEvReset, Src: []string{vlanStStarting, vlanStWaitingTechProf,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000204 vlanStConfigVtfd, vlanStConfigEvtocd, vlanStConfigDone, vlanStConfigIncrFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000205 vlanStRemoveFlow, vlanStCleanupDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000206 Dst: vlanStResetting},
207 // the only way to get to resource-cleared disabled state again is via "resseting"
208 {Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
209 },
mpagenkodff5dda2020-08-28 11:52:01 +0000210 fsm.Callbacks{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000211 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
212 ("enter_" + vlanStStarting): func(e *fsm.Event) { instFsm.enterConfigStarting(e) },
213 ("enter_" + vlanStConfigVtfd): func(e *fsm.Event) { instFsm.enterConfigVtfd(e) },
214 ("enter_" + vlanStConfigEvtocd): func(e *fsm.Event) { instFsm.enterConfigEvtocd(e) },
215 ("enter_" + vlanStConfigDone): func(e *fsm.Event) { instFsm.enterVlanConfigDone(e) },
216 ("enter_" + vlanStConfigIncrFlow): func(e *fsm.Event) { instFsm.enterConfigIncrFlow(e) },
mpagenko01e726e2020-10-23 09:45:29 +0000217 ("enter_" + vlanStRemoveFlow): func(e *fsm.Event) { instFsm.enterRemoveFlow(e) },
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000218 ("enter_" + vlanStCleanupDone): func(e *fsm.Event) { instFsm.enterVlanCleanupDone(e) },
219 ("enter_" + vlanStResetting): func(e *fsm.Event) { instFsm.enterResetting(e) },
220 ("enter_" + vlanStDisabled): func(e *fsm.Event) { instFsm.enterDisabled(e) },
mpagenkodff5dda2020-08-28 11:52:01 +0000221 },
222 )
223 if instFsm.pAdaptFsm.pFsm == nil {
224 logger.Errorw("UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000225 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000226 return nil
227 }
228
mpagenko01e726e2020-10-23 09:45:29 +0000229 _ = instFsm.initUniFlowParams(aTechProfileID, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000230
mpagenko01e726e2020-10-23 09:45:29 +0000231 logger.Infow("UniVlanConfigFsm created", log.Fields{"device-id": instFsm.deviceID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000232 "accIncrEvto": instFsm.acceptIncrementalEvtoOption})
mpagenkodff5dda2020-08-28 11:52:01 +0000233 return instFsm
234}
235
mpagenko01e726e2020-10-23 09:45:29 +0000236//initUniFlowParams is a simplified form of SetUniFlowParams() used for first flow parameters configuration
237func (oFsm *UniVlanConfigFsm) initUniFlowParams(aTpID uint16, aCookieSlice []uint64,
238 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
239 loRuleParams := uniVlanRuleParams{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000240 TpID: aTpID,
241 MatchVid: uint32(aMatchVlan),
242 SetVid: uint32(aSetVlan),
243 SetPcp: uint32(aSetPcp),
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000244 }
245 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
mpagenko01e726e2020-10-23 09:45:29 +0000246 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
247 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000248
mpagenko01e726e2020-10-23 09:45:29 +0000249 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000250 //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 +0000251 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000252 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
253 } else {
254 if !oFsm.acceptIncrementalEvtoOption {
255 //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 +0000256 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000257 }
258 }
259
mpagenko01e726e2020-10-23 09:45:29 +0000260 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000261 // no prio/vid filtering requested
mpagenko01e726e2020-10-23 09:45:29 +0000262 loRuleParams.TagsToRemove = 0 //no tag pop action
263 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
264 if loRuleParams.SetPcp == cCopyPrioFromInner {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000265 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
266 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
267 // might collide with NoMatchVid/CopyPrio(/setVid) setting
268 // this was some precondition setting taken over from py adapter ..
mpagenko01e726e2020-10-23 09:45:29 +0000269 loRuleParams.SetPcp = 0
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000270 }
271 }
mpagenko01e726e2020-10-23 09:45:29 +0000272
273 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
274 loFlowParams.CookieSlice = make([]uint64, 0)
275 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
276
277 //no mutex protection is required for initial access and adding the first flow is always possible
278 oFsm.uniVlanFlowParamsSlice = make([]uniVlanFlowParams, 0)
279 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
280 logger.Debugw("first UniVlanConfigFsm flow added", log.Fields{
281 "Cookies": oFsm.uniVlanFlowParamsSlice[0].CookieSlice,
282 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
283 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
284 "SetPcp": loRuleParams.SetPcp,
285 "device-id": oFsm.deviceID})
286 oFsm.numUniFlows = 1
287 oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
288
289 //permanently store flow config for reconcile case
290 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID,
291 &oFsm.uniVlanFlowParamsSlice); err != nil {
292 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
293 return err
294 }
295
296 return nil
297}
298
299//SetUniFlowParams verifies on existence of flow parameters to be configured,
300// optionally udates the cookie list or appends a new flow if there is space
301// if possible the FSM is trigggerd to start with the processing
302func (oFsm *UniVlanConfigFsm) SetUniFlowParams(aTpID uint16, aCookieSlice []uint64,
303 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
304 loRuleParams := uniVlanRuleParams{
305 TpID: aTpID,
306 MatchVid: uint32(aMatchVlan),
307 SetVid: uint32(aSetVlan),
308 SetPcp: uint32(aSetPcp),
309 }
310 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
311 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
312 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
313
314 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
315 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
316 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
317 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
318 } else {
319 if !oFsm.acceptIncrementalEvtoOption {
320 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
321 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
322 }
323 }
324
325 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
326 // no prio/vid filtering requested
327 loRuleParams.TagsToRemove = 0 //no tag pop action
328 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
329 if loRuleParams.SetPcp == cCopyPrioFromInner {
330 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
331 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
332 // might collide with NoMatchVid/CopyPrio(/setVid) setting
333 // this was some precondition setting taken over from py adapter ..
334 loRuleParams.SetPcp = 0
335 }
336 }
337
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000338 flowEntryMatch := false
mpagenko01e726e2020-10-23 09:45:29 +0000339 flowCookieModify := false
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000340 //mutex protection is required for possible concurrent access to FSM members
341 oFsm.mutexFlowParams.Lock()
342 defer oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000343 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
344 //TODO: Verify if using e.g. hashes for the structures here for comparison may generate
345 // countable run time optimization (perhaps with including the hash in kvStore storage?)
346 if storedUniFlowParams.VlanRuleParams == loRuleParams {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000347 flowEntryMatch = true
mpagenko01e726e2020-10-23 09:45:29 +0000348 logger.Debugw("UniVlanConfigFsm flow setting - rule already exists", log.Fields{
349 "device-id": oFsm.deviceID})
350 var cookieMatch bool
351 for _, newCookie := range aCookieSlice { // for all cookies available in the arguments
352 cookieMatch = false
353 for _, cookie := range storedUniFlowParams.CookieSlice {
354 if cookie == newCookie {
355 logger.Debugw("UniVlanConfigFsm flow setting - and cookie already exists", log.Fields{
356 "device-id": oFsm.deviceID, "cookie": cookie})
357 cookieMatch = true
358 break //found new cookie - no further search for this requested cookie
359 }
360 }
361 if !cookieMatch {
362 logger.Debugw("UniVlanConfigFsm flow setting -adding new cookie", log.Fields{
363 "device-id": oFsm.deviceID, "cookie": newCookie})
364 //as range works with copies of the slice we have to write to the original slice!!
365 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
366 newCookie)
367 flowCookieModify = true
368 }
369 } //for all new cookies
370 break // found rule - no further rule search
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000371 }
372 }
mpagenko01e726e2020-10-23 09:45:29 +0000373 if !flowEntryMatch { //it is a new rule
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000374 if oFsm.numUniFlows < cMaxAllowedFlows {
mpagenko01e726e2020-10-23 09:45:29 +0000375 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
376 loFlowParams.CookieSlice = make([]uint64, 0)
377 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
378 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
379 logger.Debugw("UniVlanConfigFsm flow add", log.Fields{
380 "Cookies": oFsm.uniVlanFlowParamsSlice[oFsm.numUniFlows].CookieSlice,
381 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
382 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
383 "SetPcp": loRuleParams.SetPcp, "numberofFlows": (oFsm.numUniFlows + 1),
384 "device-id": oFsm.deviceID})
385
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000386 oFsm.numUniFlows++
mpagenko01e726e2020-10-23 09:45:29 +0000387 // note: theoretical it would be possible to clear the same rule from the remove slice
388 // (for entries that have not yet been started with removal)
389 // but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
390 // 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 +0000391
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000392 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
393 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
394 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
395 // calling some FSM event must be decoupled
396 go func(a_pBaseFsm *fsm.FSM) {
397 _ = a_pBaseFsm.Event(vlanEvIncrFlowConfig)
398 }(pConfigVlanStateBaseFsm)
mpagenko01e726e2020-10-23 09:45:29 +0000399 } // if not in the appropriate state a new entry will be automatically considered later
400 // when the configDone state is reached
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000401 } else {
402 logger.Errorw("UniVlanConfigFsm flow limit exceeded", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000403 "device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
404 return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
405 }
406 } //new flow
407
408 if !flowEntryMatch || flowCookieModify { // some change was done to the flow entries
409 //permanently store flow config for reconcile case
410 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
411 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
412 return err
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000413 }
414 }
415 return nil
416}
417
mpagenko01e726e2020-10-23 09:45:29 +0000418//RemoveUniFlowParams verifies on existence of flow cookie,
419// if found removes cookie from flow cookie list and if this is empty
420// initiates removal of the flow related configuration from the ONU (via OMCI)
421func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(aCookie uint64) error {
422 flowCookieMatch := false
423 //mutex protection is required for possible concurrent access to FSM members
424 oFsm.mutexFlowParams.Lock()
425 defer oFsm.mutexFlowParams.Unlock()
426 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
427 for i, cookie := range storedUniFlowParams.CookieSlice {
428 if cookie == aCookie {
429 logger.Debugw("UniVlanConfigFsm flow removal - cookie found", log.Fields{
430 "device-id": oFsm.deviceID, "cookie": cookie})
431 flowCookieMatch = true
432
433 //remove the cookie from the cookie slice and verify it is getting empty
434 if len(storedUniFlowParams.CookieSlice) == 1 {
435 logger.Debugw("UniVlanConfigFsm flow removal - full flow removal", log.Fields{
436 "device-id": oFsm.deviceID})
437 oFsm.numUniFlows--
438
439 //create a new element for the removeVlanFlow slice
440 loRemoveParams := uniRemoveVlanFlowParams{
441 vlanRuleParams: storedUniFlowParams.VlanRuleParams,
442 cookie: storedUniFlowParams.CookieSlice[0],
443 }
444 oFsm.uniRemoveFlowsSlice = append(oFsm.uniRemoveFlowsSlice, loRemoveParams)
445
446 //and remove the actual element from the addVlanFlow slice
447 // oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = nil //automatically done by garbage collector
448 if len(oFsm.uniVlanFlowParamsSlice) <= 1 {
449 oFsm.numUniFlows = 0 //no more flows
450 oFsm.configuredUniFlow = 0 //no more flows configured
451 oFsm.uniVlanFlowParamsSlice = nil //reset the slice
452 logger.Debugw("UniVlanConfigFsm flow removal - no more flows", log.Fields{
453 "device-id": oFsm.deviceID})
454 } else {
455 oFsm.numUniFlows--
456 if oFsm.configuredUniFlow > 0 {
457 oFsm.configuredUniFlow--
458 //TODO!! might be needed to consider still outstanding configure requests ..
459 // so a flow at removal might still not be configured !?!
460 }
461 //cut off the requested flow by slicing out this element
462 oFsm.uniVlanFlowParamsSlice = append(
463 oFsm.uniVlanFlowParamsSlice[:flow], oFsm.uniVlanFlowParamsSlice[flow+1:]...)
464 logger.Debugw("UniVlanConfigFsm flow removal - specific flow removed from data", log.Fields{
465 "device-id": oFsm.deviceID})
466 }
467 //trigger the FSM to remove the relevant rule
468 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
469 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
470 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
471 // calling some FSM event must be decoupled
472 go func(a_pBaseFsm *fsm.FSM) {
473 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
474 }(pConfigVlanStateBaseFsm)
475 } // if not in the appropriate state a new entry will be automatically considered later
476 // when the configDone state is reached
477 } else {
478 logger.Debugw("UniVlanConfigFsm flow removal - flow persists with other cookies", log.Fields{
479 "device-id": oFsm.deviceID})
480 //cut off the requested cookie by slicing out this element
481 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
482 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
483 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
484 logger.Debugw("UniVlanConfigFsm flow removal - still valid cookies for this flow", log.Fields{
485 "device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
486 }
487
488 //permanently store the modified flow config for reconcile case
489 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
490 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
491 return err
492 }
493
494 break //found the cookie - no further search for this requested cookie
495 }
496 }
497 if flowCookieMatch { //cookie already found: no need for further search in other flows
498 break
499 }
500 } //search all flows
501 if !flowCookieMatch { //some cookie remove-request for a cookie that does not exist in the FSM data
502 logger.Warnw("UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
503 "device-id": oFsm.deviceID, "remove-cookie": aCookie})
504 // but accept the request with success as no such cookie (flow) does exist
505 return nil
506 } //unknown cookie
507
508 return nil
509}
510
mpagenkodff5dda2020-08-28 11:52:01 +0000511func (oFsm *UniVlanConfigFsm) enterConfigStarting(e *fsm.Event) {
512 logger.Debugw("UniVlanConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000513 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000514
515 // this FSM is not intended for re-start, needs always new creation for a new run
mpagenko01e726e2020-10-23 09:45:29 +0000516 // (self-destroying - compare enterDisabled())
mpagenkodff5dda2020-08-28 11:52:01 +0000517 oFsm.omciMIdsResponseReceived = make(chan bool)
518 // start go routine for processing of LockState messages
519 go oFsm.processOmciVlanMessages()
520 //let the state machine run forward from here directly
521 pConfigVlanStateAFsm := oFsm.pAdaptFsm
522 if pConfigVlanStateAFsm != nil {
523 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
524 go func(a_pAFsm *AdapterFsm) {
525 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
526 //stick to pythonAdapter numbering scheme
Himani Chawla26e555c2020-08-31 12:30:20 +0530527 oFsm.vtfdID = macBridgePortAniEID + oFsm.pOnuUniPort.entityID + oFsm.techProfileID
mpagenkodff5dda2020-08-28 11:52:01 +0000528 //cmp also usage in EVTOCDE create in omci_cc
529 oFsm.evtocdID = macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
530
Himani Chawla26e555c2020-08-31 12:30:20 +0530531 if oFsm.pUniTechProf.getTechProfileDone(oFsm.pOnuUniPort.uniID, oFsm.techProfileID) {
mpagenkodff5dda2020-08-28 11:52:01 +0000532 // let the vlan processing begin
Himani Chawla4d908332020-08-31 12:30:20 +0530533 _ = a_pAFsm.pFsm.Event(vlanEvStartConfig)
mpagenkodff5dda2020-08-28 11:52:01 +0000534 } else {
535 // set to waiting for Techprofile
Himani Chawla4d908332020-08-31 12:30:20 +0530536 _ = a_pAFsm.pFsm.Event(vlanEvWaitTechProf)
mpagenkodff5dda2020-08-28 11:52:01 +0000537 }
538 }
539 }(pConfigVlanStateAFsm)
540 }
541}
542
543func (oFsm *UniVlanConfigFsm) enterConfigVtfd(e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000544 //mutex protection is required for possible concurrent access to FSM members
545 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +0000546 if oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000547 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000548 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +0000549 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000550 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000551 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
552 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
553 pConfigVlanStateAFsm := oFsm.pAdaptFsm
554 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530555 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000556 }(pConfigVlanStateAFsm)
557 } else {
558 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
559 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000560 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
561 // setVid is assumed to be masked already by the caller to 12 bit
562 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000563 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000564 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000565 vtfdFilterList[0] = oFsm.vlanFilterList[0]
566 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000567 meParams := me.ParamData{
568 EntityID: oFsm.vtfdID,
569 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000570 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
571 "ForwardOperation": uint8(0x10), //VID investigation
572 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000573 },
574 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000575 logger.Debugw("UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000576 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000577 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
578 oFsm.pAdaptFsm.commChan, meParams)
579 //accept also nil as (error) return value for writing to LastTx
580 // - this avoids misinterpretation of new received OMCI messages
581 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
582 // send shall return (dual format) error code that can be used here for immediate error treatment
583 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000584 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000585 }
586}
587
588func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(e *fsm.Event) {
589 logger.Debugw("UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000590 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000591 go oFsm.performConfigEvtocdEntries(0)
mpagenkodff5dda2020-08-28 11:52:01 +0000592}
593
594func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000595 logger.Debugw("UniVlanConfigFsm - checking on more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000596 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
597 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
598 if len(oFsm.uniRemoveFlowsSlice) > 0 {
599 //some further flows are to be removed, removal always starts with the first element
600 // calling some FSM event must be decoupled
601 go func(a_pBaseFsm *fsm.FSM) {
602 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
603 }(pConfigVlanStateBaseFsm)
604 return
605 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000606 if oFsm.numUniFlows > oFsm.configuredUniFlow {
607 //some further flows are to be configured
608 // calling some FSM event must be decoupled
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000609 go func(a_pBaseFsm *fsm.FSM) {
610 _ = a_pBaseFsm.Event(vlanEvIncrFlowConfig)
611 }(pConfigVlanStateBaseFsm)
612 return
613 }
614
615 logger.Debugw("UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000616 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000617 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
618 // state transition notification is checked in deviceHandler
mpagenkodff5dda2020-08-28 11:52:01 +0000619 if oFsm.pDeviceHandler != nil {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530620 oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
mpagenkodff5dda2020-08-28 11:52:01 +0000621 }
622}
623
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000624func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(e *fsm.Event) {
625 logger.Debugw("UniVlanConfigFsm - start config further incremental flow", log.Fields{
626 "in state": e.FSM.Current(), "recent flow-number": (oFsm.configuredUniFlow),
mpagenko01e726e2020-10-23 09:45:29 +0000627 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000628 oFsm.mutexFlowParams.Lock()
629
mpagenko01e726e2020-10-23 09:45:29 +0000630 if oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000631 // meaning transparent setup - no specific VTFD setting required
632 oFsm.mutexFlowParams.Unlock()
633 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000634 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000635 } else {
636 if oFsm.numVlanFilterEntries == 0 {
637 //no VTFD yet created
638 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
639 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000640 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
641 // setVid is assumed to be masked already by the caller to 12 bit
642 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000643 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000644 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000645 vtfdFilterList[0] = oFsm.vlanFilterList[0]
646 oFsm.numVlanFilterEntries = 1
647 meParams := me.ParamData{
648 EntityID: oFsm.vtfdID,
649 Attributes: me.AttributeValueMap{
650 "VlanFilterList": vtfdFilterList,
651 "ForwardOperation": uint8(0x10), //VID investigation
652 "NumberOfEntries": oFsm.numVlanFilterEntries,
653 },
654 }
655 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
656 oFsm.pAdaptFsm.commChan, meParams)
657 //accept also nil as (error) return value for writing to LastTx
658 // - this avoids misinterpretation of new received OMCI messages
659 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
660 // send shall return (dual format) error code that can be used here for immediate error treatment
661 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000662 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000663 } else {
664 //VTFD already exists - just modify by 'set'
665 //TODO!!: but only if the VID is not already present, skipped by now to test basic working
666 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
667 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000668 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000669 // setVid is assumed to be masked already by the caller to 12 bit
670 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko01e726e2020-10-23 09:45:29 +0000671 uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000672 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000673 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000674 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
675 vtfdFilterList[i] = oFsm.vlanFilterList[i]
676 }
677
678 oFsm.numVlanFilterEntries++
679 meParams := me.ParamData{
680 EntityID: oFsm.vtfdID,
681 Attributes: me.AttributeValueMap{
682 "VlanFilterList": vtfdFilterList,
683 "NumberOfEntries": oFsm.numVlanFilterEntries,
684 },
685 }
686 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
687 oFsm.pAdaptFsm.commChan, meParams)
688 //accept also nil as (error) return value for writing to LastTx
689 // - this avoids misinterpretation of new received OMCI messages
690 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
691 // send shall return (dual format) error code that can be used here for immediate error treatment
692 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000693 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000694 }
695 //verify response
696 err := oFsm.waitforOmciResponse()
697 if err != nil {
698 logger.Errorw("VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000699 log.Fields{"device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000700 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
701 return
702 }
703 }
704 go oFsm.performConfigEvtocdEntries(oFsm.configuredUniFlow)
705}
706
mpagenko01e726e2020-10-23 09:45:29 +0000707func (oFsm *UniVlanConfigFsm) enterRemoveFlow(e *fsm.Event) {
708 oFsm.mutexFlowParams.Lock()
709 logger.Debugw("UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
710 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
711 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000712
mpagenko01e726e2020-10-23 09:45:29 +0000713 loVlanEntryClear := uint8(0)
714 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
715 //shallow copy is sufficient as no reference variables are used within struct
716 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
717 oFsm.mutexFlowParams.Unlock()
718 logger.Debugw("UniVlanConfigFsm - remove-flow parameters are", log.Fields{
719 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
720 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
721 "device-id": oFsm.deviceID})
722
723 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
724 // meaning transparent setup - no specific VTFD setting required
725 logger.Debugw("UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
726 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
727 } else {
728 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
729 if oFsm.numVlanFilterEntries == 1 {
730 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
731 // so we can just delete the VTFD entry
732 logger.Debugw("UniVlanConfigFsm: VTFD delete (no more vlan filters)",
733 log.Fields{"current vlan list": oFsm.vlanFilterList,
734 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
735 loVlanEntryClear = 1 //full VlanFilter clear request
736 meInstance := oFsm.pOmciCC.sendDeleteVtfd(context.TODO(), ConstDefaultOmciTimeout, true,
737 oFsm.pAdaptFsm.commChan, oFsm.vtfdID)
738 oFsm.pLastTxMeInstance = meInstance
739 } else {
740 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
741 // by updating the VTFD per set command with new valid list
742 logger.Debugw("UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
743 log.Fields{"current vlan list": oFsm.vlanFilterList,
744 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
745 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
746 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
747 loVlanEntryRmPos = i
748 break //abort search
749 }
750 }
751 if loVlanEntryRmPos < cVtfdTableSize {
752 //valid entry was found - to be eclipsed
753 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
754 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
755 if i < loVlanEntryRmPos {
756 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
757 } else if i < (cVtfdTableSize - 1) {
758 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
759 } else {
760 vtfdFilterList[i] = 0 //set last byte if needed
761 }
762 }
763 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
764 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
765 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
766
767 meParams := me.ParamData{
768 EntityID: oFsm.vtfdID,
769 Attributes: me.AttributeValueMap{
770 "VlanFilterList": vtfdFilterList,
771 "NumberOfEntries": (oFsm.numVlanFilterEntries - 1), //one element less
772 },
773 }
774 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
775 oFsm.pAdaptFsm.commChan, meParams)
776 oFsm.pLastTxMeInstance = meInstance
777 } else {
778 logger.Warnw("UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
779 log.Fields{"device-id": oFsm.deviceID})
780 }
781 }
782 if loVlanEntryClear > 0 {
783 //waiting on response
784 err := oFsm.waitforOmciResponse()
785 if err != nil {
786 logger.Errorw("VTFD delete/reset failed, aborting VlanConfig FSM!",
787 log.Fields{"device-id": oFsm.deviceID})
788 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
789 return
790 }
791
792 if loVlanEntryClear == 1 {
793 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
794 oFsm.numVlanFilterEntries = 0
795 } else if loVlanEntryClear == 2 {
796 // new VlanFilterList should be one entry smaller now - copy from last configured entry
797 // this loop now includes the 0 element on previous last valid entry
798 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
799 oFsm.vlanFilterList[i] = vtfdFilterList[i]
800 }
801 oFsm.numVlanFilterEntries--
802 }
803 }
804 }
805
806 go oFsm.removeEvtocdEntries(loRuleParams)
mpagenkodff5dda2020-08-28 11:52:01 +0000807}
808
809func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000810 logger.Debugw("UniVlanConfigFsm - removing the removal data", log.Fields{
811 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000812
mpagenko01e726e2020-10-23 09:45:29 +0000813 oFsm.mutexFlowParams.Lock()
814 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
815 oFsm.uniRemoveFlowsSlice = nil //reset the slice
816 logger.Debugw("UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
817 "device-id": oFsm.deviceID})
818 } else {
819 //cut off the actual flow by slicing out the first element
820 oFsm.uniRemoveFlowsSlice = append(
821 oFsm.uniRemoveFlowsSlice[:0],
822 oFsm.uniRemoveFlowsSlice[1:]...)
823 logger.Debugw("UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
824 "device-id": oFsm.deviceID})
825 }
826 oFsm.mutexFlowParams.Unlock()
827
828 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +0000829 pConfigVlanStateAFsm := oFsm.pAdaptFsm
830 if pConfigVlanStateAFsm != nil {
831 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
832 go func(a_pAFsm *AdapterFsm) {
833 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +0000834 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +0000835 }
836 }(pConfigVlanStateAFsm)
837 }
838}
839
840func (oFsm *UniVlanConfigFsm) enterResetting(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000841 logger.Debugw("UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000842
843 pConfigVlanStateAFsm := oFsm.pAdaptFsm
844 if pConfigVlanStateAFsm != nil {
845 // abort running message processing
846 fsmAbortMsg := Message{
847 Type: TestMsg,
848 Data: TestMessage{
849 TestMessageVal: AbortMessageProcessing,
850 },
851 }
852 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
853
854 //try to restart the FSM to 'disabled', decouple event transfer
855 go func(a_pAFsm *AdapterFsm) {
856 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530857 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +0000858 }
859 }(pConfigVlanStateAFsm)
860 }
861}
862
863func (oFsm *UniVlanConfigFsm) enterDisabled(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000864 logger.Debugw("UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
865 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +0000866 if oFsm.pDeviceHandler != nil {
867 //request removal of 'reference' in the Handler (completely clear the FSM)
868 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(oFsm.pOnuUniPort)
869 }
870}
871
872func (oFsm *UniVlanConfigFsm) processOmciVlanMessages() { //ctx context.Context?
mpagenko01e726e2020-10-23 09:45:29 +0000873 logger.Debugw("Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000874loop:
875 for {
mpagenkodff5dda2020-08-28 11:52:01 +0000876 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +0000877 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000878 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +0530879 message, ok := <-oFsm.pAdaptFsm.commChan
880 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +0000881 logger.Info("UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530882 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
883 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
884 break loop
885 }
mpagenko01e726e2020-10-23 09:45:29 +0000886 logger.Debugw("UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +0530887
888 switch message.Type {
889 case TestMsg:
890 msg, _ := message.Data.(TestMessage)
891 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +0000892 logger.Infow("UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000893 break loop
894 }
mpagenko01e726e2020-10-23 09:45:29 +0000895 logger.Warnw("UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +0530896 case OMCI:
897 msg, _ := message.Data.(OmciMessage)
898 oFsm.handleOmciVlanConfigMessage(msg)
899 default:
mpagenko01e726e2020-10-23 09:45:29 +0000900 logger.Warn("UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +0530901 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +0000902 }
903 }
mpagenko01e726e2020-10-23 09:45:29 +0000904 logger.Infow("End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000905}
906
907func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +0000908 logger.Debugw("Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000909 "msgType": msg.OmciMsg.MessageType})
910
911 switch msg.OmciMsg.MessageType {
912 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +0000913 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
914 if err := oFsm.handleOmciCreateResponseMessage(msg.OmciPacket); err != nil {
915 logger.Warnw("CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +0000916 return
917 }
mpagenkodff5dda2020-08-28 11:52:01 +0000918 } //CreateResponseType
919 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +0000920 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +0000921 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
922 if msgLayer == nil {
mpagenko01e726e2020-10-23 09:45:29 +0000923 logger.Errorw("Omci Msg layer could not be detected for SetResponse",
924 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000925 return
926 }
927 msgObj, msgOk := msgLayer.(*omci.SetResponse)
928 if !msgOk {
mpagenko01e726e2020-10-23 09:45:29 +0000929 logger.Errorw("Omci Msg layer could not be assigned for SetResponse",
930 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000931 return
932 }
mpagenko01e726e2020-10-23 09:45:29 +0000933 logger.Debugw("UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +0000934 if msgObj.Result != me.Success {
mpagenko01e726e2020-10-23 09:45:29 +0000935 logger.Errorw("UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
936 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +0000937 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
938 return
939 }
mpagenko01e726e2020-10-23 09:45:29 +0000940 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
941 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
942 switch oFsm.pLastTxMeInstance.GetName() {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000943 case "VlanTaggingFilterData",
944 "ExtendedVlanTaggingOperationConfigurationData":
945 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +0000946 oFsm.omciMIdsResponseReceived <- true
947 }
948 }
949 }
950 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +0000951 case omci.DeleteResponseType:
952 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
953 if err := oFsm.handleOmciDeleteResponseMessage(msg.OmciPacket); err != nil {
954 logger.Warnw("DeleteResponse handling aborted", log.Fields{"err": err})
955 return
956 }
957 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +0000958 default:
959 {
mpagenko01e726e2020-10-23 09:45:29 +0000960 logger.Errorw("Rx OMCI unhandled MsgType",
961 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000962 return
963 }
964 }
965}
966
mpagenko01e726e2020-10-23 09:45:29 +0000967func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(apOmciPacket *gp.Packet) error {
968 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
969 if msgLayer == nil {
970 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
971 log.Fields{"device-id": oFsm.deviceID})
972 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
973 oFsm.deviceID)
974 }
975 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
976 if !msgOk {
977 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
978 log.Fields{"device-id": oFsm.deviceID})
979 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
980 oFsm.deviceID)
981 }
982 logger.Debugw("UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
983 if msgObj.Result != me.Success {
984 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
985 "Error": msgObj.Result})
986 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
987 return fmt.Errorf("omci CreateResponse Error for device-id %x",
988 oFsm.deviceID)
989 }
990 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
991 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
992 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
993 switch oFsm.pLastTxMeInstance.GetName() {
994 case "VlanTaggingFilterData":
995 {
996 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
997 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
998 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
999 } else { // let the MultiEntity config proceed by stopping the wait function
1000 oFsm.omciMIdsResponseReceived <- true
1001 }
1002 }
1003 }
1004 }
1005 return nil
1006}
1007
1008func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(apOmciPacket *gp.Packet) error {
1009 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1010 if msgLayer == nil {
1011 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
1012 log.Fields{"device-id": oFsm.deviceID})
1013 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1014 oFsm.deviceID)
1015 }
1016 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1017 if !msgOk {
1018 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
1019 log.Fields{"device-id": oFsm.deviceID})
1020 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1021 oFsm.deviceID)
1022 }
1023 logger.Debugw("UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
1024 if msgObj.Result != me.Success {
1025 logger.Errorw("UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
1026 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1027 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1028 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1029 oFsm.deviceID)
1030 }
1031 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1032 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1033 switch oFsm.pLastTxMeInstance.GetName() {
1034 case "VlanTaggingFilterData":
1035 { // let the MultiEntity config proceed by stopping the wait function
1036 oFsm.omciMIdsResponseReceived <- true
1037 }
1038 }
1039 }
1040 return nil
1041}
1042
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001043func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(aFlowEntryNo uint8) {
1044 if aFlowEntryNo == 0 {
1045 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001046 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1047 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
1048 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD", log.Fields{
1049 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1050 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001051 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001052 meParams := me.ParamData{
1053 EntityID: oFsm.evtocdID,
1054 Attributes: me.AttributeValueMap{
1055 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1056 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1057 "DownstreamMode": uint8(cDefaultDownstreamMode),
1058 },
1059 }
1060 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1061 oFsm.pAdaptFsm.commChan, meParams)
1062 //accept also nil as (error) return value for writing to LastTx
1063 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001064 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001065
1066 //verify response
1067 err := oFsm.waitforOmciResponse()
1068 if err != nil {
1069 logger.Errorw("Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001070 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301071 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001072 return
1073 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001074 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001075
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001076 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +00001077 if oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001078 //transparent transmission required
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001079 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001080 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001081 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001082 sliceEvtocdRule := make([]uint8, 16)
1083 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1084 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1085 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1086 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1087 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1088
1089 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1090 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1091 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1092 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1093 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1094
1095 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1096 0<<cTreatTTROffset| // Do not pop any tags
1097 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1098 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1099 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1100
1101 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1102 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1103 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1104 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1105
1106 meParams := me.ParamData{
1107 EntityID: oFsm.evtocdID,
1108 Attributes: me.AttributeValueMap{
1109 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1110 },
1111 }
1112 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1113 oFsm.pAdaptFsm.commChan, meParams)
1114 //accept also nil as (error) return value for writing to LastTx
1115 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001116 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001117
1118 //verify response
1119 err := oFsm.waitforOmciResponse()
1120 if err != nil {
1121 logger.Errorw("Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001122 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301123 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001124 return
1125 }
1126 } else {
1127 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1128 if oFsm.acceptIncrementalEvtoOption {
1129 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1130 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001131 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001132 sliceEvtocdRule := make([]uint8, 16)
1133 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1134 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1135 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1136 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1137 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1138
1139 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001140 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1141 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001142 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1143 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1144
1145 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001146 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001147 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1148 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1149 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1150
1151 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001152 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetPcp<<cTreatPrioOffset| // as configured in flow
1153 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001154 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001155 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001156
1157 meParams := me.ParamData{
1158 EntityID: oFsm.evtocdID,
1159 Attributes: me.AttributeValueMap{
1160 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1161 },
1162 }
1163 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1164 oFsm.pAdaptFsm.commChan, meParams)
1165 //accept also nil as (error) return value for writing to LastTx
1166 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001167 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001168
1169 //verify response
1170 err := oFsm.waitforOmciResponse()
1171 if err != nil {
1172 logger.Errorw("Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001173 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301174 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001175 return
1176 }
1177 } else {
1178 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1179 { // just for local var's
1180 // this defines stacking scenario: untagged->singletagged
1181 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001182 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001183 sliceEvtocdRule := make([]uint8, 16)
1184 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1185 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1186 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1187 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1188 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1189
1190 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1191 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1192 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1193 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1194 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1195
1196 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1197 0<<cTreatTTROffset| // Do not pop any tags
1198 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1199 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1200 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1201
1202 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1203 0<<cTreatPrioOffset| // vlan prio set to 0
1204 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko01e726e2020-10-23 09:45:29 +00001205 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001206 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1207
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001208 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001209 meParams := me.ParamData{
1210 EntityID: oFsm.evtocdID,
1211 Attributes: me.AttributeValueMap{
1212 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1213 },
1214 }
1215 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1216 oFsm.pAdaptFsm.commChan, meParams)
1217 //accept also nil as (error) return value for writing to LastTx
1218 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001219 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001220
1221 //verify response
1222 err := oFsm.waitforOmciResponse()
1223 if err != nil {
1224 logger.Errorw("Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001225 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301226 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001227 return
1228 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001229 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001230 { // just for local var's
1231 // this defines 'stacking' scenario: priotagged->singletagged
1232 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001233 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001234 sliceEvtocdRule := make([]uint8, 16)
1235 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1236 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1237 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1238 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1239 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1240
1241 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1242 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1243 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1244 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1245 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1246
1247 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1248 1<<cTreatTTROffset| // pop the prio-tag
1249 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1250 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1251 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1252
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001253 oFsm.mutexFlowParams.Lock()
mpagenkodff5dda2020-08-28 11:52:01 +00001254 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1255 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1256 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko01e726e2020-10-23 09:45:29 +00001257 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001258 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001259 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001260
1261 meParams := me.ParamData{
1262 EntityID: oFsm.evtocdID,
1263 Attributes: me.AttributeValueMap{
1264 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1265 },
1266 }
1267 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1268 oFsm.pAdaptFsm.commChan, meParams)
1269 //accept also nil as (error) return value for writing to LastTx
1270 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001271 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001272
1273 //verify response
1274 err := oFsm.waitforOmciResponse()
1275 if err != nil {
1276 logger.Errorw("Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001277 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301278 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001279 return
1280 }
1281 } //just for local var's
1282 }
1283 }
1284
1285 // if Config has been done for all GemPort instances let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001286 logger.Debugw("EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
1287 oFsm.configuredUniFlow++ // one (more) flow configured
Himani Chawla4d908332020-08-31 12:30:20 +05301288 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
mpagenkodff5dda2020-08-28 11:52:01 +00001289}
1290
mpagenko01e726e2020-10-23 09:45:29 +00001291func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(aRuleParams uniVlanRuleParams) {
1292 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1293 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1294 //transparent transmission was set
1295 //perhaps the config is not needed for removal,
1296 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
1297 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
1298 "device-id": oFsm.deviceID})
1299 sliceEvtocdRule := make([]uint8, 16)
1300 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1301 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1302 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1303 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1304 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1305
1306 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1307 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1308 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1309 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1310 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1311
1312 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1313 0<<cTreatTTROffset| // Do not pop any tags
1314 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1315 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1316 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1317
1318 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1319 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1320 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1321 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1322
1323 meParams := me.ParamData{
1324 EntityID: oFsm.evtocdID,
1325 Attributes: me.AttributeValueMap{
1326 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1327 },
1328 }
1329 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1330 oFsm.pAdaptFsm.commChan, meParams)
1331 //accept also nil as (error) return value for writing to LastTx
1332 // - this avoids misinterpretation of new received OMCI messages
1333 oFsm.pLastTxMeInstance = meInstance
1334
1335 //verify response
1336 err := oFsm.waitforOmciResponse()
1337 if err != nil {
1338 logger.Errorw("Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
1339 log.Fields{"device-id": oFsm.deviceID})
1340 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1341 return
1342 }
1343 } else {
1344 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1345 if oFsm.acceptIncrementalEvtoOption {
1346 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1347 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
1348 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1349 sliceEvtocdRule := make([]uint8, 16)
1350 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1351 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1352 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1353 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1354 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1355
1356 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1357 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1358 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1359 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1360 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1361
1362 // delete indication for the indicated Filter
1363 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1364 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1365
1366 meParams := me.ParamData{
1367 EntityID: oFsm.evtocdID,
1368 Attributes: me.AttributeValueMap{
1369 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1370 },
1371 }
1372 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1373 oFsm.pAdaptFsm.commChan, meParams)
1374 //accept also nil as (error) return value for writing to LastTx
1375 // - this avoids misinterpretation of new received OMCI messages
1376 oFsm.pLastTxMeInstance = meInstance
1377
1378 //verify response
1379 err := oFsm.waitforOmciResponse()
1380 if err != nil {
1381 logger.Errorw("Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
1382 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1383 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1384 return
1385 }
1386 } else {
1387 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1388 { // just for local var's
1389 // this defines stacking scenario: untagged->singletagged
1390 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1391 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1392 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1393 // delete now assumes there is only one such rule!
1394 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
1395 "device-id": oFsm.deviceID})
1396 sliceEvtocdRule := make([]uint8, 16)
1397 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1398 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1399 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1400 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1401 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1402
1403 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1404 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1405 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1406 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1407 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1408
1409 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1410 0<<cTreatTTROffset| // Do not pop any tags
1411 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1412 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1413 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1414
1415 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1416 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1417 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1418 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1419
1420 meParams := me.ParamData{
1421 EntityID: oFsm.evtocdID,
1422 Attributes: me.AttributeValueMap{
1423 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1424 },
1425 }
1426 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1427 oFsm.pAdaptFsm.commChan, meParams)
1428 //accept also nil as (error) return value for writing to LastTx
1429 // - this avoids misinterpretation of new received OMCI messages
1430 oFsm.pLastTxMeInstance = meInstance
1431
1432 //verify response
1433 err := oFsm.waitforOmciResponse()
1434 if err != nil {
1435 logger.Errorw("Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
1436 log.Fields{"device-id": oFsm.deviceID})
1437 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1438 return
1439 }
1440 } // just for local var's
1441 { // just for local var's
1442 // this defines 'stacking' scenario: priotagged->singletagged
1443 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
1444 "device-id": oFsm.deviceID})
1445 sliceEvtocdRule := make([]uint8, 16)
1446 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1447 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1448 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1449 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1450 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1451
1452 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1453 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1454 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1455 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1456 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1457
1458 // delete indication for the indicated Filter
1459 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1460 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1461
1462 meParams := me.ParamData{
1463 EntityID: oFsm.evtocdID,
1464 Attributes: me.AttributeValueMap{
1465 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1466 },
1467 }
1468 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1469 oFsm.pAdaptFsm.commChan, meParams)
1470 //accept also nil as (error) return value for writing to LastTx
1471 // - this avoids misinterpretation of new received OMCI messages
1472 oFsm.pLastTxMeInstance = meInstance
1473
1474 //verify response
1475 err := oFsm.waitforOmciResponse()
1476 if err != nil {
1477 logger.Errorw("Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
1478 log.Fields{"device-id": oFsm.deviceID})
1479 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1480 return
1481 }
1482 } //just for local var's
1483 }
1484 }
1485
1486 // if Config has been done for all GemPort instances let the FSM proceed
1487 logger.Debugw("EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
1488 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone)
1489}
1490
mpagenkodff5dda2020-08-28 11:52:01 +00001491func (oFsm *UniVlanConfigFsm) waitforOmciResponse() error {
1492 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05301493 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00001494 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001495 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001496 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
mpagenko01e726e2020-10-23 09:45:29 +00001497 logger.Warnw("UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
1498 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001499 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301500 if success {
mpagenkodff5dda2020-08-28 11:52:01 +00001501 logger.Debug("UniVlanConfigFsm multi entity response received")
1502 return nil
1503 }
1504 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +00001505 logger.Warnw("UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
1506 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001507 }
1508}