blob: 561212c9634c0eb124212283a34670c02b7f0512 [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
mpagenko01e726e2020-10-23 09:45:29 +0000236 logger.Infow("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()
mpagenko01e726e2020-10-23 09:45:29 +0000611 if oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000612 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000613 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +0000614 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000615 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000616 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
617 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
618 pConfigVlanStateAFsm := oFsm.pAdaptFsm
619 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530620 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000621 }(pConfigVlanStateAFsm)
622 } else {
623 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
624 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000625 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
626 // setVid is assumed to be masked already by the caller to 12 bit
627 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000628 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000629 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000630 vtfdFilterList[0] = oFsm.vlanFilterList[0]
631 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000632 meParams := me.ParamData{
633 EntityID: oFsm.vtfdID,
634 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000635 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
636 "ForwardOperation": uint8(0x10), //VID investigation
637 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000638 },
639 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000640 logger.Debugw("UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000641 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000642 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
643 oFsm.pAdaptFsm.commChan, meParams)
644 //accept also nil as (error) return value for writing to LastTx
645 // - this avoids misinterpretation of new received OMCI messages
646 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
647 // send shall return (dual format) error code that can be used here for immediate error treatment
648 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000649 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000650 }
651}
652
653func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(e *fsm.Event) {
654 logger.Debugw("UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000655 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000656 oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000657 go oFsm.performConfigEvtocdEntries(0)
mpagenkodff5dda2020-08-28 11:52:01 +0000658}
659
660func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000661 logger.Debugw("UniVlanConfigFsm - checking on more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000662 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
663 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
664 if len(oFsm.uniRemoveFlowsSlice) > 0 {
665 //some further flows are to be removed, removal always starts with the first element
666 // calling some FSM event must be decoupled
667 go func(a_pBaseFsm *fsm.FSM) {
668 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
669 }(pConfigVlanStateBaseFsm)
670 return
671 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000672 if oFsm.numUniFlows > oFsm.configuredUniFlow {
673 //some further flows are to be configured
674 // calling some FSM event must be decoupled
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000675 go func(a_pBaseFsm *fsm.FSM) {
676 _ = a_pBaseFsm.Event(vlanEvIncrFlowConfig)
677 }(pConfigVlanStateBaseFsm)
678 return
679 }
680
681 logger.Debugw("UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000682 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000683 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
684 // state transition notification is checked in deviceHandler
mpagenkodff5dda2020-08-28 11:52:01 +0000685 if oFsm.pDeviceHandler != nil {
mpagenkofc4f56e2020-11-04 17:17:49 +0000686 //making use of the add->remove successor enum assumption/definition
Girish Gowdra041dcb32020-11-16 16:54:30 -0800687 go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent(uint8(oFsm.requestEvent) + oFsm.requestEventOffset))
mpagenkodff5dda2020-08-28 11:52:01 +0000688 }
689}
690
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000691func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(e *fsm.Event) {
692 logger.Debugw("UniVlanConfigFsm - start config further incremental flow", log.Fields{
Girish Gowdra041dcb32020-11-16 16:54:30 -0800693 "in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000694 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000695 oFsm.mutexFlowParams.Lock()
696
mpagenkofc4f56e2020-11-04 17:17:49 +0000697 if oFsm.configuredUniFlow == 0 {
698 oFsm.mutexFlowParams.Unlock()
699 // this is a restart with a complete new flow, we can re-use the initial flow config control
700 // including the check, if the related techProfile is (still) available (probably also removed in between)
701 // calling some FSM event must be decoupled
702 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
703 go func(a_pBaseFsm *fsm.FSM) {
704 _ = a_pBaseFsm.Event(vlanEvRenew)
705 }(pConfigVlanStateBaseFsm)
706 return
707 }
708
mpagenko01e726e2020-10-23 09:45:29 +0000709 if oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000710 // meaning transparent setup - no specific VTFD setting required
711 oFsm.mutexFlowParams.Unlock()
712 logger.Debugw("UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000713 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000714 } else {
715 if oFsm.numVlanFilterEntries == 0 {
716 //no VTFD yet created
717 logger.Debugw("UniVlanConfigFsm create VTFD", log.Fields{
718 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000719 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
720 // setVid is assumed to be masked already by the caller to 12 bit
721 oFsm.vlanFilterList[0] = uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000722 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000723 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000724 vtfdFilterList[0] = oFsm.vlanFilterList[0]
725 oFsm.numVlanFilterEntries = 1
726 meParams := me.ParamData{
727 EntityID: oFsm.vtfdID,
728 Attributes: me.AttributeValueMap{
729 "VlanFilterList": vtfdFilterList,
730 "ForwardOperation": uint8(0x10), //VID investigation
731 "NumberOfEntries": oFsm.numVlanFilterEntries,
732 },
733 }
734 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
735 oFsm.pAdaptFsm.commChan, meParams)
736 //accept also nil as (error) return value for writing to LastTx
737 // - this avoids misinterpretation of new received OMCI messages
738 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
739 // send shall return (dual format) error code that can be used here for immediate error treatment
740 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000741 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000742 } else {
743 //VTFD already exists - just modify by 'set'
744 //TODO!!: but only if the VID is not already present, skipped by now to test basic working
745 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
746 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000747 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000748 // setVid is assumed to be masked already by the caller to 12 bit
749 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko01e726e2020-10-23 09:45:29 +0000750 uint16(oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000751 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000752 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000753 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
754 vtfdFilterList[i] = oFsm.vlanFilterList[i]
755 }
756
757 oFsm.numVlanFilterEntries++
758 meParams := me.ParamData{
759 EntityID: oFsm.vtfdID,
760 Attributes: me.AttributeValueMap{
761 "VlanFilterList": vtfdFilterList,
762 "NumberOfEntries": oFsm.numVlanFilterEntries,
763 },
764 }
765 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
766 oFsm.pAdaptFsm.commChan, meParams)
767 //accept also nil as (error) return value for writing to LastTx
768 // - this avoids misinterpretation of new received OMCI messages
769 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
770 // send shall return (dual format) error code that can be used here for immediate error treatment
771 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000772 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000773 }
774 //verify response
775 err := oFsm.waitforOmciResponse()
776 if err != nil {
777 logger.Errorw("VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +0000778 log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000779 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
780 go func(a_pBaseFsm *fsm.FSM) {
781 _ = a_pBaseFsm.Event(vlanEvReset)
782 }(pConfigVlanStateBaseFsm)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000783 return
784 }
785 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000786 oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000787 go oFsm.performConfigEvtocdEntries(oFsm.configuredUniFlow)
788}
789
mpagenko01e726e2020-10-23 09:45:29 +0000790func (oFsm *UniVlanConfigFsm) enterRemoveFlow(e *fsm.Event) {
791 oFsm.mutexFlowParams.Lock()
792 logger.Debugw("UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
793 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
794 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000795
mpagenkofc4f56e2020-11-04 17:17:49 +0000796 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
797 loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
mpagenko01e726e2020-10-23 09:45:29 +0000798 loVlanEntryClear := uint8(0)
799 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
800 //shallow copy is sufficient as no reference variables are used within struct
801 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
802 oFsm.mutexFlowParams.Unlock()
803 logger.Debugw("UniVlanConfigFsm - remove-flow parameters are", log.Fields{
804 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
805 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
806 "device-id": oFsm.deviceID})
807
808 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
809 // meaning transparent setup - no specific VTFD setting required
810 logger.Debugw("UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
811 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
812 } else {
813 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
814 if oFsm.numVlanFilterEntries == 1 {
815 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
816 // so we can just delete the VTFD entry
817 logger.Debugw("UniVlanConfigFsm: VTFD delete (no more vlan filters)",
818 log.Fields{"current vlan list": oFsm.vlanFilterList,
819 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000820 loVlanEntryClear = 1 //full VlanFilter clear request
821 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
822 meInstance := oFsm.pOmciCC.sendDeleteVtfd(context.TODO(), ConstDefaultOmciTimeout, true,
823 oFsm.pAdaptFsm.commChan, oFsm.vtfdID)
824 oFsm.pLastTxMeInstance = meInstance
825 } else {
826 logger.Debugw("UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
827 "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.deviceReason})
828 }
mpagenko01e726e2020-10-23 09:45:29 +0000829 } else {
830 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
831 // by updating the VTFD per set command with new valid list
832 logger.Debugw("UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
833 log.Fields{"current vlan list": oFsm.vlanFilterList,
834 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
835 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
836 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
837 loVlanEntryRmPos = i
838 break //abort search
839 }
840 }
841 if loVlanEntryRmPos < cVtfdTableSize {
842 //valid entry was found - to be eclipsed
843 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
844 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
845 if i < loVlanEntryRmPos {
846 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
847 } else if i < (cVtfdTableSize - 1) {
848 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
849 } else {
850 vtfdFilterList[i] = 0 //set last byte if needed
851 }
852 }
853 logger.Debugw("UniVlanConfigFsm set VTFD", log.Fields{
854 "EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
855 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
856
mpagenkofc4f56e2020-11-04 17:17:49 +0000857 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
858 meParams := me.ParamData{
859 EntityID: oFsm.vtfdID,
860 Attributes: me.AttributeValueMap{
861 "VlanFilterList": vtfdFilterList,
Girish Gowdra041dcb32020-11-16 16:54:30 -0800862 "NumberOfEntries": oFsm.numVlanFilterEntries - 1, //one element less
mpagenkofc4f56e2020-11-04 17:17:49 +0000863 },
864 }
865 meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
866 oFsm.pAdaptFsm.commChan, meParams)
867 oFsm.pLastTxMeInstance = meInstance
868 } else {
869 logger.Debugw("UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
870 "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.deviceReason})
mpagenko01e726e2020-10-23 09:45:29 +0000871 }
mpagenko01e726e2020-10-23 09:45:29 +0000872 } else {
873 logger.Warnw("UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
874 log.Fields{"device-id": oFsm.deviceID})
875 }
876 }
877 if loVlanEntryClear > 0 {
mpagenkofc4f56e2020-11-04 17:17:49 +0000878 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
879 //waiting on response
880 err := oFsm.waitforOmciResponse()
881 if err != nil {
882 logger.Errorw("VTFD delete/reset failed, aborting VlanConfig FSM!",
883 log.Fields{"device-id": oFsm.deviceID})
884 // calling some FSM event must be decoupled
885 go func(a_pBaseFsm *fsm.FSM) {
886 _ = a_pBaseFsm.Event(vlanEvReset)
887 }(pConfigVlanStateBaseFsm)
888 return
889 }
mpagenko01e726e2020-10-23 09:45:29 +0000890 }
891
892 if loVlanEntryClear == 1 {
893 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
894 oFsm.numVlanFilterEntries = 0
895 } else if loVlanEntryClear == 2 {
896 // new VlanFilterList should be one entry smaller now - copy from last configured entry
897 // this loop now includes the 0 element on previous last valid entry
898 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
899 oFsm.vlanFilterList[i] = vtfdFilterList[i]
900 }
901 oFsm.numVlanFilterEntries--
902 }
903 }
904 }
905
mpagenkofc4f56e2020-11-04 17:17:49 +0000906 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
907 go oFsm.removeEvtocdEntries(loRuleParams)
908 } else {
909 // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
910 logger.Debugw("UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
911 "device-id": oFsm.deviceID})
912 // calling some FSM event must be decoupled
913 go func(a_pBaseFsm *fsm.FSM) {
914 _ = a_pBaseFsm.Event(vlanEvRemFlowDone)
915 }(pConfigVlanStateBaseFsm)
916 }
mpagenkodff5dda2020-08-28 11:52:01 +0000917}
918
919func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000920 logger.Debugw("UniVlanConfigFsm - removing the removal data", log.Fields{
921 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000922
mpagenko01e726e2020-10-23 09:45:29 +0000923 oFsm.mutexFlowParams.Lock()
924 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
925 oFsm.uniRemoveFlowsSlice = nil //reset the slice
926 logger.Debugw("UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
927 "device-id": oFsm.deviceID})
928 } else {
929 //cut off the actual flow by slicing out the first element
930 oFsm.uniRemoveFlowsSlice = append(
931 oFsm.uniRemoveFlowsSlice[:0],
932 oFsm.uniRemoveFlowsSlice[1:]...)
933 logger.Debugw("UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
934 "device-id": oFsm.deviceID})
935 }
936 oFsm.mutexFlowParams.Unlock()
937
mpagenkofc4f56e2020-11-04 17:17:49 +0000938 oFsm.requestEventOffset = 1 //offset 1 for last flow-remove activity
mpagenko01e726e2020-10-23 09:45:29 +0000939 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +0000940 pConfigVlanStateAFsm := oFsm.pAdaptFsm
941 if pConfigVlanStateAFsm != nil {
942 // obviously calling some FSM event here directly does not work - so trying to decouple it ...
943 go func(a_pAFsm *AdapterFsm) {
944 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +0000945 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +0000946 }
947 }(pConfigVlanStateAFsm)
948 }
949}
950
951func (oFsm *UniVlanConfigFsm) enterResetting(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000952 logger.Debugw("UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000953
954 pConfigVlanStateAFsm := oFsm.pAdaptFsm
955 if pConfigVlanStateAFsm != nil {
956 // abort running message processing
957 fsmAbortMsg := Message{
958 Type: TestMsg,
959 Data: TestMessage{
960 TestMessageVal: AbortMessageProcessing,
961 },
962 }
963 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
964
965 //try to restart the FSM to 'disabled', decouple event transfer
966 go func(a_pAFsm *AdapterFsm) {
967 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +0530968 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +0000969 }
970 }(pConfigVlanStateAFsm)
971 }
972}
973
974func (oFsm *UniVlanConfigFsm) enterDisabled(e *fsm.Event) {
mpagenko01e726e2020-10-23 09:45:29 +0000975 logger.Debugw("UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
976 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +0000977 if oFsm.pDeviceHandler != nil {
mpagenko2418ab02020-11-12 12:58:06 +0000978 //TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
979 // current code removes the complete FSM including all flow/rule configuration done so far
980 // this might be a bit to much, it would require fully new flow config from rwCore (at least on OnuDown/up)
981 // maybe a more sophisticated approach is possible without clearing the data
982 if oFsm.clearPersistency {
983 //permanently remove possibly stored persistent data
984 if len(oFsm.uniVlanFlowParamsSlice) > 0 {
985 var emptySlice = make([]uniVlanFlowParams, 0)
986 _ = oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &emptySlice) //ignore errors
987 }
988 } else {
989 logger.Debugw("UniVlanConfigFsm persistency data not cleared", log.Fields{"device-id": oFsm.deviceID})
990 }
991 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
mpagenkodff5dda2020-08-28 11:52:01 +0000992 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(oFsm.pOnuUniPort)
993 }
994}
995
996func (oFsm *UniVlanConfigFsm) processOmciVlanMessages() { //ctx context.Context?
mpagenko01e726e2020-10-23 09:45:29 +0000997 logger.Debugw("Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000998loop:
999 for {
mpagenkodff5dda2020-08-28 11:52:01 +00001000 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001001 // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001002 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301003 message, ok := <-oFsm.pAdaptFsm.commChan
1004 if !ok {
mpagenko01e726e2020-10-23 09:45:29 +00001005 logger.Info("UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301006 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1007 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1008 break loop
1009 }
mpagenko01e726e2020-10-23 09:45:29 +00001010 logger.Debugw("UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301011
1012 switch message.Type {
1013 case TestMsg:
1014 msg, _ := message.Data.(TestMessage)
1015 if msg.TestMessageVal == AbortMessageProcessing {
mpagenko01e726e2020-10-23 09:45:29 +00001016 logger.Infow("UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001017 break loop
1018 }
mpagenko01e726e2020-10-23 09:45:29 +00001019 logger.Warnw("UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301020 case OMCI:
1021 msg, _ := message.Data.(OmciMessage)
1022 oFsm.handleOmciVlanConfigMessage(msg)
1023 default:
mpagenko01e726e2020-10-23 09:45:29 +00001024 logger.Warn("UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301025 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +00001026 }
1027 }
mpagenko01e726e2020-10-23 09:45:29 +00001028 logger.Infow("End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001029}
1030
1031func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(msg OmciMessage) {
mpagenko01e726e2020-10-23 09:45:29 +00001032 logger.Debugw("Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001033 "msgType": msg.OmciMsg.MessageType})
1034
1035 switch msg.OmciMsg.MessageType {
1036 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001037 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
1038 if err := oFsm.handleOmciCreateResponseMessage(msg.OmciPacket); err != nil {
1039 logger.Warnw("CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +00001040 return
1041 }
mpagenkodff5dda2020-08-28 11:52:01 +00001042 } //CreateResponseType
1043 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001044 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +00001045 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1046 if msgLayer == nil {
mpagenko01e726e2020-10-23 09:45:29 +00001047 logger.Errorw("Omci Msg layer could not be detected for SetResponse",
1048 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001049 return
1050 }
1051 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1052 if !msgOk {
mpagenko01e726e2020-10-23 09:45:29 +00001053 logger.Errorw("Omci Msg layer could not be assigned for SetResponse",
1054 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001055 return
1056 }
mpagenko01e726e2020-10-23 09:45:29 +00001057 logger.Debugw("UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +00001058 if msgObj.Result != me.Success {
mpagenko01e726e2020-10-23 09:45:29 +00001059 logger.Errorw("UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
1060 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +00001061 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1062 return
1063 }
mpagenko01e726e2020-10-23 09:45:29 +00001064 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1065 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1066 switch oFsm.pLastTxMeInstance.GetName() {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001067 case "VlanTaggingFilterData",
1068 "ExtendedVlanTaggingOperationConfigurationData":
1069 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +00001070 oFsm.omciMIdsResponseReceived <- true
1071 }
1072 }
1073 }
1074 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +00001075 case omci.DeleteResponseType:
1076 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
1077 if err := oFsm.handleOmciDeleteResponseMessage(msg.OmciPacket); err != nil {
1078 logger.Warnw("DeleteResponse handling aborted", log.Fields{"err": err})
1079 return
1080 }
1081 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +00001082 default:
1083 {
mpagenko01e726e2020-10-23 09:45:29 +00001084 logger.Errorw("Rx OMCI unhandled MsgType",
1085 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001086 return
1087 }
1088 }
1089}
1090
mpagenko01e726e2020-10-23 09:45:29 +00001091func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(apOmciPacket *gp.Packet) error {
1092 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
1093 if msgLayer == nil {
1094 logger.Errorw("Omci Msg layer could not be detected for CreateResponse",
1095 log.Fields{"device-id": oFsm.deviceID})
1096 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
1097 oFsm.deviceID)
1098 }
1099 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1100 if !msgOk {
1101 logger.Errorw("Omci Msg layer could not be assigned for CreateResponse",
1102 log.Fields{"device-id": oFsm.deviceID})
1103 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
1104 oFsm.deviceID)
1105 }
1106 logger.Debugw("UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
1107 if msgObj.Result != me.Success {
1108 logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
1109 "Error": msgObj.Result})
1110 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1111 return fmt.Errorf("omci CreateResponse Error for device-id %x",
1112 oFsm.deviceID)
1113 }
1114 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1115 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1116 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
1117 switch oFsm.pLastTxMeInstance.GetName() {
1118 case "VlanTaggingFilterData":
1119 {
1120 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
1121 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
1122 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
1123 } else { // let the MultiEntity config proceed by stopping the wait function
1124 oFsm.omciMIdsResponseReceived <- true
1125 }
1126 }
1127 }
1128 }
1129 return nil
1130}
1131
1132func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(apOmciPacket *gp.Packet) error {
1133 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1134 if msgLayer == nil {
1135 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
1136 log.Fields{"device-id": oFsm.deviceID})
1137 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1138 oFsm.deviceID)
1139 }
1140 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1141 if !msgOk {
1142 logger.Errorw("UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
1143 log.Fields{"device-id": oFsm.deviceID})
1144 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1145 oFsm.deviceID)
1146 }
1147 logger.Debugw("UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
1148 if msgObj.Result != me.Success {
1149 logger.Errorw("UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
1150 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1151 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1152 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1153 oFsm.deviceID)
1154 }
1155 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1156 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1157 switch oFsm.pLastTxMeInstance.GetName() {
1158 case "VlanTaggingFilterData":
1159 { // let the MultiEntity config proceed by stopping the wait function
1160 oFsm.omciMIdsResponseReceived <- true
1161 }
1162 }
1163 }
1164 return nil
1165}
1166
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001167func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(aFlowEntryNo uint8) {
1168 if aFlowEntryNo == 0 {
1169 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001170 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1171 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
1172 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD", log.Fields{
1173 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1174 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001175 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001176 meParams := me.ParamData{
1177 EntityID: oFsm.evtocdID,
1178 Attributes: me.AttributeValueMap{
1179 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1180 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1181 "DownstreamMode": uint8(cDefaultDownstreamMode),
1182 },
1183 }
1184 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1185 oFsm.pAdaptFsm.commChan, meParams)
1186 //accept also nil as (error) return value for writing to LastTx
1187 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001188 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001189
1190 //verify response
1191 err := oFsm.waitforOmciResponse()
1192 if err != nil {
1193 logger.Errorw("Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001194 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301195 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001196 return
1197 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001198 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001199
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001200 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +00001201 if oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001202 //transparent transmission required
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001203 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001204 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001205 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001206 sliceEvtocdRule := make([]uint8, 16)
1207 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1208 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1209 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1210 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1211 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1212
1213 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1214 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1215 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1216 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1217 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1218
1219 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1220 0<<cTreatTTROffset| // Do not pop any tags
1221 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1222 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1223 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1224
1225 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1226 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1227 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1228 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1229
1230 meParams := me.ParamData{
1231 EntityID: oFsm.evtocdID,
1232 Attributes: me.AttributeValueMap{
1233 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1234 },
1235 }
1236 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1237 oFsm.pAdaptFsm.commChan, meParams)
1238 //accept also nil as (error) return value for writing to LastTx
1239 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001240 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001241
1242 //verify response
1243 err := oFsm.waitforOmciResponse()
1244 if err != nil {
1245 logger.Errorw("Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001246 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301247 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001248 return
1249 }
1250 } else {
1251 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1252 if oFsm.acceptIncrementalEvtoOption {
1253 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1254 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001255 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001256 sliceEvtocdRule := make([]uint8, 16)
1257 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1258 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1259 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1260 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1261 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1262
1263 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001264 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1265 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001266 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1267 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1268
1269 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001270 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001271 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1272 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1273 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1274
1275 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko01e726e2020-10-23 09:45:29 +00001276 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetPcp<<cTreatPrioOffset| // as configured in flow
1277 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001278 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001279 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001280
1281 meParams := me.ParamData{
1282 EntityID: oFsm.evtocdID,
1283 Attributes: me.AttributeValueMap{
1284 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1285 },
1286 }
1287 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1288 oFsm.pAdaptFsm.commChan, meParams)
1289 //accept also nil as (error) return value for writing to LastTx
1290 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001291 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001292
1293 //verify response
1294 err := oFsm.waitforOmciResponse()
1295 if err != nil {
1296 logger.Errorw("Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001297 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301298 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001299 return
1300 }
1301 } else {
1302 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1303 { // just for local var's
1304 // this defines stacking scenario: untagged->singletagged
1305 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001306 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001307 sliceEvtocdRule := make([]uint8, 16)
1308 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1309 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1310 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1311 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1312 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1313
1314 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1315 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1316 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1317 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1318 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1319
1320 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1321 0<<cTreatTTROffset| // Do not pop any tags
1322 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1323 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1324 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1325
1326 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1327 0<<cTreatPrioOffset| // vlan prio set to 0
1328 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko01e726e2020-10-23 09:45:29 +00001329 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001330 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1331
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001332 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001333 meParams := me.ParamData{
1334 EntityID: oFsm.evtocdID,
1335 Attributes: me.AttributeValueMap{
1336 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1337 },
1338 }
1339 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1340 oFsm.pAdaptFsm.commChan, meParams)
1341 //accept also nil as (error) return value for writing to LastTx
1342 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001343 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001344
1345 //verify response
1346 err := oFsm.waitforOmciResponse()
1347 if err != nil {
1348 logger.Errorw("Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001349 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301350 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001351 return
1352 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001353 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001354 { // just for local var's
1355 // this defines 'stacking' scenario: priotagged->singletagged
1356 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001357 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001358 sliceEvtocdRule := make([]uint8, 16)
1359 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1360 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1361 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1362 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1363 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1364
1365 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1366 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1367 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1368 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1369 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1370
1371 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1372 1<<cTreatTTROffset| // pop the prio-tag
1373 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1374 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1375 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1376
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001377 oFsm.mutexFlowParams.Lock()
mpagenkodff5dda2020-08-28 11:52:01 +00001378 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1379 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1380 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko01e726e2020-10-23 09:45:29 +00001381 oFsm.uniVlanFlowParamsSlice[aFlowEntryNo].VlanRuleParams.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001382 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001383 oFsm.mutexFlowParams.Unlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001384
1385 meParams := me.ParamData{
1386 EntityID: oFsm.evtocdID,
1387 Attributes: me.AttributeValueMap{
1388 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1389 },
1390 }
1391 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1392 oFsm.pAdaptFsm.commChan, meParams)
1393 //accept also nil as (error) return value for writing to LastTx
1394 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001395 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001396
1397 //verify response
1398 err := oFsm.waitforOmciResponse()
1399 if err != nil {
1400 logger.Errorw("Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001401 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301402 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
mpagenkodff5dda2020-08-28 11:52:01 +00001403 return
1404 }
1405 } //just for local var's
1406 }
1407 }
1408
mpagenkofc4f56e2020-11-04 17:17:49 +00001409 // if Config has been done for all EVTOCD entries let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001410 logger.Debugw("EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
1411 oFsm.configuredUniFlow++ // one (more) flow configured
Himani Chawla4d908332020-08-31 12:30:20 +05301412 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
mpagenkodff5dda2020-08-28 11:52:01 +00001413}
1414
mpagenko01e726e2020-10-23 09:45:29 +00001415func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(aRuleParams uniVlanRuleParams) {
1416 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1417 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1418 //transparent transmission was set
1419 //perhaps the config is not needed for removal,
1420 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
1421 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
1422 "device-id": oFsm.deviceID})
1423 sliceEvtocdRule := make([]uint8, 16)
1424 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1425 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1426 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1427 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1428 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1429
1430 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1431 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1432 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1433 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1434 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1435
1436 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1437 0<<cTreatTTROffset| // Do not pop any tags
1438 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1439 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1440 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1441
1442 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1443 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1444 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1445 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1446
1447 meParams := me.ParamData{
1448 EntityID: oFsm.evtocdID,
1449 Attributes: me.AttributeValueMap{
1450 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1451 },
1452 }
1453 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1454 oFsm.pAdaptFsm.commChan, meParams)
1455 //accept also nil as (error) return value for writing to LastTx
1456 // - this avoids misinterpretation of new received OMCI messages
1457 oFsm.pLastTxMeInstance = meInstance
1458
1459 //verify response
1460 err := oFsm.waitforOmciResponse()
1461 if err != nil {
1462 logger.Errorw("Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
1463 log.Fields{"device-id": oFsm.deviceID})
1464 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1465 return
1466 }
1467 } else {
1468 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1469 if oFsm.acceptIncrementalEvtoOption {
1470 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
1471 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
1472 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1473 sliceEvtocdRule := make([]uint8, 16)
1474 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1475 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1476 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1477 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1478 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1479
1480 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1481 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1482 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1483 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1484 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1485
1486 // delete indication for the indicated Filter
1487 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1488 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1489
1490 meParams := me.ParamData{
1491 EntityID: oFsm.evtocdID,
1492 Attributes: me.AttributeValueMap{
1493 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1494 },
1495 }
1496 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1497 oFsm.pAdaptFsm.commChan, meParams)
1498 //accept also nil as (error) return value for writing to LastTx
1499 // - this avoids misinterpretation of new received OMCI messages
1500 oFsm.pLastTxMeInstance = meInstance
1501
1502 //verify response
1503 err := oFsm.waitforOmciResponse()
1504 if err != nil {
1505 logger.Errorw("Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
1506 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1507 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1508 return
1509 }
1510 } else {
1511 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1512 { // just for local var's
1513 // this defines stacking scenario: untagged->singletagged
1514 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1515 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1516 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1517 // delete now assumes there is only one such rule!
1518 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
1519 "device-id": oFsm.deviceID})
1520 sliceEvtocdRule := make([]uint8, 16)
1521 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1522 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1523 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1524 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1525 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1526
1527 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1528 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1529 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1530 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1531 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1532
1533 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1534 0<<cTreatTTROffset| // Do not pop any tags
1535 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1536 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1537 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1538
1539 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1540 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1541 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1542 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1543
1544 meParams := me.ParamData{
1545 EntityID: oFsm.evtocdID,
1546 Attributes: me.AttributeValueMap{
1547 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1548 },
1549 }
1550 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1551 oFsm.pAdaptFsm.commChan, meParams)
1552 //accept also nil as (error) return value for writing to LastTx
1553 // - this avoids misinterpretation of new received OMCI messages
1554 oFsm.pLastTxMeInstance = meInstance
1555
1556 //verify response
1557 err := oFsm.waitforOmciResponse()
1558 if err != nil {
1559 logger.Errorw("Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
1560 log.Fields{"device-id": oFsm.deviceID})
1561 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1562 return
1563 }
1564 } // just for local var's
1565 { // just for local var's
1566 // this defines 'stacking' scenario: priotagged->singletagged
1567 logger.Debugw("UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
1568 "device-id": oFsm.deviceID})
1569 sliceEvtocdRule := make([]uint8, 16)
1570 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1571 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1572 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1573 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1574 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1575
1576 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1577 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1578 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1579 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1580 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1581
1582 // delete indication for the indicated Filter
1583 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1584 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1585
1586 meParams := me.ParamData{
1587 EntityID: oFsm.evtocdID,
1588 Attributes: me.AttributeValueMap{
1589 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1590 },
1591 }
1592 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1593 oFsm.pAdaptFsm.commChan, meParams)
1594 //accept also nil as (error) return value for writing to LastTx
1595 // - this avoids misinterpretation of new received OMCI messages
1596 oFsm.pLastTxMeInstance = meInstance
1597
1598 //verify response
1599 err := oFsm.waitforOmciResponse()
1600 if err != nil {
1601 logger.Errorw("Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
1602 log.Fields{"device-id": oFsm.deviceID})
1603 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1604 return
1605 }
1606 } //just for local var's
1607 }
1608 }
1609
mpagenkofc4f56e2020-11-04 17:17:49 +00001610 // if Config has been done for all EVTOCD entries let the FSM proceed
mpagenko01e726e2020-10-23 09:45:29 +00001611 logger.Debugw("EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
1612 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone)
1613}
1614
mpagenkodff5dda2020-08-28 11:52:01 +00001615func (oFsm *UniVlanConfigFsm) waitforOmciResponse() error {
1616 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05301617 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00001618 // case <-ctx.Done():
mpagenko01e726e2020-10-23 09:45:29 +00001619 // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001620 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
mpagenko01e726e2020-10-23 09:45:29 +00001621 logger.Warnw("UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
1622 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001623 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05301624 if success {
mpagenkodff5dda2020-08-28 11:52:01 +00001625 logger.Debug("UniVlanConfigFsm multi entity response received")
1626 return nil
1627 }
1628 // should not happen so far
mpagenko01e726e2020-10-23 09:45:29 +00001629 logger.Warnw("UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
1630 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00001631 }
1632}