blob: aeb696782a0a444a384df424109ddb71a2f14944 [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"
mpagenkofc4f56e2020-11-04 17:17:49 +000087 vlanEvRenew = "vlanEvRenew"
mpagenko01e726e2020-10-23 09:45:29 +000088 vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
89 vlanEvRemFlowDone = "vlanEvRemFlowDone"
90 vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
Holger Hildebrandt394c5522020-09-11 11:23:01 +000091 //vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
92 //vlanEvTimeoutMids = "vlanEvTimeoutMids"
Himani Chawla4d908332020-08-31 12:30:20 +053093 vlanEvReset = "vlanEvReset"
94 vlanEvRestart = "vlanEvRestart"
mpagenkodff5dda2020-08-28 11:52:01 +000095)
mpagenko01e726e2020-10-23 09:45:29 +000096
mpagenkodff5dda2020-08-28 11:52:01 +000097const (
98 // states of config PON ANI port FSM
99 vlanStDisabled = "vlanStDisabled"
100 vlanStStarting = "vlanStStarting"
101 vlanStWaitingTechProf = "vlanStWaitingTechProf"
102 vlanStConfigVtfd = "vlanStConfigVtfd"
103 vlanStConfigEvtocd = "vlanStConfigEvtocd"
104 vlanStConfigDone = "vlanStConfigDone"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000105 vlanStConfigIncrFlow = "vlanStConfigIncrFlow"
mpagenko01e726e2020-10-23 09:45:29 +0000106 vlanStRemoveFlow = "vlanStRemoveFlow"
mpagenkodff5dda2020-08-28 11:52:01 +0000107 vlanStCleanupDone = "vlanStCleanupDone"
108 vlanStResetting = "vlanStResetting"
109)
110
mpagenko01e726e2020-10-23 09:45:29 +0000111type uniVlanRuleParams struct {
112 TpID uint16 `json:"tp_id"`
113 MatchVid uint32 `json:"match_vid"` //use uint32 types for allowing immediate bitshifting
114 MatchPcp uint32 `json:"match_pcp"`
115 TagsToRemove uint32 `json:"tags_to_remove"`
116 SetVid uint32 `json:"set_vid"`
117 SetPcp uint32 `json:"set_pcp"`
118}
119
120type uniVlanFlowParams struct {
121 CookieSlice []uint64 `json:"cookie_slice"`
122 VlanRuleParams uniVlanRuleParams `json:"vlan_rule_params"`
123}
124
125type uniRemoveVlanFlowParams struct {
126 cookie uint64 //just the last cookie valid for removal
127 vlanRuleParams uniVlanRuleParams
128}
129
mpagenkodff5dda2020-08-28 11:52:01 +0000130//UniVlanConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
131type UniVlanConfigFsm struct {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530132 pDeviceHandler *deviceHandler
mpagenko01e726e2020-10-23 09:45:29 +0000133 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530134 pOmciCC *omciCC
135 pOnuUniPort *onuUniPort
136 pUniTechProf *onuUniTechProf
137 pOnuDB *onuDeviceDB
mpagenkodff5dda2020-08-28 11:52:01 +0000138 techProfileID uint16
139 requestEvent OnuDeviceEvent
140 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
141 pAdaptFsm *AdapterFsm
142 acceptIncrementalEvtoOption bool
mpagenko2418ab02020-11-12 12:58:06 +0000143 clearPersistency bool
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000144 mutexFlowParams sync.Mutex
mpagenko01e726e2020-10-23 09:45:29 +0000145 uniVlanFlowParamsSlice []uniVlanFlowParams
146 uniRemoveFlowsSlice []uniRemoveVlanFlowParams
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000147 numUniFlows uint8 // expected number of flows should be less than 12
148 configuredUniFlow uint8
mpagenko01e726e2020-10-23 09:45:29 +0000149 numRemoveFlows uint8
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000150 numVlanFilterEntries uint8
mpagenko01e726e2020-10-23 09:45:29 +0000151 vlanFilterList [cVtfdTableSize]uint16
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000152 vtfdID uint16
153 evtocdID uint16
mpagenko01e726e2020-10-23 09:45:29 +0000154 pLastTxMeInstance *me.ManagedEntity
mpagenkofc4f56e2020-11-04 17:17:49 +0000155 requestEventOffset uint8
mpagenkodff5dda2020-08-28 11:52:01 +0000156}
157
mpagenko01e726e2020-10-23 09:45:29 +0000158//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
159// of ONU UNI ports via OMCI
160func NewUniVlanConfigFsm(apDeviceHandler *deviceHandler, apDevOmciCC *omciCC, apUniPort *onuUniPort,
161 apUniTechProf *onuUniTechProf, apOnuDB *onuDeviceDB, aTechProfileID uint16,
162 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message, aAcceptIncrementalEvto bool,
163 aCookieSlice []uint64, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) *UniVlanConfigFsm {
mpagenkodff5dda2020-08-28 11:52:01 +0000164 instFsm := &UniVlanConfigFsm{
165 pDeviceHandler: apDeviceHandler,
mpagenko01e726e2020-10-23 09:45:29 +0000166 deviceID: apDeviceHandler.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000167 pOmciCC: apDevOmciCC,
168 pOnuUniPort: apUniPort,
169 pUniTechProf: apUniTechProf,
170 pOnuDB: apOnuDB,
171 techProfileID: aTechProfileID,
172 requestEvent: aRequestEvent,
173 acceptIncrementalEvtoOption: aAcceptIncrementalEvto,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000174 numUniFlows: 0,
175 configuredUniFlow: 0,
mpagenko01e726e2020-10-23 09:45:29 +0000176 numRemoveFlows: 0,
mpagenko2418ab02020-11-12 12:58:06 +0000177 clearPersistency: true,
mpagenkodff5dda2020-08-28 11:52:01 +0000178 }
179
mpagenko01e726e2020-10-23 09:45:29 +0000180 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenkodff5dda2020-08-28 11:52:01 +0000181 if instFsm.pAdaptFsm == nil {
182 logger.Errorw("UniVlanConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000183 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000184 return nil
185 }
mpagenkodff5dda2020-08-28 11:52:01 +0000186 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
187 vlanStDisabled,
188 fsm.Events{
189 {Name: vlanEvStart, Src: []string{vlanStDisabled}, Dst: vlanStStarting},
190 {Name: vlanEvWaitTechProf, Src: []string{vlanStStarting}, Dst: vlanStWaitingTechProf},
191 {Name: vlanEvContinueConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigVtfd},
192 {Name: vlanEvStartConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigVtfd},
193 {Name: vlanEvRxConfigVtfd, Src: []string{vlanStConfigVtfd}, Dst: vlanStConfigEvtocd},
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000194 {Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
195 Dst: vlanStConfigDone},
196 {Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStConfigIncrFlow},
mpagenkofc4f56e2020-11-04 17:17:49 +0000197 {Name: vlanEvRenew, Src: []string{vlanStConfigIncrFlow}, Dst: vlanStStarting},
mpagenko01e726e2020-10-23 09:45:29 +0000198 {Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
199 {Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
200 {Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000201 /*
202 {Name: vlanEvTimeoutSimple, Src: []string{
203 vlanStCreatingDot1PMapper, vlanStCreatingMBPCD, vlanStSettingTconts, vlanStSettingDot1PMapper}, Dst: vlanStStarting},
204 {Name: vlanEvTimeoutMids, Src: []string{
205 vlanStCreatingGemNCTPs, vlanStCreatingGemIWs, vlanStSettingPQs}, Dst: vlanStStarting},
206 */
207 // exceptional treatment for all states except vlanStResetting
208 {Name: vlanEvReset, Src: []string{vlanStStarting, vlanStWaitingTechProf,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000209 vlanStConfigVtfd, vlanStConfigEvtocd, vlanStConfigDone, vlanStConfigIncrFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000210 vlanStRemoveFlow, vlanStCleanupDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000211 Dst: vlanStResetting},
212 // the only way to get to resource-cleared disabled state again is via "resseting"
213 {Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
214 },
mpagenkodff5dda2020-08-28 11:52:01 +0000215 fsm.Callbacks{
Girish Gowdra041dcb32020-11-16 16:54:30 -0800216 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
217 "enter_" + vlanStStarting: func(e *fsm.Event) { instFsm.enterConfigStarting(e) },
218 "enter_" + vlanStConfigVtfd: func(e *fsm.Event) { instFsm.enterConfigVtfd(e) },
219 "enter_" + vlanStConfigEvtocd: func(e *fsm.Event) { instFsm.enterConfigEvtocd(e) },
220 "enter_" + vlanStConfigDone: func(e *fsm.Event) { instFsm.enterVlanConfigDone(e) },
221 "enter_" + vlanStConfigIncrFlow: func(e *fsm.Event) { instFsm.enterConfigIncrFlow(e) },
222 "enter_" + vlanStRemoveFlow: func(e *fsm.Event) { instFsm.enterRemoveFlow(e) },
223 "enter_" + vlanStCleanupDone: func(e *fsm.Event) { instFsm.enterVlanCleanupDone(e) },
224 "enter_" + vlanStResetting: func(e *fsm.Event) { instFsm.enterResetting(e) },
225 "enter_" + vlanStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(e) },
mpagenkodff5dda2020-08-28 11:52:01 +0000226 },
227 )
228 if instFsm.pAdaptFsm.pFsm == nil {
229 logger.Errorw("UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000230 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000231 return nil
232 }
233
mpagenko01e726e2020-10-23 09:45:29 +0000234 _ = instFsm.initUniFlowParams(aTechProfileID, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000235
Holger Hildebrandt80129db2020-11-23 10:49:32 +0000236 logger.Debugw("UniVlanConfigFsm created", log.Fields{"device-id": instFsm.deviceID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000237 "accIncrEvto": instFsm.acceptIncrementalEvtoOption})
mpagenkodff5dda2020-08-28 11:52:01 +0000238 return instFsm
239}
240
mpagenko01e726e2020-10-23 09:45:29 +0000241//initUniFlowParams is a simplified form of SetUniFlowParams() used for first flow parameters configuration
242func (oFsm *UniVlanConfigFsm) initUniFlowParams(aTpID uint16, aCookieSlice []uint64,
243 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
244 loRuleParams := uniVlanRuleParams{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000245 TpID: aTpID,
246 MatchVid: uint32(aMatchVlan),
247 SetVid: uint32(aSetVlan),
248 SetPcp: uint32(aSetPcp),
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000249 }
250 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
mpagenko01e726e2020-10-23 09:45:29 +0000251 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
252 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000253
mpagenko01e726e2020-10-23 09:45:29 +0000254 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000255 //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 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
258 } else {
259 if !oFsm.acceptIncrementalEvtoOption {
260 //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 +0000261 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000262 }
263 }
264
mpagenko01e726e2020-10-23 09:45:29 +0000265 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000266 // no prio/vid filtering requested
mpagenko01e726e2020-10-23 09:45:29 +0000267 loRuleParams.TagsToRemove = 0 //no tag pop action
268 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
269 if loRuleParams.SetPcp == cCopyPrioFromInner {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000270 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
271 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
272 // might collide with NoMatchVid/CopyPrio(/setVid) setting
273 // this was some precondition setting taken over from py adapter ..
mpagenko01e726e2020-10-23 09:45:29 +0000274 loRuleParams.SetPcp = 0
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000275 }
276 }
mpagenko01e726e2020-10-23 09:45:29 +0000277
278 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
279 loFlowParams.CookieSlice = make([]uint64, 0)
280 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
281
282 //no mutex protection is required for initial access and adding the first flow is always possible
283 oFsm.uniVlanFlowParamsSlice = make([]uniVlanFlowParams, 0)
284 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
285 logger.Debugw("first UniVlanConfigFsm flow added", log.Fields{
286 "Cookies": oFsm.uniVlanFlowParamsSlice[0].CookieSlice,
287 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
288 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
289 "SetPcp": loRuleParams.SetPcp,
290 "device-id": oFsm.deviceID})
291 oFsm.numUniFlows = 1
292 oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
293
294 //permanently store flow config for reconcile case
295 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID,
296 &oFsm.uniVlanFlowParamsSlice); err != nil {
297 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
298 return err
299 }
300
301 return nil
302}
303
mpagenko2418ab02020-11-12 12:58:06 +0000304//RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
305func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
306 //mutex protection is required for possible concurrent access to FSM members
307 oFsm.mutexFlowParams.Lock()
308 defer oFsm.mutexFlowParams.Unlock()
309 oFsm.clearPersistency = aClear
310}
311
mpagenko01e726e2020-10-23 09:45:29 +0000312//SetUniFlowParams verifies on existence of flow parameters to be configured,
313// optionally udates the cookie list or appends a new flow if there is space
314// if possible the FSM is trigggerd to start with the processing
315func (oFsm *UniVlanConfigFsm) SetUniFlowParams(aTpID uint16, aCookieSlice []uint64,
316 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
317 loRuleParams := uniVlanRuleParams{
318 TpID: aTpID,
319 MatchVid: uint32(aMatchVlan),
320 SetVid: uint32(aSetVlan),
321 SetPcp: uint32(aSetPcp),
322 }
323 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
324 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
325 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
326
327 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
328 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
329 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
330 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
331 } else {
332 if !oFsm.acceptIncrementalEvtoOption {
333 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
334 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
335 }
336 }
337
338 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
339 // no prio/vid filtering requested
340 loRuleParams.TagsToRemove = 0 //no tag pop action
341 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
342 if loRuleParams.SetPcp == cCopyPrioFromInner {
343 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
344 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
345 // might collide with NoMatchVid/CopyPrio(/setVid) setting
346 // this was some precondition setting taken over from py adapter ..
347 loRuleParams.SetPcp = 0
348 }
349 }
350
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000351 flowEntryMatch := false
mpagenko01e726e2020-10-23 09:45:29 +0000352 flowCookieModify := false
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000353 //mutex protection is required for possible concurrent access to FSM members
354 oFsm.mutexFlowParams.Lock()
355 defer oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000356 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
357 //TODO: Verify if using e.g. hashes for the structures here for comparison may generate
358 // countable run time optimization (perhaps with including the hash in kvStore storage?)
359 if storedUniFlowParams.VlanRuleParams == loRuleParams {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000360 flowEntryMatch = true
mpagenko01e726e2020-10-23 09:45:29 +0000361 logger.Debugw("UniVlanConfigFsm flow setting - rule already exists", log.Fields{
362 "device-id": oFsm.deviceID})
363 var cookieMatch bool
364 for _, newCookie := range aCookieSlice { // for all cookies available in the arguments
365 cookieMatch = false
366 for _, cookie := range storedUniFlowParams.CookieSlice {
367 if cookie == newCookie {
368 logger.Debugw("UniVlanConfigFsm flow setting - and cookie already exists", log.Fields{
369 "device-id": oFsm.deviceID, "cookie": cookie})
370 cookieMatch = true
371 break //found new cookie - no further search for this requested cookie
372 }
373 }
374 if !cookieMatch {
375 logger.Debugw("UniVlanConfigFsm flow setting -adding new cookie", log.Fields{
376 "device-id": oFsm.deviceID, "cookie": newCookie})
377 //as range works with copies of the slice we have to write to the original slice!!
378 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
379 newCookie)
380 flowCookieModify = true
381 }
382 } //for all new cookies
383 break // found rule - no further rule search
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000384 }
385 }
mpagenko01e726e2020-10-23 09:45:29 +0000386 if !flowEntryMatch { //it is a new rule
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000387 if oFsm.numUniFlows < cMaxAllowedFlows {
mpagenko01e726e2020-10-23 09:45:29 +0000388 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
389 loFlowParams.CookieSlice = make([]uint64, 0)
390 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
391 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
392 logger.Debugw("UniVlanConfigFsm flow add", log.Fields{
393 "Cookies": oFsm.uniVlanFlowParamsSlice[oFsm.numUniFlows].CookieSlice,
394 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
395 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800396 "SetPcp": loRuleParams.SetPcp, "numberofFlows": oFsm.numUniFlows + 1,
mpagenko01e726e2020-10-23 09:45:29 +0000397 "device-id": oFsm.deviceID})
398
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000399 oFsm.numUniFlows++
mpagenko01e726e2020-10-23 09:45:29 +0000400 // note: theoretical it would be possible to clear the same rule from the remove slice
401 // (for entries that have not yet been started with removal)
402 // but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
403 // 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 +0000404
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000405 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
406 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
407 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
408 // calling some FSM event must be decoupled
409 go func(a_pBaseFsm *fsm.FSM) {
410 _ = a_pBaseFsm.Event(vlanEvIncrFlowConfig)
411 }(pConfigVlanStateBaseFsm)
mpagenko01e726e2020-10-23 09:45:29 +0000412 } // if not in the appropriate state a new entry will be automatically considered later
413 // when the configDone state is reached
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000414 } else {
415 logger.Errorw("UniVlanConfigFsm flow limit exceeded", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000416 "device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
417 return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
418 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000419 } else {
420 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
421 if oFsm.numUniFlows == oFsm.configuredUniFlow {
422 //all requested rules really have been configured
423 // state transition notification is checked in deviceHandler
424 if oFsm.pDeviceHandler != nil {
425 //also the related TechProfile was already configured
426 logger.Debugw("UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
427 "device-id": oFsm.deviceID})
428 go oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
429 }
430 } else {
431 // avoid device reason update as the rule config connected to this flow may still be in progress
432 // and the device reason should only be updated on success of rule config
433 logger.Debugw("UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
434 log.Fields{"device-id": oFsm.deviceID,
435 "NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
436 }
437 }
mpagenko01e726e2020-10-23 09:45:29 +0000438
439 if !flowEntryMatch || flowCookieModify { // some change was done to the flow entries
440 //permanently store flow config for reconcile case
441 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
442 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
443 return err
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000444 }
445 }
446 return nil
447}
448
mpagenko01e726e2020-10-23 09:45:29 +0000449//RemoveUniFlowParams verifies on existence of flow cookie,
450// if found removes cookie from flow cookie list and if this is empty
451// initiates removal of the flow related configuration from the ONU (via OMCI)
452func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(aCookie uint64) error {
453 flowCookieMatch := false
454 //mutex protection is required for possible concurrent access to FSM members
455 oFsm.mutexFlowParams.Lock()
456 defer oFsm.mutexFlowParams.Unlock()
457 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
458 for i, cookie := range storedUniFlowParams.CookieSlice {
459 if cookie == aCookie {
460 logger.Debugw("UniVlanConfigFsm flow removal - cookie found", log.Fields{
461 "device-id": oFsm.deviceID, "cookie": cookie})
462 flowCookieMatch = true
463
464 //remove the cookie from the cookie slice and verify it is getting empty
465 if len(storedUniFlowParams.CookieSlice) == 1 {
466 logger.Debugw("UniVlanConfigFsm flow removal - full flow removal", log.Fields{
467 "device-id": oFsm.deviceID})
468 oFsm.numUniFlows--
469
470 //create a new element for the removeVlanFlow slice
471 loRemoveParams := uniRemoveVlanFlowParams{
472 vlanRuleParams: storedUniFlowParams.VlanRuleParams,
473 cookie: storedUniFlowParams.CookieSlice[0],
474 }
475 oFsm.uniRemoveFlowsSlice = append(oFsm.uniRemoveFlowsSlice, loRemoveParams)
476
477 //and remove the actual element from the addVlanFlow slice
478 // oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = nil //automatically done by garbage collector
479 if len(oFsm.uniVlanFlowParamsSlice) <= 1 {
480 oFsm.numUniFlows = 0 //no more flows
481 oFsm.configuredUniFlow = 0 //no more flows configured
482 oFsm.uniVlanFlowParamsSlice = nil //reset the slice
mpagenko2418ab02020-11-12 12:58:06 +0000483 //at this point it is evident that no flow anymore refers to a still possibly active Techprofile
484 //request that this profile gets deleted before a new flow add is allowed
Girish Gowdra041dcb32020-11-16 16:54:30 -0800485 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, uint8(oFsm.techProfileID), true)
mpagenko01e726e2020-10-23 09:45:29 +0000486 logger.Debugw("UniVlanConfigFsm flow removal - no more flows", log.Fields{
487 "device-id": oFsm.deviceID})
488 } else {
489 oFsm.numUniFlows--
490 if oFsm.configuredUniFlow > 0 {
491 oFsm.configuredUniFlow--
492 //TODO!! might be needed to consider still outstanding configure requests ..
493 // so a flow at removal might still not be configured !?!
494 }
mpagenko2418ab02020-11-12 12:58:06 +0000495 usedTpID := storedUniFlowParams.VlanRuleParams.TpID
mpagenko01e726e2020-10-23 09:45:29 +0000496 //cut off the requested flow by slicing out this element
497 oFsm.uniVlanFlowParamsSlice = append(
498 oFsm.uniVlanFlowParamsSlice[:flow], oFsm.uniVlanFlowParamsSlice[flow+1:]...)
mpagenko2418ab02020-11-12 12:58:06 +0000499 //here we have to check, if there are still other flows referencing to the actual ProfileId
500 // before we can request that this profile gets deleted before a new flow add is allowed
501 tpIDInOtherFlows := false
502 for _, tpUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
503 if tpUniFlowParams.VlanRuleParams.TpID == usedTpID {
504 tpIDInOtherFlows = true
505 break // search loop can be left
506 }
507 }
508 if tpIDInOtherFlows {
509 logger.Debugw("UniVlanConfigFsm tp-id used in deleted flow is still used in other flows", log.Fields{
510 "device-id": oFsm.deviceID, "tp-id": usedTpID})
511 } else {
512 logger.Debugw("UniVlanConfigFsm tp-id used in deleted flow is not used anymore", log.Fields{
513 "device-id": oFsm.deviceID, "tp-id": usedTpID})
514 //request that this profile gets deleted before a new flow add is allowed
Girish Gowdra041dcb32020-11-16 16:54:30 -0800515 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, uint8(oFsm.techProfileID), true)
mpagenko2418ab02020-11-12 12:58:06 +0000516 }
mpagenko01e726e2020-10-23 09:45:29 +0000517 logger.Debugw("UniVlanConfigFsm flow removal - specific flow removed from data", log.Fields{
518 "device-id": oFsm.deviceID})
519 }
520 //trigger the FSM to remove the relevant rule
521 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
522 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
523 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
524 // calling some FSM event must be decoupled
525 go func(a_pBaseFsm *fsm.FSM) {
526 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
527 }(pConfigVlanStateBaseFsm)
528 } // if not in the appropriate state a new entry will be automatically considered later
529 // when the configDone state is reached
530 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000531 //cut off the requested cookie by slicing out this element
532 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
533 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
534 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
mpagenkofc4f56e2020-11-04 17:17:49 +0000535 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
536 // state transition notification is checked in deviceHandler
537 if oFsm.pDeviceHandler != nil {
538 //making use of the add->remove successor enum assumption/definition
Girish Gowdra041dcb32020-11-16 16:54:30 -0800539 go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent(uint8(oFsm.requestEvent) + 1))
mpagenkofc4f56e2020-11-04 17:17:49 +0000540 }
541 logger.Debugw("UniVlanConfigFsm flow removal - rule persists with still valid cookies", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000542 "device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
543 }
544
545 //permanently store the modified flow config for reconcile case
mpagenkofc4f56e2020-11-04 17:17:49 +0000546 if oFsm.pDeviceHandler != nil {
547 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
548 logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
549 return err
550 }
mpagenko01e726e2020-10-23 09:45:29 +0000551 }
552
553 break //found the cookie - no further search for this requested cookie
554 }
555 }
556 if flowCookieMatch { //cookie already found: no need for further search in other flows
557 break
558 }
559 } //search all flows
560 if !flowCookieMatch { //some cookie remove-request for a cookie that does not exist in the FSM data
561 logger.Warnw("UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
562 "device-id": oFsm.deviceID, "remove-cookie": aCookie})
563 // but accept the request with success as no such cookie (flow) does exist
mpagenkofc4f56e2020-11-04 17:17:49 +0000564 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
565 // state transition notification is checked in deviceHandler
566 if oFsm.pDeviceHandler != nil {
567 //making use of the add->remove successor enum assumption/definition
Girish Gowdra041dcb32020-11-16 16:54:30 -0800568 go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent(uint8(oFsm.requestEvent) + 1))
mpagenkofc4f56e2020-11-04 17:17:49 +0000569 }
mpagenko01e726e2020-10-23 09:45:29 +0000570 return nil
571 } //unknown cookie
572
573 return nil
574}
575
mpagenkodff5dda2020-08-28 11:52:01 +0000576func (oFsm *UniVlanConfigFsm) enterConfigStarting(e *fsm.Event) {
577 logger.Debugw("UniVlanConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000578 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000579
580 // this FSM is not intended for re-start, needs always new creation for a new run
mpagenko01e726e2020-10-23 09:45:29 +0000581 // (self-destroying - compare enterDisabled())
mpagenkodff5dda2020-08-28 11:52:01 +0000582 oFsm.omciMIdsResponseReceived = make(chan bool)
583 // start go routine for processing of LockState messages
584 go oFsm.processOmciVlanMessages()
585 //let the state machine run forward from here directly
586 pConfigVlanStateAFsm := oFsm.pAdaptFsm
587 if pConfigVlanStateAFsm != nil {
588 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
589 go func(a_pAFsm *AdapterFsm) {
590 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
591 //stick to pythonAdapter numbering scheme
Himani Chawla26e555c2020-08-31 12:30:20 +0530592 oFsm.vtfdID = macBridgePortAniEID + oFsm.pOnuUniPort.entityID + oFsm.techProfileID
mpagenkodff5dda2020-08-28 11:52:01 +0000593 //cmp also usage in EVTOCDE create in omci_cc
594 oFsm.evtocdID = macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
595
Girish Gowdra041dcb32020-11-16 16:54:30 -0800596 if oFsm.pUniTechProf.getTechProfileDone(oFsm.pOnuUniPort.uniID, uint8(oFsm.techProfileID)) {
mpagenkodff5dda2020-08-28 11:52:01 +0000597 // let the vlan processing begin
Himani Chawla4d908332020-08-31 12:30:20 +0530598 _ = a_pAFsm.pFsm.Event(vlanEvStartConfig)
mpagenkodff5dda2020-08-28 11:52:01 +0000599 } else {
600 // set to waiting for Techprofile
Himani Chawla4d908332020-08-31 12:30:20 +0530601 _ = a_pAFsm.pFsm.Event(vlanEvWaitTechProf)
mpagenkodff5dda2020-08-28 11:52:01 +0000602 }
603 }
604 }(pConfigVlanStateAFsm)
605 }
606}
607
608func (oFsm *UniVlanConfigFsm) enterConfigVtfd(e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000609 //mutex protection is required for possible concurrent access to FSM members
610 oFsm.mutexFlowParams.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +0000611 if len(oFsm.uniVlanFlowParamsSlice) == 0 {
612 //possibly the entry is not valid anymore based on intermediate delete requests
613 //just a basic protection ...
614 oFsm.mutexFlowParams.Unlock()
615 pConfigVlanStateAFsm := oFsm.pAdaptFsm
616 go func(a_pAFsm *AdapterFsm) {
617 _ = a_pAFsm.pFsm.Event(vlanEvReset)
618 }(pConfigVlanStateAFsm)
619 return
620 }
mpagenko01e726e2020-10-23 09:45:29 +0000621 if oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000622 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000623 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +0000624 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000625 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000626 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
627 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
628 pConfigVlanStateAFsm := oFsm.pAdaptFsm
629 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530630 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000631 }(pConfigVlanStateAFsm)
632 } else {
633 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
634 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000635 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
636 // setVid is assumed to be masked already by the caller to 12 bit
637 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000638 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000639 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000640 vtfdFilterList[0] = oFsm.vlanFilterList[0]
641 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000642 meParams := me.ParamData{
643 EntityID: oFsm.vtfdID,
644 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000645 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
646 "ForwardOperation": uint8(0x10), //VID investigation
647 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000648 },
649 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000650 logger.Debugw("UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000651 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000652 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
653 oFsm.pAdaptFsm.commChan, meParams)
654 //accept also nil as (error) return value for writing to LastTx
655 // - this avoids misinterpretation of new received OMCI messages
656 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
657 // send shall return (dual format) error code that can be used here for immediate error treatment
658 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000659 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000660 }
661}
662
663func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(e *fsm.Event) {
664 logger.Debugw("UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000665 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000666 oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000667 go oFsm.performConfigEvtocdEntries(0)
mpagenkodff5dda2020-08-28 11:52:01 +0000668}
669
670func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000671 logger.Debugw("UniVlanConfigFsm - checking on more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000672 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
673 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
674 if len(oFsm.uniRemoveFlowsSlice) > 0 {
675 //some further flows are to be removed, removal always starts with the first element
676 // calling some FSM event must be decoupled
677 go func(a_pBaseFsm *fsm.FSM) {
678 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
679 }(pConfigVlanStateBaseFsm)
680 return
681 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000682 if oFsm.numUniFlows > oFsm.configuredUniFlow {
683 //some further flows are to be configured
684 // calling some FSM event must be decoupled
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000685 go func(a_pBaseFsm *fsm.FSM) {
686 _ = a_pBaseFsm.Event(vlanEvIncrFlowConfig)
687 }(pConfigVlanStateBaseFsm)
688 return
689 }
690
691 logger.Debugw("UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000692 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000693 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
694 // state transition notification is checked in deviceHandler
mpagenkodff5dda2020-08-28 11:52:01 +0000695 if oFsm.pDeviceHandler != nil {
mpagenkofc4f56e2020-11-04 17:17:49 +0000696 //making use of the add->remove successor enum assumption/definition
Girish Gowdra041dcb32020-11-16 16:54:30 -0800697 go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent(uint8(oFsm.requestEvent) + oFsm.requestEventOffset))
mpagenkodff5dda2020-08-28 11:52:01 +0000698 }
699}
700
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000701func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(e *fsm.Event) {
702 logger.Debugw("UniVlanConfigFsm - start config further incremental flow", log.Fields{
Girish Gowdra041dcb32020-11-16 16:54:30 -0800703 "in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000704 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000705 oFsm.mutexFlowParams.Lock()
706
mpagenkofc4f56e2020-11-04 17:17:49 +0000707 if oFsm.configuredUniFlow == 0 {
708 oFsm.mutexFlowParams.Unlock()
709 // this is a restart with a complete new flow, we can re-use the initial flow config control
710 // including the check, if the related techProfile is (still) available (probably also removed in between)
711 // calling some FSM event must be decoupled
712 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
713 go func(a_pBaseFsm *fsm.FSM) {
714 _ = a_pBaseFsm.Event(vlanEvRenew)
715 }(pConfigVlanStateBaseFsm)
716 return
717 }
mpagenko8b07c1b2020-11-26 10:36:31 +0000718 if uint8(len(oFsm.uniVlanFlowParamsSlice)) < oFsm.configuredUniFlow {
719 //possibly the entry is not valid anymore based on intermediate delete requests
720 //just a basic protection ...
721 oFsm.mutexFlowParams.Unlock()
722 pConfigVlanStateAFsm := oFsm.pAdaptFsm
723 go func(a_pAFsm *AdapterFsm) {
724 _ = a_pAFsm.pFsm.Event(vlanEvReset)
725 }(pConfigVlanStateAFsm)
726 return
727 }
mpagenko01e726e2020-10-23 09:45:29 +0000728 if oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000729 // meaning transparent setup - no specific VTFD setting required
730 oFsm.mutexFlowParams.Unlock()
731 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000732 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000733 } else {
734 if oFsm.numVlanFilterEntries == 0 {
735 //no VTFD yet created
736 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
737 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000738 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
739 // setVid is assumed to be masked already by the caller to 12 bit
740 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000741 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000742 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000743 vtfdFilterList[0] = oFsm.vlanFilterList[0]
744 oFsm.numVlanFilterEntries = 1
745 meParams := me.ParamData{
746 EntityID: oFsm.vtfdID,
747 Attributes: me.AttributeValueMap{
748 "VlanFilterList": vtfdFilterList,
749 "ForwardOperation": uint8(0x10), //VID investigation
750 "NumberOfEntries": oFsm.numVlanFilterEntries,
751 },
752 }
753 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
754 oFsm.pAdaptFsm.commChan, meParams)
755 //accept also nil as (error) return value for writing to LastTx
756 // - this avoids misinterpretation of new received OMCI messages
757 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
758 // send shall return (dual format) error code that can be used here for immediate error treatment
759 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000760 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000761 } else {
762 //VTFD already exists - just modify by 'set'
763 //TODO!!: but only if the VID is not already present, skipped by now to test basic working
764 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
765 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000766 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000767 // setVid is assumed to be masked already by the caller to 12 bit
768 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko01e726e2020-10-23 09:45:29 +0000769 uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000770 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000771 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000772 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
773 vtfdFilterList[i] = oFsm.vlanFilterList[i]
774 }
775
776 oFsm.numVlanFilterEntries++
777 meParams := me.ParamData{
778 EntityID: oFsm.vtfdID,
779 Attributes: me.AttributeValueMap{
780 "VlanFilterList": vtfdFilterList,
781 "NumberOfEntries": oFsm.numVlanFilterEntries,
782 },
783 }
784 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
785 oFsm.pAdaptFsm.commChan, meParams)
786 //accept also nil as (error) return value for writing to LastTx
787 // - this avoids misinterpretation of new received OMCI messages
788 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
789 // send shall return (dual format) error code that can be used here for immediate error treatment
790 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000791 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000792 }
793 //verify response
794 err := oFsm.waitforOmciResponse()
795 if err != nil {
796 logger.Errorw("VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000797 log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000798 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
799 go func(a_pBaseFsm *fsm.FSM) {
800 _ = a_pBaseFsm.Event(vlanEvReset)
801 }(pConfigVlanStateBaseFsm)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000802 return
803 }
804 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000805 oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000806 go oFsm.performConfigEvtocdEntries(oFsm.configuredUniFlow)
807}
808
mpagenko01e726e2020-10-23 09:45:29 +0000809func (oFsm *UniVlanConfigFsm) enterRemoveFlow(e *fsm.Event) {
810 oFsm.mutexFlowParams.Lock()
811 logger.Debugw("UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
812 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
813 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000814
mpagenkofc4f56e2020-11-04 17:17:49 +0000815 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
816 loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
mpagenko01e726e2020-10-23 09:45:29 +0000817 loVlanEntryClear := uint8(0)
818 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
819 //shallow copy is sufficient as no reference variables are used within struct
820 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
821 oFsm.mutexFlowParams.Unlock()
822 logger.Debugw("UniVlanConfigFsm - remove-flow parameters are", log.Fields{
823 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
824 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
825 "device-id": oFsm.deviceID})
826
827 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
828 // meaning transparent setup - no specific VTFD setting required
829 logger.Debugw("UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
830 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
831 } else {
832 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
833 if oFsm.numVlanFilterEntries == 1 {
834 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
835 // so we can just delete the VTFD entry
836 logger.Debugw("UniVlanConfigFsm: VTFD delete (no more vlan filters)",
837 log.Fields{"current vlan list": oFsm.vlanFilterList,
838 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000839 loVlanEntryClear = 1 //full VlanFilter clear request
840 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
841 meInstance := oFsm.pOmciCC.sendDeleteVtfd(context.TODO(), ConstDefaultOmciTimeout, true,
842 oFsm.pAdaptFsm.commChan, oFsm.vtfdID)
843 oFsm.pLastTxMeInstance = meInstance
844 } else {
845 logger.Debugw("UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +0000846 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenkofc4f56e2020-11-04 17:17:49 +0000847 }
mpagenko01e726e2020-10-23 09:45:29 +0000848 } else {
849 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
850 // by updating the VTFD per set command with new valid list
851 logger.Debugw("UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
852 log.Fields{"current vlan list": oFsm.vlanFilterList,
853 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
854 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
855 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
856 loVlanEntryRmPos = i
857 break //abort search
858 }
859 }
860 if loVlanEntryRmPos < cVtfdTableSize {
861 //valid entry was found - to be eclipsed
862 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
863 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
864 if i < loVlanEntryRmPos {
865 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
866 } else if i < (cVtfdTableSize - 1) {
867 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
868 } else {
869 vtfdFilterList[i] = 0 //set last byte if needed
870 }
871 }
872 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
873 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
874 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
875
mpagenkofc4f56e2020-11-04 17:17:49 +0000876 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
877 meParams := me.ParamData{
878 EntityID: oFsm.vtfdID,
879 Attributes: me.AttributeValueMap{
880 "VlanFilterList": vtfdFilterList,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800881 "NumberOfEntries": oFsm.numVlanFilterEntries - 1, //one element less
mpagenkofc4f56e2020-11-04 17:17:49 +0000882 },
883 }
884 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
885 oFsm.pAdaptFsm.commChan, meParams)
886 oFsm.pLastTxMeInstance = meInstance
887 } else {
888 logger.Debugw("UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +0000889 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenko01e726e2020-10-23 09:45:29 +0000890 }
mpagenko01e726e2020-10-23 09:45:29 +0000891 } else {
892 logger.Warnw("UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
893 log.Fields{"device-id": oFsm.deviceID})
894 }
895 }
896 if loVlanEntryClear > 0 {
mpagenkofc4f56e2020-11-04 17:17:49 +0000897 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
898 //waiting on response
899 err := oFsm.waitforOmciResponse()
900 if err != nil {
901 logger.Errorw("VTFD delete/reset failed, aborting VlanConfig FSM!",
902 log.Fields{"device-id": oFsm.deviceID})
903 // calling some FSM event must be decoupled
904 go func(a_pBaseFsm *fsm.FSM) {
905 _ = a_pBaseFsm.Event(vlanEvReset)
906 }(pConfigVlanStateBaseFsm)
907 return
908 }
mpagenko01e726e2020-10-23 09:45:29 +0000909 }
910
911 if loVlanEntryClear == 1 {
912 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
913 oFsm.numVlanFilterEntries = 0
914 } else if loVlanEntryClear == 2 {
915 // new VlanFilterList should be one entry smaller now - copy from last configured entry
916 // this loop now includes the 0 element on previous last valid entry
917 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
918 oFsm.vlanFilterList[i] = vtfdFilterList[i]
919 }
920 oFsm.numVlanFilterEntries--
921 }
922 }
923 }
924
mpagenkofc4f56e2020-11-04 17:17:49 +0000925 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
926 go oFsm.removeEvtocdEntries(loRuleParams)
927 } else {
928 // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
929 logger.Debugw("UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
930 "device-id": oFsm.deviceID})
931 // calling some FSM event must be decoupled
932 go func(a_pBaseFsm *fsm.FSM) {
933 _ = a_pBaseFsm.Event(vlanEvRemFlowDone)
934 }(pConfigVlanStateBaseFsm)
935 }
mpagenkodff5dda2020-08-28 11:52:01 +0000936}
937
938func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000939 logger.Debugw("UniVlanConfigFsm - removing the removal data", log.Fields{
940 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000941
mpagenko01e726e2020-10-23 09:45:29 +0000942 oFsm.mutexFlowParams.Lock()
943 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
944 oFsm.uniRemoveFlowsSlice = nil //reset the slice
945 logger.Debugw("UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
946 "device-id": oFsm.deviceID})
947 } else {
948 //cut off the actual flow by slicing out the first element
949 oFsm.uniRemoveFlowsSlice = append(
950 oFsm.uniRemoveFlowsSlice[:0],
951 oFsm.uniRemoveFlowsSlice[1:]...)
952 logger.Debugw("UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
953 "device-id": oFsm.deviceID})
954 }
955 oFsm.mutexFlowParams.Unlock()
956
mpagenkofc4f56e2020-11-04 17:17:49 +0000957 oFsm.requestEventOffset = 1 //offset 1 for last flow-remove activity
mpagenko01e726e2020-10-23 09:45:29 +0000958 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +0000959 pConfigVlanStateAFsm := oFsm.pAdaptFsm
960 if pConfigVlanStateAFsm != nil {
961 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
962 go func(a_pAFsm *AdapterFsm) {
963 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +0000964 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +0000965 }
966 }(pConfigVlanStateAFsm)
967 }
968}
969
970func (oFsm *UniVlanConfigFsm) enterResetting(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000971 logger.Debugw("UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000972
973 pConfigVlanStateAFsm := oFsm.pAdaptFsm
974 if pConfigVlanStateAFsm != nil {
975 // abort running message processing
976 fsmAbortMsg := Message{
977 Type: TestMsg,
978 Data: TestMessage{
979 TestMessageVal: AbortMessageProcessing,
980 },
981 }
982 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
983
984 //try to restart the FSM to 'disabled', decouple event transfer
985 go func(a_pAFsm *AdapterFsm) {
986 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530987 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +0000988 }
989 }(pConfigVlanStateAFsm)
990 }
991}
992
993func (oFsm *UniVlanConfigFsm) enterDisabled(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000994 logger.Debugw("UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
995 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +0000996 if oFsm.pDeviceHandler != nil {
mpagenko2418ab02020-11-12 12:58:06 +0000997 //TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
998 // current code removes the complete FSM including all flow/rule configuration done so far
999 // this might be a bit to much, it would require fully new flow config from rwCore (at least on OnuDown/up)
1000 // maybe a more sophisticated approach is possible without clearing the data
1001 if oFsm.clearPersistency {
1002 //permanently remove possibly stored persistent data
1003 if len(oFsm.uniVlanFlowParamsSlice) > 0 {
1004 var emptySlice = make([]uniVlanFlowParams, 0)
1005 _ = oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &emptySlice) //ignore errors
1006 }
1007 } else {
1008 logger.Debugw("UniVlanConfigFsm persistency data not cleared", log.Fields{"device-id": oFsm.deviceID})
1009 }
1010 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenkodff5dda2020-08-28 11:52:01 +00001011 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(oFsm.pOnuUniPort)
1012 }
1013}
1014
1015func (oFsm *UniVlanConfigFsm) processOmciVlanMessages() { //ctx context.Context?
mpagenko01e726e2020-10-23 09:45:29 +00001016 logger.Debugw("Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001017loop:
1018 for {
mpagenkodff5dda2020-08-28 11:52:01 +00001019 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001020 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001021 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301022 message, ok := <-oFsm.pAdaptFsm.commChan
1023 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +00001024 logger.Info("UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301025 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1026 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1027 break loop
1028 }
mpagenko01e726e2020-10-23 09:45:29 +00001029 logger.Debugw("UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301030
1031 switch message.Type {
1032 case TestMsg:
1033 msg, _ := message.Data.(TestMessage)
1034 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +00001035 logger.Infow("UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001036 break loop
1037 }
mpagenko01e726e2020-10-23 09:45:29 +00001038 logger.Warnw("UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301039 case OMCI:
1040 msg, _ := message.Data.(OmciMessage)
1041 oFsm.handleOmciVlanConfigMessage(msg)
1042 default:
mpagenko01e726e2020-10-23 09:45:29 +00001043 logger.Warn("UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301044 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +00001045 }
1046 }
mpagenko01e726e2020-10-23 09:45:29 +00001047 logger.Infow("End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001048}
1049
1050func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +00001051 logger.Debugw("Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001052 "msgType": msg.OmciMsg.MessageType})
1053
1054 switch msg.OmciMsg.MessageType {
1055 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001056 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
1057 if err := oFsm.handleOmciCreateResponseMessage(msg.OmciPacket); err != nil {
1058 logger.Warnw("CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +00001059 return
1060 }
mpagenkodff5dda2020-08-28 11:52:01 +00001061 } //CreateResponseType
1062 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001063 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +00001064 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1065 if msgLayer == nil {
mpagenko01e726e2020-10-23 09:45:29 +00001066 logger.Errorw("Omci Msg layer could not be detected for SetResponse",
1067 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001068 return
1069 }
1070 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1071 if !msgOk {
mpagenko01e726e2020-10-23 09:45:29 +00001072 logger.Errorw("Omci Msg layer could not be assigned for SetResponse",
1073 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001074 return
1075 }
mpagenko01e726e2020-10-23 09:45:29 +00001076 logger.Debugw("UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +00001077 if msgObj.Result != me.Success {
mpagenko01e726e2020-10-23 09:45:29 +00001078 logger.Errorw("UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
1079 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +00001080 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1081 return
1082 }
mpagenko01e726e2020-10-23 09:45:29 +00001083 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1084 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1085 switch oFsm.pLastTxMeInstance.GetName() {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001086 case "VlanTaggingFilterData",
1087 "ExtendedVlanTaggingOperationConfigurationData":
1088 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +00001089 oFsm.omciMIdsResponseReceived <- true
1090 }
1091 }
1092 }
1093 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +00001094 case omci.DeleteResponseType:
1095 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
1096 if err := oFsm.handleOmciDeleteResponseMessage(msg.OmciPacket); err != nil {
1097 logger.Warnw("DeleteResponse handling aborted", log.Fields{"err": err})
1098 return
1099 }
1100 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +00001101 default:
1102 {
mpagenko01e726e2020-10-23 09:45:29 +00001103 logger.Errorw("Rx OMCI unhandled MsgType",
1104 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001105 return
1106 }
1107 }
1108}
1109
mpagenko01e726e2020-10-23 09:45:29 +00001110func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(apOmciPacket *gp.Packet) error {
1111 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
1112 if msgLayer == nil {
1113 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
1114 log.Fields{"device-id": oFsm.deviceID})
1115 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
1116 oFsm.deviceID)
1117 }
1118 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1119 if !msgOk {
1120 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
1121 log.Fields{"device-id": oFsm.deviceID})
1122 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
1123 oFsm.deviceID)
1124 }
1125 logger.Debugw("UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
1126 if msgObj.Result != me.Success {
1127 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
1128 "Error": msgObj.Result})
1129 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1130 return fmt.Errorf("omci CreateResponse Error for device-id %x",
1131 oFsm.deviceID)
1132 }
1133 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1134 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1135 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
1136 switch oFsm.pLastTxMeInstance.GetName() {
1137 case "VlanTaggingFilterData":
1138 {
1139 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
1140 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
1141 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
1142 } else { // let the MultiEntity config proceed by stopping the wait function
1143 oFsm.omciMIdsResponseReceived <- true
1144 }
1145 }
1146 }
1147 }
1148 return nil
1149}
1150
1151func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(apOmciPacket *gp.Packet) error {
1152 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1153 if msgLayer == nil {
1154 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
1155 log.Fields{"device-id": oFsm.deviceID})
1156 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1157 oFsm.deviceID)
1158 }
1159 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1160 if !msgOk {
1161 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
1162 log.Fields{"device-id": oFsm.deviceID})
1163 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1164 oFsm.deviceID)
1165 }
1166 logger.Debugw("UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
1167 if msgObj.Result != me.Success {
1168 logger.Errorw("UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
1169 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1170 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1171 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1172 oFsm.deviceID)
1173 }
1174 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1175 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1176 switch oFsm.pLastTxMeInstance.GetName() {
1177 case "VlanTaggingFilterData":
1178 { // let the MultiEntity config proceed by stopping the wait function
1179 oFsm.omciMIdsResponseReceived <- true
1180 }
1181 }
1182 }
1183 return nil
1184}
1185
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001186func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(aFlowEntryNo uint8) {
1187 if aFlowEntryNo == 0 {
1188 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001189 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1190 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
1191 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD", log.Fields{
1192 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1193 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001194 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001195 meParams := me.ParamData{
1196 EntityID: oFsm.evtocdID,
1197 Attributes: me.AttributeValueMap{
1198 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1199 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1200 "DownstreamMode": uint8(cDefaultDownstreamMode),
1201 },
1202 }
1203 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1204 oFsm.pAdaptFsm.commChan, meParams)
1205 //accept also nil as (error) return value for writing to LastTx
1206 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001207 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001208
1209 //verify response
1210 err := oFsm.waitforOmciResponse()
1211 if err != nil {
1212 logger.Errorw("Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001213 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301214 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001215 return
1216 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001217 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001218
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001219 oFsm.mutexFlowParams.Lock()
mpagenko8b07c1b2020-11-26 10:36:31 +00001220 if uint8(len(oFsm.uniVlanFlowParamsSlice)) < aFlowEntryNo {
1221 //possibly the entry is not valid anymore based on intermediate delete requests
1222 //just a basic protection ...
1223 oFsm.mutexFlowParams.Unlock()
1224 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1225 go func(a_pAFsm *AdapterFsm) {
1226 _ = a_pAFsm.pFsm.Event(vlanEvReset)
1227 }(pConfigVlanStateAFsm)
1228 return
1229 }
1230
mpagenko01e726e2020-10-23 09:45:29 +00001231 if oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001232 //transparent transmission required
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001233 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001234 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001235 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001236 sliceEvtocdRule := make([]uint8, 16)
1237 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1238 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1239 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1240 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1241 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1242
1243 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1244 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1245 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1246 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1247 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1248
1249 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1250 0<<cTreatTTROffset| // Do not pop any tags
1251 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1252 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1253 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1254
1255 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1256 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1257 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1258 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1259
1260 meParams := me.ParamData{
1261 EntityID: oFsm.evtocdID,
1262 Attributes: me.AttributeValueMap{
1263 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1264 },
1265 }
1266 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1267 oFsm.pAdaptFsm.commChan, meParams)
1268 //accept also nil as (error) return value for writing to LastTx
1269 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001270 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001271
1272 //verify response
1273 err := oFsm.waitforOmciResponse()
1274 if err != nil {
1275 logger.Errorw("Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001276 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301277 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001278 return
1279 }
1280 } else {
1281 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1282 if oFsm.acceptIncrementalEvtoOption {
1283 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1284 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001285 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001286 sliceEvtocdRule := make([]uint8, 16)
1287 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1288 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1289 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1290 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1291 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1292
1293 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001294 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1295 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001296 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1297 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1298
1299 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001300 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001301 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1302 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1303 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1304
1305 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001306 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetPcp<<cTreatPrioOffset| // as configured in flow
1307 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001308 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001309 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001310
1311 meParams := me.ParamData{
1312 EntityID: oFsm.evtocdID,
1313 Attributes: me.AttributeValueMap{
1314 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1315 },
1316 }
1317 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1318 oFsm.pAdaptFsm.commChan, meParams)
1319 //accept also nil as (error) return value for writing to LastTx
1320 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001321 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001322
1323 //verify response
1324 err := oFsm.waitforOmciResponse()
1325 if err != nil {
1326 logger.Errorw("Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001327 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301328 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001329 return
1330 }
1331 } else {
1332 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1333 { // just for local var's
1334 // this defines stacking scenario: untagged->singletagged
1335 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001336 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001337 sliceEvtocdRule := make([]uint8, 16)
1338 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1339 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1340 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1341 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1342 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1343
1344 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1345 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1346 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1347 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1348 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1349
1350 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1351 0<<cTreatTTROffset| // Do not pop any tags
1352 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1353 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1354 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1355
1356 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1357 0<<cTreatPrioOffset| // vlan prio set to 0
1358 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko01e726e2020-10-23 09:45:29 +00001359 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001360 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1361
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001362 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001363 meParams := me.ParamData{
1364 EntityID: oFsm.evtocdID,
1365 Attributes: me.AttributeValueMap{
1366 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1367 },
1368 }
1369 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1370 oFsm.pAdaptFsm.commChan, meParams)
1371 //accept also nil as (error) return value for writing to LastTx
1372 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001373 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001374
1375 //verify response
1376 err := oFsm.waitforOmciResponse()
1377 if err != nil {
1378 logger.Errorw("Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001379 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301380 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001381 return
1382 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001383 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001384 { // just for local var's
1385 // this defines 'stacking' scenario: priotagged->singletagged
1386 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001387 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001388 sliceEvtocdRule := make([]uint8, 16)
1389 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1390 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1391 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1392 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1393 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1394
1395 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1396 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1397 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1398 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1399 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1400
1401 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1402 1<<cTreatTTROffset| // pop the prio-tag
1403 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1404 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1405 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1406
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001407 oFsm.mutexFlowParams.Lock()
mpagenkodff5dda2020-08-28 11:52:01 +00001408 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1409 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1410 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko01e726e2020-10-23 09:45:29 +00001411 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001412 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001413 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001414
1415 meParams := me.ParamData{
1416 EntityID: oFsm.evtocdID,
1417 Attributes: me.AttributeValueMap{
1418 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1419 },
1420 }
1421 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1422 oFsm.pAdaptFsm.commChan, meParams)
1423 //accept also nil as (error) return value for writing to LastTx
1424 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001425 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001426
1427 //verify response
1428 err := oFsm.waitforOmciResponse()
1429 if err != nil {
1430 logger.Errorw("Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001431 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301432 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001433 return
1434 }
1435 } //just for local var's
1436 }
1437 }
1438
mpagenkofc4f56e2020-11-04 17:17:49 +00001439 // if Config has been done for all EVTOCD entries let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001440 logger.Debugw("EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
1441 oFsm.configuredUniFlow++ // one (more) flow configured
Himani Chawla4d908332020-08-31 12:30:20 +05301442 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
mpagenkodff5dda2020-08-28 11:52:01 +00001443}
1444
mpagenko01e726e2020-10-23 09:45:29 +00001445func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(aRuleParams uniVlanRuleParams) {
1446 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1447 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1448 //transparent transmission was set
1449 //perhaps the config is not needed for removal,
1450 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
1451 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
1452 "device-id": oFsm.deviceID})
1453 sliceEvtocdRule := make([]uint8, 16)
1454 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1455 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1456 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1457 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1458 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1459
1460 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1461 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1462 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1463 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1464 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1465
1466 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1467 0<<cTreatTTROffset| // Do not pop any tags
1468 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1469 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1470 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1471
1472 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1473 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1474 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1475 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1476
1477 meParams := me.ParamData{
1478 EntityID: oFsm.evtocdID,
1479 Attributes: me.AttributeValueMap{
1480 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1481 },
1482 }
1483 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1484 oFsm.pAdaptFsm.commChan, meParams)
1485 //accept also nil as (error) return value for writing to LastTx
1486 // - this avoids misinterpretation of new received OMCI messages
1487 oFsm.pLastTxMeInstance = meInstance
1488
1489 //verify response
1490 err := oFsm.waitforOmciResponse()
1491 if err != nil {
1492 logger.Errorw("Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
1493 log.Fields{"device-id": oFsm.deviceID})
1494 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1495 return
1496 }
1497 } else {
1498 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1499 if oFsm.acceptIncrementalEvtoOption {
1500 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1501 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
1502 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1503 sliceEvtocdRule := make([]uint8, 16)
1504 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1505 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1506 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1507 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1508 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1509
1510 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1511 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1512 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1513 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1514 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1515
1516 // delete indication for the indicated Filter
1517 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1518 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1519
1520 meParams := me.ParamData{
1521 EntityID: oFsm.evtocdID,
1522 Attributes: me.AttributeValueMap{
1523 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1524 },
1525 }
1526 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1527 oFsm.pAdaptFsm.commChan, meParams)
1528 //accept also nil as (error) return value for writing to LastTx
1529 // - this avoids misinterpretation of new received OMCI messages
1530 oFsm.pLastTxMeInstance = meInstance
1531
1532 //verify response
1533 err := oFsm.waitforOmciResponse()
1534 if err != nil {
1535 logger.Errorw("Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
1536 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1537 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1538 return
1539 }
1540 } else {
1541 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1542 { // just for local var's
1543 // this defines stacking scenario: untagged->singletagged
1544 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1545 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1546 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1547 // delete now assumes there is only one such rule!
1548 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
1549 "device-id": oFsm.deviceID})
1550 sliceEvtocdRule := make([]uint8, 16)
1551 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1552 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1553 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1554 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1555 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1556
1557 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1558 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1559 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1560 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1561 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1562
1563 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1564 0<<cTreatTTROffset| // Do not pop any tags
1565 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1566 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1567 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1568
1569 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1570 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1571 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1572 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1573
1574 meParams := me.ParamData{
1575 EntityID: oFsm.evtocdID,
1576 Attributes: me.AttributeValueMap{
1577 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1578 },
1579 }
1580 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1581 oFsm.pAdaptFsm.commChan, meParams)
1582 //accept also nil as (error) return value for writing to LastTx
1583 // - this avoids misinterpretation of new received OMCI messages
1584 oFsm.pLastTxMeInstance = meInstance
1585
1586 //verify response
1587 err := oFsm.waitforOmciResponse()
1588 if err != nil {
1589 logger.Errorw("Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
1590 log.Fields{"device-id": oFsm.deviceID})
1591 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1592 return
1593 }
1594 } // just for local var's
1595 { // just for local var's
1596 // this defines 'stacking' scenario: priotagged->singletagged
1597 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
1598 "device-id": oFsm.deviceID})
1599 sliceEvtocdRule := make([]uint8, 16)
1600 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1601 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1602 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1603 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1604 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1605
1606 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1607 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1608 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1609 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1610 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1611
1612 // delete indication for the indicated Filter
1613 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1614 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1615
1616 meParams := me.ParamData{
1617 EntityID: oFsm.evtocdID,
1618 Attributes: me.AttributeValueMap{
1619 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1620 },
1621 }
1622 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1623 oFsm.pAdaptFsm.commChan, meParams)
1624 //accept also nil as (error) return value for writing to LastTx
1625 // - this avoids misinterpretation of new received OMCI messages
1626 oFsm.pLastTxMeInstance = meInstance
1627
1628 //verify response
1629 err := oFsm.waitforOmciResponse()
1630 if err != nil {
1631 logger.Errorw("Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
1632 log.Fields{"device-id": oFsm.deviceID})
1633 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1634 return
1635 }
1636 } //just for local var's
1637 }
1638 }
1639
mpagenkofc4f56e2020-11-04 17:17:49 +00001640 // if Config has been done for all EVTOCD entries let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001641 logger.Debugw("EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
1642 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone)
1643}
1644
mpagenkodff5dda2020-08-28 11:52:01 +00001645func (oFsm *UniVlanConfigFsm) waitforOmciResponse() error {
1646 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05301647 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00001648 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001649 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001650 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
mpagenko01e726e2020-10-23 09:45:29 +00001651 logger.Warnw("UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
1652 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001653 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301654 if success {
mpagenkodff5dda2020-08-28 11:52:01 +00001655 logger.Debug("UniVlanConfigFsm multi entity response received")
1656 return nil
1657 }
1658 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +00001659 logger.Warnw("UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
1660 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001661 }
1662}