blob: 3a33a0f8812abedc232e8ff64f81dee86feaa8bf [file] [log] [blame]
mpagenkodff5dda2020-08-28 11:52:01 +00001/*
2 * Copyright 2020-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//Package adaptercoreonu provides the utility for onu devices, flows and statistics
18package adaptercoreonu
19
20import (
21 "context"
22 "encoding/binary"
Andrea Campanella6515c582020-10-05 11:25:00 +020023 "fmt"
ozgecanetsiab5000ef2020-11-27 14:38:20 +030024 "net"
mpagenkodff5dda2020-08-28 11:52:01 +000025 "strconv"
Holger Hildebrandt394c5522020-09-11 11:23:01 +000026 "sync"
mpagenkodff5dda2020-08-28 11:52:01 +000027 "time"
28
mpagenko01e726e2020-10-23 09:45:29 +000029 gp "github.com/google/gopacket"
mpagenkodff5dda2020-08-28 11:52:01 +000030 "github.com/looplab/fsm"
31 "github.com/opencord/omci-lib-go"
32 me "github.com/opencord/omci-lib-go/generated"
dbainbri4d3a0dc2020-12-02 00:33:42 +000033 "github.com/opencord/voltha-lib-go/v4/pkg/log"
34 of "github.com/opencord/voltha-protos/v4/go/openflow_13"
mpagenkodff5dda2020-08-28 11:52:01 +000035)
36
37const (
38 // internal predefined values
mpagenkof1fc3862021-02-16 10:09:52 +000039 cWaitForCookieDeletion = 3 //seconds
mpagenkodff5dda2020-08-28 11:52:01 +000040 cDefaultDownstreamMode = 0
41 cDefaultTpid = 0x8100
mpagenko01e726e2020-10-23 09:45:29 +000042 cVtfdTableSize = 12 //as per G.988
43 cMaxAllowedFlows = cVtfdTableSize //which might be under discussion, for the moment connected to limit of VLAN's within VTFD
mpagenkodff5dda2020-08-28 11:52:01 +000044)
45
46const (
mpagenkof1fc3862021-02-16 10:09:52 +000047 // internal offsets for requestEvent according to definition in onu_device_entry::OnuDeviceEvent
48 cDeviceEventOffsetAddWithKvStore = 0 //OmciVlanFilterAddDone - OmciVlanFilterAddDone cannot use because of lint
49 cDeviceEventOffsetAddNoKvStore = OmciVlanFilterAddDoneNoKvStore - OmciVlanFilterAddDone
50 cDeviceEventOffsetRemoveWithKvStore = OmciVlanFilterRemDone - OmciVlanFilterAddDone
51 cDeviceEventOffsetRemoveNoKvStore = OmciVlanFilterRemDoneNoKvStore - OmciVlanFilterAddDone
52)
53
54const (
mpagenkodff5dda2020-08-28 11:52:01 +000055 // bit mask offsets for EVTOCD VlanTaggingOperationTable related to 32 bits (4 bytes)
56 cFilterPrioOffset = 28
57 cFilterVidOffset = 15
58 cFilterTpidOffset = 12
59 cFilterEtherTypeOffset = 0
60 cTreatTTROffset = 30
61 cTreatPrioOffset = 16
62 cTreatVidOffset = 3
63 cTreatTpidOffset = 0
64)
65const (
66 // byte offsets for EVTOCD VlanTaggingOperationTable related to overall 16 byte size with slice byte 0 as first Byte (MSB)
67 cFilterOuterOffset = 0
68 cFilterInnerOffset = 4
69 cTreatOuterOffset = 8
70 cTreatInnerOffset = 12
71)
72const (
73 // basic values used within EVTOCD VlanTaggingOperationTable in respect to their bitfields
74 cPrioIgnoreTag uint32 = 15
75 cPrioDefaultFilter uint32 = 14
76 cPrioDoNotFilter uint32 = 8
77 cDoNotFilterVid uint32 = 4096
78 cDoNotFilterTPID uint32 = 0
79 cDoNotFilterEtherType uint32 = 0
80 cDoNotAddPrio uint32 = 15
81 cCopyPrioFromInner uint32 = 8
Himani Chawla4d908332020-08-31 12:30:20 +053082 //cDontCarePrio uint32 = 0
mpagenkodff5dda2020-08-28 11:52:01 +000083 cDontCareVid uint32 = 0
84 cDontCareTpid uint32 = 0
85 cSetOutputTpidCopyDei uint32 = 4
86)
87
88const (
Holger Hildebrandt10d98192021-01-27 15:29:31 +000089 // events of config UNI port VLAN FSM
mpagenko535d6ef2021-02-26 13:15:34 +000090 vlanEvStart = "vlanEvStart"
91 vlanEvWaitTechProf = "vlanEvWaitTechProf"
92 vlanEvCancelOutstandingConfig = "vlanEvCancelOutstandingConfig"
93 vlanEvContinueConfig = "vlanEvContinueConfig"
94 vlanEvStartConfig = "vlanEvStartConfig"
95 vlanEvRxConfigVtfd = "vlanEvRxConfigVtfd"
96 vlanEvRxConfigEvtocd = "vlanEvRxConfigEvtocd"
97 vlanEvWaitTPIncr = "vlanEvWaitTPIncr"
98 vlanEvIncrFlowConfig = "vlanEvIncrFlowConfig"
99 vlanEvRenew = "vlanEvRenew"
100 vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
101 vlanEvRemFlowDone = "vlanEvRemFlowDone"
102 vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000103 //vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
104 //vlanEvTimeoutMids = "vlanEvTimeoutMids"
Himani Chawla4d908332020-08-31 12:30:20 +0530105 vlanEvReset = "vlanEvReset"
106 vlanEvRestart = "vlanEvRestart"
mpagenkodff5dda2020-08-28 11:52:01 +0000107)
mpagenko01e726e2020-10-23 09:45:29 +0000108
mpagenkodff5dda2020-08-28 11:52:01 +0000109const (
Holger Hildebrandt10d98192021-01-27 15:29:31 +0000110 // states of config UNI port VLAN FSM
mpagenkodff5dda2020-08-28 11:52:01 +0000111 vlanStDisabled = "vlanStDisabled"
112 vlanStStarting = "vlanStStarting"
113 vlanStWaitingTechProf = "vlanStWaitingTechProf"
114 vlanStConfigVtfd = "vlanStConfigVtfd"
115 vlanStConfigEvtocd = "vlanStConfigEvtocd"
116 vlanStConfigDone = "vlanStConfigDone"
mpagenko551a4d42020-12-08 18:09:20 +0000117 vlanStIncrFlowWaitTP = "vlanStIncrFlowWaitTP"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000118 vlanStConfigIncrFlow = "vlanStConfigIncrFlow"
mpagenko01e726e2020-10-23 09:45:29 +0000119 vlanStRemoveFlow = "vlanStRemoveFlow"
mpagenkodff5dda2020-08-28 11:52:01 +0000120 vlanStCleanupDone = "vlanStCleanupDone"
121 vlanStResetting = "vlanStResetting"
122)
mpagenkof1fc3862021-02-16 10:09:52 +0000123const cVlanFsmIdleState = vlanStConfigDone // state where no OMCI activity is done (for a longer time)
124const cVlanFsmConfiguredState = vlanStConfigDone // state that indicates that at least some valid user related VLAN configuration should exist
mpagenkodff5dda2020-08-28 11:52:01 +0000125
mpagenko01e726e2020-10-23 09:45:29 +0000126type uniVlanRuleParams struct {
mpagenko551a4d42020-12-08 18:09:20 +0000127 TpID uint8 `json:"tp_id"`
mpagenko01e726e2020-10-23 09:45:29 +0000128 MatchVid uint32 `json:"match_vid"` //use uint32 types for allowing immediate bitshifting
129 MatchPcp uint32 `json:"match_pcp"`
130 TagsToRemove uint32 `json:"tags_to_remove"`
131 SetVid uint32 `json:"set_vid"`
132 SetPcp uint32 `json:"set_pcp"`
133}
134
135type uniVlanFlowParams struct {
136 CookieSlice []uint64 `json:"cookie_slice"`
137 VlanRuleParams uniVlanRuleParams `json:"vlan_rule_params"`
138}
139
140type uniRemoveVlanFlowParams struct {
141 cookie uint64 //just the last cookie valid for removal
142 vlanRuleParams uniVlanRuleParams
143}
144
mpagenkodff5dda2020-08-28 11:52:01 +0000145//UniVlanConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
146type UniVlanConfigFsm struct {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530147 pDeviceHandler *deviceHandler
mpagenko01e726e2020-10-23 09:45:29 +0000148 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530149 pOmciCC *omciCC
150 pOnuUniPort *onuUniPort
151 pUniTechProf *onuUniTechProf
152 pOnuDB *onuDeviceDB
mpagenkodff5dda2020-08-28 11:52:01 +0000153 requestEvent OnuDeviceEvent
154 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
155 pAdaptFsm *AdapterFsm
156 acceptIncrementalEvtoOption bool
mpagenko2418ab02020-11-12 12:58:06 +0000157 clearPersistency bool
mpagenko551a4d42020-12-08 18:09:20 +0000158 mutexFlowParams sync.RWMutex
mpagenkof1fc3862021-02-16 10:09:52 +0000159 chCookieDeleted chan bool //channel to indicate that a specificly indicated cookie was deleted
mpagenko9a304ea2020-12-16 15:54:01 +0000160 actualUniVlanConfigRule uniVlanRuleParams
mpagenko01e726e2020-10-23 09:45:29 +0000161 uniVlanFlowParamsSlice []uniVlanFlowParams
162 uniRemoveFlowsSlice []uniRemoveVlanFlowParams
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000163 numUniFlows uint8 // expected number of flows should be less than 12
164 configuredUniFlow uint8
mpagenko01e726e2020-10-23 09:45:29 +0000165 numRemoveFlows uint8
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000166 numVlanFilterEntries uint8
mpagenko01e726e2020-10-23 09:45:29 +0000167 vlanFilterList [cVtfdTableSize]uint16
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000168 evtocdID uint16
mpagenko01e726e2020-10-23 09:45:29 +0000169 pLastTxMeInstance *me.ManagedEntity
mpagenkofc4f56e2020-11-04 17:17:49 +0000170 requestEventOffset uint8
mpagenko551a4d42020-12-08 18:09:20 +0000171 TpIDWaitingFor uint8
mpagenkof1fc3862021-02-16 10:09:52 +0000172 //cookie value that indicates that a rule to add is delayed by waiting for deletion of some other existing rule with the same cookie
173 delayNewRuleCookie uint64
mpagenkodff5dda2020-08-28 11:52:01 +0000174}
175
mpagenko01e726e2020-10-23 09:45:29 +0000176//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
177// of ONU UNI ports via OMCI
dbainbri4d3a0dc2020-12-02 00:33:42 +0000178func NewUniVlanConfigFsm(ctx context.Context, apDeviceHandler *deviceHandler, apDevOmciCC *omciCC, apUniPort *onuUniPort,
mpagenko551a4d42020-12-08 18:09:20 +0000179 apUniTechProf *onuUniTechProf, apOnuDB *onuDeviceDB, aTechProfileID uint8,
mpagenko01e726e2020-10-23 09:45:29 +0000180 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message, aAcceptIncrementalEvto bool,
181 aCookieSlice []uint64, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) *UniVlanConfigFsm {
mpagenkodff5dda2020-08-28 11:52:01 +0000182 instFsm := &UniVlanConfigFsm{
183 pDeviceHandler: apDeviceHandler,
mpagenko01e726e2020-10-23 09:45:29 +0000184 deviceID: apDeviceHandler.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000185 pOmciCC: apDevOmciCC,
186 pOnuUniPort: apUniPort,
187 pUniTechProf: apUniTechProf,
188 pOnuDB: apOnuDB,
mpagenkodff5dda2020-08-28 11:52:01 +0000189 requestEvent: aRequestEvent,
190 acceptIncrementalEvtoOption: aAcceptIncrementalEvto,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000191 numUniFlows: 0,
192 configuredUniFlow: 0,
mpagenko01e726e2020-10-23 09:45:29 +0000193 numRemoveFlows: 0,
mpagenko2418ab02020-11-12 12:58:06 +0000194 clearPersistency: true,
mpagenkodff5dda2020-08-28 11:52:01 +0000195 }
196
mpagenko01e726e2020-10-23 09:45:29 +0000197 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenkodff5dda2020-08-28 11:52:01 +0000198 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000199 logger.Errorw(ctx, "UniVlanConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000200 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000201 return nil
202 }
mpagenkodff5dda2020-08-28 11:52:01 +0000203 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
204 vlanStDisabled,
205 fsm.Events{
206 {Name: vlanEvStart, Src: []string{vlanStDisabled}, Dst: vlanStStarting},
207 {Name: vlanEvWaitTechProf, Src: []string{vlanStStarting}, Dst: vlanStWaitingTechProf},
mpagenko535d6ef2021-02-26 13:15:34 +0000208 {Name: vlanEvCancelOutstandingConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000209 {Name: vlanEvContinueConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigVtfd},
210 {Name: vlanEvStartConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigVtfd},
211 {Name: vlanEvRxConfigVtfd, Src: []string{vlanStConfigVtfd}, Dst: vlanStConfigEvtocd},
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000212 {Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
213 Dst: vlanStConfigDone},
mpagenko551a4d42020-12-08 18:09:20 +0000214 {Name: vlanEvRenew, Src: []string{vlanStConfigDone}, Dst: vlanStStarting},
215 {Name: vlanEvWaitTPIncr, Src: []string{vlanStConfigDone}, Dst: vlanStIncrFlowWaitTP},
216 {Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone, vlanStIncrFlowWaitTP},
217 Dst: vlanStConfigIncrFlow},
mpagenko01e726e2020-10-23 09:45:29 +0000218 {Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
219 {Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
220 {Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000221 /*
222 {Name: vlanEvTimeoutSimple, Src: []string{
223 vlanStCreatingDot1PMapper, vlanStCreatingMBPCD, vlanStSettingTconts, vlanStSettingDot1PMapper}, Dst: vlanStStarting},
224 {Name: vlanEvTimeoutMids, Src: []string{
225 vlanStCreatingGemNCTPs, vlanStCreatingGemIWs, vlanStSettingPQs}, Dst: vlanStStarting},
226 */
227 // exceptional treatment for all states except vlanStResetting
228 {Name: vlanEvReset, Src: []string{vlanStStarting, vlanStWaitingTechProf,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000229 vlanStConfigVtfd, vlanStConfigEvtocd, vlanStConfigDone, vlanStConfigIncrFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000230 vlanStRemoveFlow, vlanStCleanupDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000231 Dst: vlanStResetting},
232 // the only way to get to resource-cleared disabled state again is via "resseting"
233 {Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
234 },
mpagenkodff5dda2020-08-28 11:52:01 +0000235 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000236 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
237 "enter_" + vlanStStarting: func(e *fsm.Event) { instFsm.enterConfigStarting(ctx, e) },
238 "enter_" + vlanStConfigVtfd: func(e *fsm.Event) { instFsm.enterConfigVtfd(ctx, e) },
239 "enter_" + vlanStConfigEvtocd: func(e *fsm.Event) { instFsm.enterConfigEvtocd(ctx, e) },
240 "enter_" + vlanStConfigDone: func(e *fsm.Event) { instFsm.enterVlanConfigDone(ctx, e) },
241 "enter_" + vlanStConfigIncrFlow: func(e *fsm.Event) { instFsm.enterConfigIncrFlow(ctx, e) },
242 "enter_" + vlanStRemoveFlow: func(e *fsm.Event) { instFsm.enterRemoveFlow(ctx, e) },
243 "enter_" + vlanStCleanupDone: func(e *fsm.Event) { instFsm.enterVlanCleanupDone(ctx, e) },
244 "enter_" + vlanStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
245 "enter_" + vlanStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
mpagenkodff5dda2020-08-28 11:52:01 +0000246 },
247 )
248 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000249 logger.Errorw(ctx, "UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000250 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000251 return nil
252 }
253
dbainbri4d3a0dc2020-12-02 00:33:42 +0000254 _ = instFsm.initUniFlowParams(ctx, aTechProfileID, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000255
dbainbri4d3a0dc2020-12-02 00:33:42 +0000256 logger.Debugw(ctx, "UniVlanConfigFsm created", log.Fields{"device-id": instFsm.deviceID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000257 "accIncrEvto": instFsm.acceptIncrementalEvtoOption})
mpagenkodff5dda2020-08-28 11:52:01 +0000258 return instFsm
259}
260
mpagenko01e726e2020-10-23 09:45:29 +0000261//initUniFlowParams is a simplified form of SetUniFlowParams() used for first flow parameters configuration
mpagenko551a4d42020-12-08 18:09:20 +0000262func (oFsm *UniVlanConfigFsm) initUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000263 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
264 loRuleParams := uniVlanRuleParams{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000265 TpID: aTpID,
266 MatchVid: uint32(aMatchVlan),
267 SetVid: uint32(aSetVlan),
268 SetPcp: uint32(aSetPcp),
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000269 }
270 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
mpagenko01e726e2020-10-23 09:45:29 +0000271 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
272 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000273
mpagenko01e726e2020-10-23 09:45:29 +0000274 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000275 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000276 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000277 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
278 } else {
279 if !oFsm.acceptIncrementalEvtoOption {
280 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000281 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000282 }
283 }
284
mpagenko01e726e2020-10-23 09:45:29 +0000285 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000286 // no prio/vid filtering requested
mpagenko01e726e2020-10-23 09:45:29 +0000287 loRuleParams.TagsToRemove = 0 //no tag pop action
288 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
289 if loRuleParams.SetPcp == cCopyPrioFromInner {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000290 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
291 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
292 // might collide with NoMatchVid/CopyPrio(/setVid) setting
293 // this was some precondition setting taken over from py adapter ..
mpagenko01e726e2020-10-23 09:45:29 +0000294 loRuleParams.SetPcp = 0
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000295 }
296 }
mpagenko01e726e2020-10-23 09:45:29 +0000297
298 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
299 loFlowParams.CookieSlice = make([]uint64, 0)
300 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
301
302 //no mutex protection is required for initial access and adding the first flow is always possible
303 oFsm.uniVlanFlowParamsSlice = make([]uniVlanFlowParams, 0)
304 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000305 logger.Debugw(ctx, "first UniVlanConfigFsm flow added", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000306 "Cookies": oFsm.uniVlanFlowParamsSlice[0].CookieSlice,
307 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
308 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
309 "SetPcp": loRuleParams.SetPcp,
310 "device-id": oFsm.deviceID})
311 oFsm.numUniFlows = 1
312 oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
313
314 //permanently store flow config for reconcile case
dbainbri4d3a0dc2020-12-02 00:33:42 +0000315 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
mpagenkof1fc3862021-02-16 10:09:52 +0000316 &oFsm.uniVlanFlowParamsSlice, true); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000317 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000318 return err
319 }
320
321 return nil
322}
323
mpagenko551a4d42020-12-08 18:09:20 +0000324//GetWaitingTpID returns the TpId that the FSM might be waiting for continuation (0 if none)
325func (oFsm *UniVlanConfigFsm) GetWaitingTpID() uint8 {
326 //mutex protection is required for possible concurrent access to FSM members
327 oFsm.mutexFlowParams.RLock()
328 defer oFsm.mutexFlowParams.RUnlock()
329 return oFsm.TpIDWaitingFor
330}
331
mpagenko2418ab02020-11-12 12:58:06 +0000332//RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
333func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
334 //mutex protection is required for possible concurrent access to FSM members
mpagenko15ff4a52021-03-02 10:09:20 +0000335 oFsm.mutexFlowParams.Lock()
336 defer oFsm.mutexFlowParams.Unlock()
mpagenko2418ab02020-11-12 12:58:06 +0000337 oFsm.clearPersistency = aClear
338}
339
mpagenko01e726e2020-10-23 09:45:29 +0000340//SetUniFlowParams verifies on existence of flow parameters to be configured,
341// optionally udates the cookie list or appends a new flow if there is space
342// if possible the FSM is trigggerd to start with the processing
mpagenko551a4d42020-12-08 18:09:20 +0000343// ignore complexity by now
344// nolint: gocyclo
345func (oFsm *UniVlanConfigFsm) SetUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000346 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
347 loRuleParams := uniVlanRuleParams{
348 TpID: aTpID,
349 MatchVid: uint32(aMatchVlan),
350 SetVid: uint32(aSetVlan),
351 SetPcp: uint32(aSetPcp),
352 }
353 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
354 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
355 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
356
357 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
358 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
359 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
360 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
361 } else {
362 if !oFsm.acceptIncrementalEvtoOption {
363 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
364 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
365 }
366 }
367
368 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
369 // no prio/vid filtering requested
370 loRuleParams.TagsToRemove = 0 //no tag pop action
371 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
372 if loRuleParams.SetPcp == cCopyPrioFromInner {
373 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
374 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
375 // might collide with NoMatchVid/CopyPrio(/setVid) setting
376 // this was some precondition setting taken over from py adapter ..
377 loRuleParams.SetPcp = 0
378 }
379 }
380
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000381 flowEntryMatch := false
mpagenko01e726e2020-10-23 09:45:29 +0000382 flowCookieModify := false
mpagenkof1fc3862021-02-16 10:09:52 +0000383 requestAppendRule := false
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000384 //mutex protection is required for possible concurrent access to FSM members
385 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +0000386 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
387 //TODO: Verify if using e.g. hashes for the structures here for comparison may generate
388 // countable run time optimization (perhaps with including the hash in kvStore storage?)
389 if storedUniFlowParams.VlanRuleParams == loRuleParams {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000390 flowEntryMatch = true
dbainbri4d3a0dc2020-12-02 00:33:42 +0000391 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - rule already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000392 "device-id": oFsm.deviceID})
393 var cookieMatch bool
394 for _, newCookie := range aCookieSlice { // for all cookies available in the arguments
395 cookieMatch = false
396 for _, cookie := range storedUniFlowParams.CookieSlice {
397 if cookie == newCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000398 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - and cookie already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000399 "device-id": oFsm.deviceID, "cookie": cookie})
400 cookieMatch = true
401 break //found new cookie - no further search for this requested cookie
402 }
403 }
404 if !cookieMatch {
mpagenkof1fc3862021-02-16 10:09:52 +0000405 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
406 if delayedCookie != 0 {
407 //a delay for adding the cookie to this rule is requested
408 // take care of the mutex which is already locked here, need to unlock/lock accordingly to prevent deadlock in suspension
409 oFsm.mutexFlowParams.Unlock()
410 oFsm.suspendNewRule(ctx)
411 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
412 oFsm.mutexFlowParams.Lock()
413 } else {
414 logger.Debugw(ctx, "UniVlanConfigFsm flow setting -adding new cookie", log.Fields{
415 "device-id": oFsm.deviceID, "cookie": newCookie})
416 //as range works with copies of the slice we have to write to the original slice!!
417 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
418 newCookie)
419 flowCookieModify = true
420 }
mpagenko01e726e2020-10-23 09:45:29 +0000421 }
422 } //for all new cookies
423 break // found rule - no further rule search
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000424 }
425 }
mpagenkof1fc3862021-02-16 10:09:52 +0000426 oFsm.mutexFlowParams.Unlock()
427
428 if !flowEntryMatch { //it is (was) a new rule
429 delayedCookie := oFsm.suspendIfRequiredNewRule(ctx, aCookieSlice)
430 requestAppendRule = true //default assumption here is that rule is to be appended
431 flowCookieModify = true //and that the the flow data base is to be updated
432 if delayedCookie != 0 { //it was suspended
433 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
434 }
435 }
436 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
437 if requestAppendRule {
438 oFsm.mutexFlowParams.Lock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000439 if oFsm.numUniFlows < cMaxAllowedFlows {
mpagenko01e726e2020-10-23 09:45:29 +0000440 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
441 loFlowParams.CookieSlice = make([]uint64, 0)
442 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
443 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000444 logger.Debugw(ctx, "UniVlanConfigFsm flow add", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000445 "Cookies": oFsm.uniVlanFlowParamsSlice[oFsm.numUniFlows].CookieSlice,
446 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
447 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800448 "SetPcp": loRuleParams.SetPcp, "numberofFlows": oFsm.numUniFlows + 1,
mpagenko01e726e2020-10-23 09:45:29 +0000449 "device-id": oFsm.deviceID})
450
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000451 oFsm.numUniFlows++
mpagenko01e726e2020-10-23 09:45:29 +0000452 // note: theoretical it would be possible to clear the same rule from the remove slice
453 // (for entries that have not yet been started with removal)
454 // but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
455 // 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 +0000456
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000457 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
458 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
459 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
mpagenko551a4d42020-12-08 18:09:20 +0000460 if oFsm.configuredUniFlow == 0 {
461 // this is a restart with a complete new flow, we can re-use the initial flow config control
462 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000463 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000464 go func(a_pBaseFsm *fsm.FSM) {
465 _ = a_pBaseFsm.Event(vlanEvRenew)
466 }(pConfigVlanStateBaseFsm)
467 } else {
468 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000469 //store the actual rule that shall be worked upon in the following transient states
470 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000471 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000472 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000473 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
474 oFsm.TpIDWaitingFor = tpID
mpagenko9a304ea2020-12-16 15:54:01 +0000475 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request (on setConfig)", log.Fields{
476 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
477 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
478
mpagenko551a4d42020-12-08 18:09:20 +0000479 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
480 if aTechProfDone {
481 // let the vlan processing continue with next rule
482 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
483 } else {
484 // set to waiting for Techprofile
485 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
486 }
487 }(pConfigVlanStateBaseFsm, loTechProfDone)
488 }
mpagenko01e726e2020-10-23 09:45:29 +0000489 } // if not in the appropriate state a new entry will be automatically considered later
490 // when the configDone state is reached
mpagenko15ff4a52021-03-02 10:09:20 +0000491 oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000492 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000493 logger.Errorw(ctx, "UniVlanConfigFsm flow limit exceeded", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000494 "device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
mpagenko15ff4a52021-03-02 10:09:20 +0000495 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000496 return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
497 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000498 } else {
499 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000500 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenko15ff4a52021-03-02 10:09:20 +0000501 oFsm.mutexFlowParams.RLock()
mpagenkofc4f56e2020-11-04 17:17:49 +0000502 if oFsm.numUniFlows == oFsm.configuredUniFlow {
503 //all requested rules really have been configured
504 // state transition notification is checked in deviceHandler
mpagenko15ff4a52021-03-02 10:09:20 +0000505 oFsm.mutexFlowParams.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +0000506 if oFsm.pDeviceHandler != nil {
507 //also the related TechProfile was already configured
dbainbri4d3a0dc2020-12-02 00:33:42 +0000508 logger.Debugw(ctx, "UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +0000509 "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000510 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
511 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetAddNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000512 }
513 } else {
514 // avoid device reason update as the rule config connected to this flow may still be in progress
515 // and the device reason should only be updated on success of rule config
dbainbri4d3a0dc2020-12-02 00:33:42 +0000516 logger.Debugw(ctx, "UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
mpagenkofc4f56e2020-11-04 17:17:49 +0000517 log.Fields{"device-id": oFsm.deviceID,
518 "NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
mpagenko15ff4a52021-03-02 10:09:20 +0000519 oFsm.mutexFlowParams.RUnlock()
mpagenkofc4f56e2020-11-04 17:17:49 +0000520 }
521 }
mpagenko01e726e2020-10-23 09:45:29 +0000522
mpagenkof1fc3862021-02-16 10:09:52 +0000523 if flowCookieModify { // some change was done to the flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000524 //permanently store flow config for reconcile case
mpagenko15ff4a52021-03-02 10:09:20 +0000525 oFsm.mutexFlowParams.RLock()
mpagenkof1fc3862021-02-16 10:09:52 +0000526 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
527 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
mpagenko15ff4a52021-03-02 10:09:20 +0000528 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000529 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000530 return err
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000531 }
mpagenko15ff4a52021-03-02 10:09:20 +0000532 oFsm.mutexFlowParams.RUnlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000533 }
534 return nil
535}
536
mpagenkof1fc3862021-02-16 10:09:52 +0000537// VOL-3828 flow config sequence workaround ########### start ##########
538func (oFsm *UniVlanConfigFsm) delayNewRuleForCookie(ctx context.Context, aCookieSlice []uint64) uint64 {
539 //assumes mutexFlowParams.Lock() protection from caller!
540 if oFsm.delayNewRuleCookie == 0 && len(aCookieSlice) == 1 {
541 // if not already waiting, limitation for this workaround is to just have one overlapping cookie/rule
542 // suspend check is done only of there is only one cookie in the request
543 // background: more elements only expected in reconcile use case, where no conflicting sequence is to be expected
544 newCookie := aCookieSlice[0]
545 for _, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
546 for _, cookie := range storedUniFlowParams.CookieSlice {
547 if cookie == newCookie {
548 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - new cookie still exists for some rule", log.Fields{
549 "device-id": oFsm.deviceID, "cookie": cookie, "exists with SetVlan": storedUniFlowParams.VlanRuleParams.SetVid})
550 oFsm.delayNewRuleCookie = newCookie
551 return newCookie //found new cookie in some existing rule
552 }
553 } // for all stored cookies of the actual inspected rule
554 } //for all rules
555 }
556 return 0 //no delay requested
557}
558func (oFsm *UniVlanConfigFsm) suspendNewRule(ctx context.Context) {
559 oFsm.mutexFlowParams.RLock()
560 logger.Infow(ctx, "Need to suspend adding this rule as long as the cookie is still connected to some other rule", log.Fields{
561 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
562 oFsm.mutexFlowParams.RUnlock()
563 select {
564 case <-oFsm.chCookieDeleted:
565 logger.Infow(ctx, "resume adding this rule after having deleted cookie in some other rule", log.Fields{
566 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
567 case <-time.After(time.Duration(cWaitForCookieDeletion) * time.Second):
568 logger.Errorw(ctx, "timeout waiting for deletion of cookie in some other rule, just try to continue", log.Fields{
569 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
570 }
571 oFsm.mutexFlowParams.Lock()
572 oFsm.delayNewRuleCookie = 0
573 oFsm.mutexFlowParams.Unlock()
574}
575func (oFsm *UniVlanConfigFsm) suspendIfRequiredNewRule(ctx context.Context, aCookieSlice []uint64) uint64 {
576 oFsm.mutexFlowParams.Lock()
577 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
578 oFsm.mutexFlowParams.Unlock()
579
580 if delayedCookie != 0 {
581 oFsm.suspendNewRule(ctx)
582 }
583 return delayedCookie
584}
585
586//returns flowModified, RuleAppendRequest
587func (oFsm *UniVlanConfigFsm) reviseFlowConstellation(ctx context.Context, aCookie uint64, aUniVlanRuleParams uniVlanRuleParams) (bool, bool) {
588 flowEntryMatch := false
589 oFsm.mutexFlowParams.Lock()
590 defer oFsm.mutexFlowParams.Unlock()
591 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
592 if storedUniFlowParams.VlanRuleParams == aUniVlanRuleParams {
593 flowEntryMatch = true
594 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - rule already exists", log.Fields{
595 "device-id": oFsm.deviceID})
596 cookieMatch := false
597 for _, cookie := range storedUniFlowParams.CookieSlice {
598 if cookie == aCookie {
599 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - and cookie already exists", log.Fields{
600 "device-id": oFsm.deviceID, "cookie": cookie})
601 cookieMatch = true
602 break //found new cookie - no further search for this requested cookie
603 }
604 }
605 if !cookieMatch {
606 logger.Debugw(ctx, "UniVlanConfigFsm flow revise -adding new cookie", log.Fields{
607 "device-id": oFsm.deviceID, "cookie": aCookie})
608 //as range works with copies of the slice we have to write to the original slice!!
609 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
610 aCookie)
611 return true, false //flowModified, NoRuleAppend
612 }
613 break // found rule - no further rule search
614 }
615 }
616 if !flowEntryMatch { //it is a new rule
617 return true, true //flowModified, RuleAppend
618 }
619 return false, false //flowNotModified, NoRuleAppend
620}
621
622// VOL-3828 flow config sequence workaround ########### end ##########
623
mpagenko01e726e2020-10-23 09:45:29 +0000624//RemoveUniFlowParams verifies on existence of flow cookie,
625// if found removes cookie from flow cookie list and if this is empty
626// initiates removal of the flow related configuration from the ONU (via OMCI)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000627func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(ctx context.Context, aCookie uint64) error {
mpagenkof1fc3862021-02-16 10:09:52 +0000628 var deletedCookie uint64
mpagenko01e726e2020-10-23 09:45:29 +0000629 flowCookieMatch := false
630 //mutex protection is required for possible concurrent access to FSM members
631 oFsm.mutexFlowParams.Lock()
632 defer oFsm.mutexFlowParams.Unlock()
mpagenkof1fc3862021-02-16 10:09:52 +0000633remove_loop:
mpagenko01e726e2020-10-23 09:45:29 +0000634 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
635 for i, cookie := range storedUniFlowParams.CookieSlice {
636 if cookie == aCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000637 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - cookie found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000638 "device-id": oFsm.deviceID, "cookie": cookie})
639 flowCookieMatch = true
mpagenkof1fc3862021-02-16 10:09:52 +0000640 deletedCookie = aCookie
641 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
mpagenko01e726e2020-10-23 09:45:29 +0000642 //remove the cookie from the cookie slice and verify it is getting empty
643 if len(storedUniFlowParams.CookieSlice) == 1 {
mpagenko535d6ef2021-02-26 13:15:34 +0000644 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
645 var cancelPendingConfig bool = false
646 var loRemoveParams uniRemoveVlanFlowParams = uniRemoveVlanFlowParams{}
dbainbri4d3a0dc2020-12-02 00:33:42 +0000647 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - full flow removal", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000648 "device-id": oFsm.deviceID})
mpagenko15ff4a52021-03-02 10:09:20 +0000649 //rwCore flow recovery may be the reason for this delete, in which case the flowToBeDeleted may be the same
mpagenko535d6ef2021-02-26 13:15:34 +0000650 // as the one still waiting in the FSM as toAdd but waiting for TechProfileConfig
mpagenko15ff4a52021-03-02 10:09:20 +0000651 // so we have to check if we have to abort the outstanding AddRequest and regard the current DelRequest as done
mpagenko535d6ef2021-02-26 13:15:34 +0000652 // if the Fsm is in some other transient (config) state, we will reach the DelRequest later and correctly process it then
653 if pConfigVlanStateBaseFsm.Is(vlanStWaitingTechProf) {
654 logger.Debugw(ctx, "UniVlanConfigFsm was waiting for TechProf config with this rule, aborting the outstanding config",
655 log.Fields{"device-id": oFsm.deviceID})
656 cancelPendingConfig = true
657 } else {
658 //create a new element for the removeVlanFlow slice
659 loRemoveParams = uniRemoveVlanFlowParams{
660 vlanRuleParams: storedUniFlowParams.VlanRuleParams,
661 cookie: aCookie,
662 }
663 oFsm.uniRemoveFlowsSlice = append(oFsm.uniRemoveFlowsSlice, loRemoveParams)
mpagenko01e726e2020-10-23 09:45:29 +0000664 }
mpagenko01e726e2020-10-23 09:45:29 +0000665
666 //and remove the actual element from the addVlanFlow slice
667 // oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = nil //automatically done by garbage collector
668 if len(oFsm.uniVlanFlowParamsSlice) <= 1 {
669 oFsm.numUniFlows = 0 //no more flows
670 oFsm.configuredUniFlow = 0 //no more flows configured
671 oFsm.uniVlanFlowParamsSlice = nil //reset the slice
mpagenko2418ab02020-11-12 12:58:06 +0000672 //at this point it is evident that no flow anymore refers to a still possibly active Techprofile
mpagenko535d6ef2021-02-26 13:15:34 +0000673 //request that this profile gets deleted before a new flow add is allowed (except for some aborted add)
674 if !cancelPendingConfig {
675 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, loRemoveParams.vlanRuleParams.TpID, true)
676 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000677 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - no more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000678 "device-id": oFsm.deviceID})
679 } else {
680 oFsm.numUniFlows--
681 if oFsm.configuredUniFlow > 0 {
682 oFsm.configuredUniFlow--
683 //TODO!! might be needed to consider still outstanding configure requests ..
684 // so a flow at removal might still not be configured !?!
685 }
mpagenko2418ab02020-11-12 12:58:06 +0000686 usedTpID := storedUniFlowParams.VlanRuleParams.TpID
mpagenko01e726e2020-10-23 09:45:29 +0000687 //cut off the requested flow by slicing out this element
688 oFsm.uniVlanFlowParamsSlice = append(
689 oFsm.uniVlanFlowParamsSlice[:flow], oFsm.uniVlanFlowParamsSlice[flow+1:]...)
mpagenko2418ab02020-11-12 12:58:06 +0000690 //here we have to check, if there are still other flows referencing to the actual ProfileId
691 // before we can request that this profile gets deleted before a new flow add is allowed
mpagenkof1fc3862021-02-16 10:09:52 +0000692 // (needed to extract to function due to lint complexity)
mpagenko535d6ef2021-02-26 13:15:34 +0000693 if !cancelPendingConfig {
694 oFsm.updateTechProfileToDelete(ctx, usedTpID)
695 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000696 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow removed from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000697 "device-id": oFsm.deviceID})
698 }
699 //trigger the FSM to remove the relevant rule
mpagenko535d6ef2021-02-26 13:15:34 +0000700 if cancelPendingConfig {
701 oFsm.requestEventOffset = uint8(cDeviceEventOffsetRemoveWithKvStore) //offset for last flow-remove activity (with kvStore request)
mpagenko01e726e2020-10-23 09:45:29 +0000702 go func(a_pBaseFsm *fsm.FSM) {
mpagenko535d6ef2021-02-26 13:15:34 +0000703 _ = a_pBaseFsm.Event(vlanEvCancelOutstandingConfig)
mpagenko01e726e2020-10-23 09:45:29 +0000704 }(pConfigVlanStateBaseFsm)
mpagenko535d6ef2021-02-26 13:15:34 +0000705 } else {
706 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
707 logger.Debugw(ctx, "UniVlanConfigFsm rule removal request", log.Fields{
708 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
709 "tp-id": loRemoveParams.vlanRuleParams.TpID,
710 "set-Vlan": loRemoveParams.vlanRuleParams.SetVid})
711 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
712 // Can't call FSM Event directly, decoupling it
713 go func(a_pBaseFsm *fsm.FSM) {
714 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
715 }(pConfigVlanStateBaseFsm)
716 } // if not in the appropriate state a new entry will be automatically considered later
717 // when the configDone state is reached
718 }
mpagenko01e726e2020-10-23 09:45:29 +0000719 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000720 //cut off the requested cookie by slicing out this element
721 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
722 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
723 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
mpagenkofc4f56e2020-11-04 17:17:49 +0000724 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000725 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenkofc4f56e2020-11-04 17:17:49 +0000726 // state transition notification is checked in deviceHandler
727 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000728 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
729 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000730 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000731 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - rule persists with still valid cookies", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000732 "device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
mpagenkof1fc3862021-02-16 10:09:52 +0000733 if deletedCookie == oFsm.delayNewRuleCookie {
734 //the delayedNewCookie is the one that is currently deleted, but the rule still exist with other cookies
735 //as long as there are further cookies for this rule indicate there is still some cookie to be deleted
736 //simply use the first one
737 oFsm.delayNewRuleCookie = oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[0]
738 logger.Debugw(ctx, "UniVlanConfigFsm remaining cookie awaited for deletion before new rule add", log.Fields{
739 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
740 }
mpagenko01e726e2020-10-23 09:45:29 +0000741 }
mpagenko01e726e2020-10-23 09:45:29 +0000742 //permanently store the modified flow config for reconcile case
mpagenkofc4f56e2020-11-04 17:17:49 +0000743 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000744 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
745 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000746 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000747 return err
748 }
mpagenko01e726e2020-10-23 09:45:29 +0000749 }
mpagenkof1fc3862021-02-16 10:09:52 +0000750 break remove_loop //found the cookie - no further search for this requested cookie
mpagenko01e726e2020-10-23 09:45:29 +0000751 }
752 }
mpagenko01e726e2020-10-23 09:45:29 +0000753 } //search all flows
754 if !flowCookieMatch { //some cookie remove-request for a cookie that does not exist in the FSM data
dbainbri4d3a0dc2020-12-02 00:33:42 +0000755 logger.Warnw(ctx, "UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000756 "device-id": oFsm.deviceID, "remove-cookie": aCookie})
757 // but accept the request with success as no such cookie (flow) does exist
mpagenkofc4f56e2020-11-04 17:17:49 +0000758 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
759 // state transition notification is checked in deviceHandler
760 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000761 // success indication without the need to write to kvStore (no change)
762 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000763 }
mpagenko01e726e2020-10-23 09:45:29 +0000764 return nil
765 } //unknown cookie
766
767 return nil
768}
769
mpagenkof1fc3862021-02-16 10:09:52 +0000770func (oFsm *UniVlanConfigFsm) updateTechProfileToDelete(ctx context.Context, usedTpID uint8) {
771 //here we have to check, if there are still other flows referencing to the actual ProfileId
772 // before we can request that this profile gets deleted before a new flow add is allowed
773 tpIDInOtherFlows := false
774 for _, tpUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
775 if tpUniFlowParams.VlanRuleParams.TpID == usedTpID {
776 tpIDInOtherFlows = true
777 break // search loop can be left
778 }
779 }
780 if tpIDInOtherFlows {
781 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is still used in other flows", log.Fields{
782 "device-id": oFsm.deviceID, "tp-id": usedTpID})
783 } else {
784 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is not used anymore", log.Fields{
785 "device-id": oFsm.deviceID, "tp-id": usedTpID})
786 //request that this profile gets deleted before a new flow add is allowed
787 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, usedTpID, true)
788 }
789}
790
dbainbri4d3a0dc2020-12-02 00:33:42 +0000791func (oFsm *UniVlanConfigFsm) enterConfigStarting(ctx context.Context, e *fsm.Event) {
792 logger.Debugw(ctx, "UniVlanConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000793 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000794
795 // this FSM is not intended for re-start, needs always new creation for a new run
mpagenko01e726e2020-10-23 09:45:29 +0000796 // (self-destroying - compare enterDisabled())
mpagenkodff5dda2020-08-28 11:52:01 +0000797 oFsm.omciMIdsResponseReceived = make(chan bool)
mpagenkof1fc3862021-02-16 10:09:52 +0000798 oFsm.chCookieDeleted = make(chan bool)
mpagenkodff5dda2020-08-28 11:52:01 +0000799 // start go routine for processing of LockState messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000800 go oFsm.processOmciVlanMessages(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +0000801 //let the state machine run forward from here directly
802 pConfigVlanStateAFsm := oFsm.pAdaptFsm
803 if pConfigVlanStateAFsm != nil {
mpagenko551a4d42020-12-08 18:09:20 +0000804 oFsm.mutexFlowParams.Lock()
mpagenko9a304ea2020-12-16 15:54:01 +0000805
806 //possibly the entry is not valid anymore based on intermediate delete requests
807 //just a basic protection ...
808 if len(oFsm.uniVlanFlowParamsSlice) == 0 {
809 oFsm.mutexFlowParams.Unlock()
810 logger.Debugw(ctx, "UniVlanConfigFsm start: no rule entry anymore available", log.Fields{
811 "device-id": oFsm.deviceID})
812 // Can't call FSM Event directly, decoupling it
813 go func(a_pAFsm *AdapterFsm) {
814 _ = a_pAFsm.pFsm.Event(vlanEvReset)
815 }(pConfigVlanStateAFsm)
816 return
817 }
818
819 //access to uniVlanFlowParamsSlice is done on first element only here per definition
820 //store the actual rule that shall be worked upon in the following transient states
821 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams
mpagenko9a304ea2020-12-16 15:54:01 +0000822 tpID := oFsm.actualUniVlanConfigRule.TpID
823 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000824 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID))
mpagenko9a304ea2020-12-16 15:54:01 +0000825 logger.Debugw(ctx, "UniVlanConfigFsm - start with first rule", log.Fields{
826 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
827 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
mpagenko551a4d42020-12-08 18:09:20 +0000828 //cmp also usage in EVTOCDE create in omci_cc
829 oFsm.evtocdID = macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
mpagenko535d6ef2021-02-26 13:15:34 +0000830 oFsm.mutexFlowParams.Unlock()
mpagenko9a304ea2020-12-16 15:54:01 +0000831 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000832 go func(aPAFsm *AdapterFsm, aTechProfDone bool) {
833 if aPAFsm != nil && aPAFsm.pFsm != nil {
834 if aTechProfDone {
mpagenkodff5dda2020-08-28 11:52:01 +0000835 // let the vlan processing begin
mpagenko551a4d42020-12-08 18:09:20 +0000836 _ = aPAFsm.pFsm.Event(vlanEvStartConfig)
mpagenkodff5dda2020-08-28 11:52:01 +0000837 } else {
838 // set to waiting for Techprofile
mpagenko551a4d42020-12-08 18:09:20 +0000839 _ = aPAFsm.pFsm.Event(vlanEvWaitTechProf)
mpagenkodff5dda2020-08-28 11:52:01 +0000840 }
841 }
mpagenko551a4d42020-12-08 18:09:20 +0000842 }(pConfigVlanStateAFsm, loTechProfDone)
843 } else {
844 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
845 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
846 //should never happen, else: recovery would be needed from outside the FSM
847 return
mpagenkodff5dda2020-08-28 11:52:01 +0000848 }
849}
850
dbainbri4d3a0dc2020-12-02 00:33:42 +0000851func (oFsm *UniVlanConfigFsm) enterConfigVtfd(ctx context.Context, e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000852 //mutex protection is required for possible concurrent access to FSM members
853 oFsm.mutexFlowParams.Lock()
mpagenko551a4d42020-12-08 18:09:20 +0000854 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
mpagenko9a304ea2020-12-16 15:54:01 +0000855 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000856 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000857 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000858 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000859 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000860 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
mpagenkodff5dda2020-08-28 11:52:01 +0000861 pConfigVlanStateAFsm := oFsm.pAdaptFsm
mpagenko9a304ea2020-12-16 15:54:01 +0000862 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +0000863 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530864 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000865 }(pConfigVlanStateAFsm)
866 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300867 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
868 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +0000869 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000870 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300871 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000872 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
873 // setVid is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +0000874 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000875 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000876 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000877 vtfdFilterList[0] = oFsm.vlanFilterList[0]
878 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000879 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300880 EntityID: vtfdID,
mpagenkodff5dda2020-08-28 11:52:01 +0000881 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000882 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
883 "ForwardOperation": uint8(0x10), //VID investigation
884 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000885 },
886 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000887 logger.Debugw(ctx, "UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000888 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000889 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +0000890 oFsm.pAdaptFsm.commChan, meParams)
891 //accept also nil as (error) return value for writing to LastTx
892 // - this avoids misinterpretation of new received OMCI messages
893 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
894 // send shall return (dual format) error code that can be used here for immediate error treatment
895 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000896 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000897 }
898}
899
dbainbri4d3a0dc2020-12-02 00:33:42 +0000900func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(ctx context.Context, e *fsm.Event) {
901 logger.Debugw(ctx, "UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000902 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000903 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300904 go func() {
mpagenko9a304ea2020-12-16 15:54:01 +0000905 //using the first element in the slice because it's the first flow per definition here
906 errEvto := oFsm.performConfigEvtocdEntries(ctx, 0)
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300907 //This is correct passing scenario
908 if errEvto == nil {
mpagenko9a304ea2020-12-16 15:54:01 +0000909 tpID := oFsm.actualUniVlanConfigRule.TpID
910 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +0000911 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
912 logger.Infow(ctx, "Setting multicast MEs, with first flow", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300913 "techProfile": tpID, "gemPort": gemPort, "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000914 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300915 vlanID)
916 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000917 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300918 log.Fields{"device-id": oFsm.deviceID})
919 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
920 }
921 }
922 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
923 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
924 }
925 }()
mpagenkodff5dda2020-08-28 11:52:01 +0000926}
927
dbainbri4d3a0dc2020-12-02 00:33:42 +0000928func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(ctx context.Context, e *fsm.Event) {
mpagenko9a304ea2020-12-16 15:54:01 +0000929 oFsm.mutexFlowParams.RLock()
930 defer oFsm.mutexFlowParams.RUnlock()
931
mpagenkof1fc3862021-02-16 10:09:52 +0000932 logger.Infow(ctx, "UniVlanConfigFsm config done - checking on more flows", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000933 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
934 "overall-uni-rules": oFsm.numUniFlows, "configured-uni-rules": oFsm.configuredUniFlow})
935 pConfigVlanStateAFsm := oFsm.pAdaptFsm
936 if pConfigVlanStateAFsm == nil {
mpagenko551a4d42020-12-08 18:09:20 +0000937 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
938 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
939 //should never happen, else: recovery would be needed from outside the FSM
940 return
941 }
942 pConfigVlanStateBaseFsm := pConfigVlanStateAFsm.pFsm
mpagenko01e726e2020-10-23 09:45:29 +0000943 if len(oFsm.uniRemoveFlowsSlice) > 0 {
944 //some further flows are to be removed, removal always starts with the first element
mpagenko9a304ea2020-12-16 15:54:01 +0000945 logger.Debugw(ctx, "UniVlanConfigFsm rule removal from ConfigDone", log.Fields{
946 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
947 "tp-id": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.TpID,
948 "set-Vlan": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.SetVid})
949 // Can't call FSM Event directly, decoupling it
mpagenko01e726e2020-10-23 09:45:29 +0000950 go func(a_pBaseFsm *fsm.FSM) {
951 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
952 }(pConfigVlanStateBaseFsm)
953 return
954 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000955 if oFsm.numUniFlows > oFsm.configuredUniFlow {
mpagenko551a4d42020-12-08 18:09:20 +0000956 if oFsm.configuredUniFlow == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000957 // this is a restart with a complete new flow, we can re-use the initial flow config control
958 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000959 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000960 go func(a_pBaseFsm *fsm.FSM) {
961 _ = a_pBaseFsm.Event(vlanEvRenew)
962 }(pConfigVlanStateBaseFsm)
963 return
964 }
965
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000966 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000967 //store the actual rule that shall be worked upon in the following transient states
968 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000969 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000970 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000971 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000972 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
mpagenko9a304ea2020-12-16 15:54:01 +0000973 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request", log.Fields{
974 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
975 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
976 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000977 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
978 if aTechProfDone {
979 // let the vlan processing continue with next rule
980 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
981 } else {
982 // set to waiting for Techprofile
983 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
984 }
985 }(pConfigVlanStateBaseFsm, loTechProfDone)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000986 return
987 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000988 logger.Debugw(ctx, "UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000989 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000990 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
991 // state transition notification is checked in deviceHandler
mpagenko551a4d42020-12-08 18:09:20 +0000992 // note: 'flowPushed' event is only generated if all 'pending' rules are configured
mpagenkodff5dda2020-08-28 11:52:01 +0000993 if oFsm.pDeviceHandler != nil {
mpagenkofc4f56e2020-11-04 17:17:49 +0000994 //making use of the add->remove successor enum assumption/definition
dbainbri4d3a0dc2020-12-02 00:33:42 +0000995 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(uint8(oFsm.requestEvent)+oFsm.requestEventOffset))
mpagenkodff5dda2020-08-28 11:52:01 +0000996 }
997}
998
dbainbri4d3a0dc2020-12-02 00:33:42 +0000999func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(ctx context.Context, e *fsm.Event) {
mpagenko15ff4a52021-03-02 10:09:20 +00001000 oFsm.mutexFlowParams.Lock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001001 logger.Debugw(ctx, "UniVlanConfigFsm - start config further incremental flow", log.Fields{
Girish Gowdra041dcb32020-11-16 16:54:30 -08001002 "in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
mpagenko01e726e2020-10-23 09:45:29 +00001003 "device-id": oFsm.deviceID})
mpagenko551a4d42020-12-08 18:09:20 +00001004 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001005
mpagenko9a304ea2020-12-16 15:54:01 +00001006 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001007 // meaning transparent setup - no specific VTFD setting required
1008 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001009 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001010 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001011 } else {
1012 if oFsm.numVlanFilterEntries == 0 {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001013 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
1014 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +00001015 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001016 //no VTFD yet created
dbainbri4d3a0dc2020-12-02 00:33:42 +00001017 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001018 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001019 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001020 // 'SetVid' below is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +00001021 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001022
mpagenko01e726e2020-10-23 09:45:29 +00001023 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001024 vtfdFilterList[0] = oFsm.vlanFilterList[0]
1025 oFsm.numVlanFilterEntries = 1
1026 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001027 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001028 Attributes: me.AttributeValueMap{
1029 "VlanFilterList": vtfdFilterList,
1030 "ForwardOperation": uint8(0x10), //VID investigation
1031 "NumberOfEntries": oFsm.numVlanFilterEntries,
1032 },
1033 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001034 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001035 oFsm.pAdaptFsm.commChan, meParams)
1036 //accept also nil as (error) return value for writing to LastTx
1037 // - this avoids misinterpretation of new received OMCI messages
1038 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1039 // send shall return (dual format) error code that can be used here for immediate error treatment
1040 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001041 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001042 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001043 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
1044 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko551a4d42020-12-08 18:09:20 +00001045 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID +
mpagenko9a304ea2020-12-16 15:54:01 +00001046 uint16(oFsm.actualUniVlanConfigRule.TpID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001047
dbainbri4d3a0dc2020-12-02 00:33:42 +00001048 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001049 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001050 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001051 // setVid is assumed to be masked already by the caller to 12 bit
1052 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko9a304ea2020-12-16 15:54:01 +00001053 uint16(oFsm.actualUniVlanConfigRule.SetVid)
mpagenko01e726e2020-10-23 09:45:29 +00001054 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001055
1056 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
1057 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
1058 // new vlan associated with a different TP.
mpagenko9a304ea2020-12-16 15:54:01 +00001059 vtfdFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001060
1061 oFsm.numVlanFilterEntries++
1062 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001063 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001064 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001065 "VlanFilterList": vtfdFilterList,
1066 "ForwardOperation": uint8(0x10), //VID investigation
1067 "NumberOfEntries": oFsm.numVlanFilterEntries,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001068 },
1069 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001070 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001071 oFsm.pAdaptFsm.commChan, meParams)
1072 //accept also nil as (error) return value for writing to LastTx
1073 // - this avoids misinterpretation of new received OMCI messages
1074 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1075 // send shall return (dual format) error code that can be used here for immediate error treatment
1076 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001077 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001078 }
mpagenko15ff4a52021-03-02 10:09:20 +00001079 oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001080 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001081 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001082 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001083 logger.Errorw(ctx, "VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001084 log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001085 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
mpagenko9a304ea2020-12-16 15:54:01 +00001086 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001087 go func(a_pBaseFsm *fsm.FSM) {
1088 _ = a_pBaseFsm.Event(vlanEvReset)
1089 }(pConfigVlanStateBaseFsm)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001090 return
1091 }
1092 }
mpagenko15ff4a52021-03-02 10:09:20 +00001093 oFsm.mutexFlowParams.Lock()
mpagenkof1fc3862021-02-16 10:09:52 +00001094 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
mpagenko15ff4a52021-03-02 10:09:20 +00001095 oFsm.mutexFlowParams.Unlock()
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001096 go func() {
mpagenko15ff4a52021-03-02 10:09:20 +00001097 oFsm.mutexFlowParams.RLock()
mpagenko9a304ea2020-12-16 15:54:01 +00001098 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko15ff4a52021-03-02 10:09:20 +00001099 configuredUniFlow := oFsm.configuredUniFlow
1100 oFsm.mutexFlowParams.RUnlock()
1101 errEvto := oFsm.performConfigEvtocdEntries(ctx, configuredUniFlow)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001102 //This is correct passing scenario
1103 if errEvto == nil {
1104 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
dbainbri4d3a0dc2020-12-02 00:33:42 +00001105 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
mpagenko15ff4a52021-03-02 10:09:20 +00001106 oFsm.mutexFlowParams.RLock()
mpagenko9a304ea2020-12-16 15:54:01 +00001107 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +00001108 logger.Infow(ctx, "Setting multicast MEs for additional flows", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001109 "techProfile": tpID, "gemPort": gemPort,
1110 "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
mpagenko15ff4a52021-03-02 10:09:20 +00001111 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001112 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001113 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001114 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001115 log.Fields{"device-id": oFsm.deviceID})
1116 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1117 }
1118 }
1119 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
1120 }
1121 }()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001122}
1123
dbainbri4d3a0dc2020-12-02 00:33:42 +00001124func (oFsm *UniVlanConfigFsm) enterRemoveFlow(ctx context.Context, e *fsm.Event) {
mpagenko551a4d42020-12-08 18:09:20 +00001125 oFsm.mutexFlowParams.RLock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001126 logger.Debugw(ctx, "UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001127 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
1128 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001129
mpagenkofc4f56e2020-11-04 17:17:49 +00001130 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
1131 loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
mpagenko01e726e2020-10-23 09:45:29 +00001132 loVlanEntryClear := uint8(0)
1133 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
1134 //shallow copy is sufficient as no reference variables are used within struct
1135 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +00001136 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001137 logger.Debugw(ctx, "UniVlanConfigFsm - remove-flow parameters are", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001138 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
1139 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
1140 "device-id": oFsm.deviceID})
1141
1142 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1143 // meaning transparent setup - no specific VTFD setting required
dbainbri4d3a0dc2020-12-02 00:33:42 +00001144 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001145 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
1146 } else {
1147 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
1148 if oFsm.numVlanFilterEntries == 1 {
mpagenko551a4d42020-12-08 18:09:20 +00001149 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001150 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
1151 // so we can just delete the VTFD entry
dbainbri4d3a0dc2020-12-02 00:33:42 +00001152 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD delete (no more vlan filters)",
mpagenko01e726e2020-10-23 09:45:29 +00001153 log.Fields{"current vlan list": oFsm.vlanFilterList,
1154 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001155 loVlanEntryClear = 1 //full VlanFilter clear request
1156 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001157 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001158 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001159 oFsm.pLastTxMeInstance = meInstance
1160 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001161 logger.Debugw(ctx, "UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001162 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenkofc4f56e2020-11-04 17:17:49 +00001163 }
mpagenko01e726e2020-10-23 09:45:29 +00001164 } else {
1165 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
1166 // by updating the VTFD per set command with new valid list
dbainbri4d3a0dc2020-12-02 00:33:42 +00001167 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
mpagenko01e726e2020-10-23 09:45:29 +00001168 log.Fields{"current vlan list": oFsm.vlanFilterList,
1169 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
1170 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1171 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
1172 loVlanEntryRmPos = i
1173 break //abort search
1174 }
1175 }
1176 if loVlanEntryRmPos < cVtfdTableSize {
mpagenko551a4d42020-12-08 18:09:20 +00001177 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001178 //valid entry was found - to be eclipsed
1179 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
1180 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1181 if i < loVlanEntryRmPos {
1182 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
1183 } else if i < (cVtfdTableSize - 1) {
1184 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
1185 } else {
1186 vtfdFilterList[i] = 0 //set last byte if needed
1187 }
1188 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001189 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001190 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001191 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
1192
mpagenkofc4f56e2020-11-04 17:17:49 +00001193 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001194 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
dbainbri4d3a0dc2020-12-02 00:33:42 +00001195 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001196 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001197 oFsm.pLastTxMeInstance = meInstance
1198 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001199 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001200 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenko01e726e2020-10-23 09:45:29 +00001201 }
mpagenko01e726e2020-10-23 09:45:29 +00001202 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001203 logger.Warnw(ctx, "UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
mpagenko01e726e2020-10-23 09:45:29 +00001204 log.Fields{"device-id": oFsm.deviceID})
1205 }
1206 }
1207 if loVlanEntryClear > 0 {
mpagenkofc4f56e2020-11-04 17:17:49 +00001208 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
1209 //waiting on response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001210 err := oFsm.waitforOmciResponse(ctx)
mpagenkofc4f56e2020-11-04 17:17:49 +00001211 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001212 logger.Errorw(ctx, "VTFD delete/reset failed, aborting VlanConfig FSM!",
mpagenkofc4f56e2020-11-04 17:17:49 +00001213 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001214 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001215 go func(a_pBaseFsm *fsm.FSM) {
1216 _ = a_pBaseFsm.Event(vlanEvReset)
1217 }(pConfigVlanStateBaseFsm)
1218 return
1219 }
mpagenko01e726e2020-10-23 09:45:29 +00001220 }
1221
mpagenko15ff4a52021-03-02 10:09:20 +00001222 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +00001223 if loVlanEntryClear == 1 {
1224 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
1225 oFsm.numVlanFilterEntries = 0
1226 } else if loVlanEntryClear == 2 {
1227 // new VlanFilterList should be one entry smaller now - copy from last configured entry
1228 // this loop now includes the 0 element on previous last valid entry
1229 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
1230 oFsm.vlanFilterList[i] = vtfdFilterList[i]
1231 }
1232 oFsm.numVlanFilterEntries--
1233 }
mpagenko15ff4a52021-03-02 10:09:20 +00001234 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +00001235 }
1236 }
1237
mpagenkofc4f56e2020-11-04 17:17:49 +00001238 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001239 go oFsm.removeEvtocdEntries(ctx, loRuleParams)
mpagenkofc4f56e2020-11-04 17:17:49 +00001240 } else {
1241 // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001242 logger.Debugw(ctx, "UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +00001243 "device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001244 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001245 go func(a_pBaseFsm *fsm.FSM) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001246 _ = a_pBaseFsm.Event(vlanEvRemFlowDone, loRuleParams.TpID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001247 }(pConfigVlanStateBaseFsm)
1248 }
mpagenkodff5dda2020-08-28 11:52:01 +00001249}
1250
dbainbri4d3a0dc2020-12-02 00:33:42 +00001251func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(ctx context.Context, e *fsm.Event) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001252 var tpID uint8
1253 // Extract the tpID
1254 if len(e.Args) > 0 {
1255 tpID = e.Args[0].(uint8)
1256 logger.Debugw(ctx, "UniVlanConfigFsm - flow removed for tp id", log.Fields{"device-id": oFsm.deviceID, "tpID": e.Args[0].(uint8)})
1257 } else {
1258 logger.Warnw(ctx, "UniVlanConfigFsm - tp id not available", log.Fields{"device-id": oFsm.deviceID})
1259 }
mpagenko01e726e2020-10-23 09:45:29 +00001260 oFsm.mutexFlowParams.Lock()
mpagenkof1fc3862021-02-16 10:09:52 +00001261 deletedCookie := oFsm.uniRemoveFlowsSlice[0].cookie
1262 logger.Debugw(ctx, "UniVlanConfigFsm - removing the removal data", log.Fields{
1263 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
1264 "removed cookie": deletedCookie, "waitForDeleteCookie": oFsm.delayNewRuleCookie})
1265
mpagenko01e726e2020-10-23 09:45:29 +00001266 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
1267 oFsm.uniRemoveFlowsSlice = nil //reset the slice
dbainbri4d3a0dc2020-12-02 00:33:42 +00001268 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001269 "device-id": oFsm.deviceID})
1270 } else {
1271 //cut off the actual flow by slicing out the first element
1272 oFsm.uniRemoveFlowsSlice = append(
1273 oFsm.uniRemoveFlowsSlice[:0],
1274 oFsm.uniRemoveFlowsSlice[1:]...)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001275 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001276 "device-id": oFsm.deviceID})
1277 }
1278 oFsm.mutexFlowParams.Unlock()
1279
mpagenkof1fc3862021-02-16 10:09:52 +00001280 oFsm.requestEventOffset = uint8(cDeviceEventOffsetRemoveWithKvStore) //offset for last flow-remove activity (with kvStore request)
mpagenko01e726e2020-10-23 09:45:29 +00001281 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +00001282 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1283 if pConfigVlanStateAFsm != nil {
mpagenko9a304ea2020-12-16 15:54:01 +00001284 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001285 go func(a_pAFsm *AdapterFsm) {
1286 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001287 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +00001288 }
1289 }(pConfigVlanStateAFsm)
1290 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001291
1292 oFsm.mutexFlowParams.RLock()
1293 noOfFlowRem := len(oFsm.uniRemoveFlowsSlice)
mpagenkof1fc3862021-02-16 10:09:52 +00001294 if deletedCookie == oFsm.delayNewRuleCookie {
1295 // flush the channel CookieDeleted to ensure it is not lingering from some previous (aborted) activity
1296 select {
1297 case <-oFsm.chCookieDeleted:
1298 logger.Debug(ctx, "flushed CookieDeleted")
1299 default:
1300 }
1301 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue
1302 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001303 oFsm.mutexFlowParams.RUnlock()
1304 // If all pending flow removes are completed and TP ID is valid, processing any pending TP delete
1305 if noOfFlowRem == 0 && tpID > 0 {
1306 logger.Debugw(ctx, "processing pending tp delete", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID})
1307 // If we are here then all flows are removed.
1308 oFsm.pDeviceHandler.ProcessPendingTpDelete(ctx, oFsm.pOnuUniPort, tpID)
1309 }
mpagenkodff5dda2020-08-28 11:52:01 +00001310}
1311
dbainbri4d3a0dc2020-12-02 00:33:42 +00001312func (oFsm *UniVlanConfigFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1313 logger.Debugw(ctx, "UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001314
1315 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1316 if pConfigVlanStateAFsm != nil {
1317 // abort running message processing
1318 fsmAbortMsg := Message{
1319 Type: TestMsg,
1320 Data: TestMessage{
1321 TestMessageVal: AbortMessageProcessing,
1322 },
1323 }
1324 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
1325
mpagenko9a304ea2020-12-16 15:54:01 +00001326 //try to restart the FSM to 'disabled'
1327 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001328 go func(a_pAFsm *AdapterFsm) {
1329 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301330 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +00001331 }
1332 }(pConfigVlanStateAFsm)
1333 }
1334}
1335
dbainbri4d3a0dc2020-12-02 00:33:42 +00001336func (oFsm *UniVlanConfigFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1337 logger.Debugw(ctx, "UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001338 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +00001339 if oFsm.pDeviceHandler != nil {
mpagenko2418ab02020-11-12 12:58:06 +00001340 //TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
1341 // current code removes the complete FSM including all flow/rule configuration done so far
1342 // this might be a bit to much, it would require fully new flow config from rwCore (at least on OnuDown/up)
1343 // maybe a more sophisticated approach is possible without clearing the data
mpagenko9a304ea2020-12-16 15:54:01 +00001344 oFsm.mutexFlowParams.RLock()
mpagenko2418ab02020-11-12 12:58:06 +00001345 if oFsm.clearPersistency {
1346 //permanently remove possibly stored persistent data
1347 if len(oFsm.uniVlanFlowParamsSlice) > 0 {
1348 var emptySlice = make([]uniVlanFlowParams, 0)
mpagenkof1fc3862021-02-16 10:09:52 +00001349 _ = oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID, &emptySlice, true) //ignore errors
mpagenko2418ab02020-11-12 12:58:06 +00001350 }
1351 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001352 logger.Debugw(ctx, "UniVlanConfigFsm persistency data not cleared", log.Fields{"device-id": oFsm.deviceID})
mpagenko2418ab02020-11-12 12:58:06 +00001353 }
mpagenkof1fc3862021-02-16 10:09:52 +00001354 if oFsm.delayNewRuleCookie != 0 {
1355 // looks like the waiting AddFlow is stuck
1356 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue/treminate
1357 }
mpagenko9a304ea2020-12-16 15:54:01 +00001358 oFsm.mutexFlowParams.RUnlock()
mpagenko2418ab02020-11-12 12:58:06 +00001359 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001360 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(ctx, oFsm.pOnuUniPort)
mpagenkodff5dda2020-08-28 11:52:01 +00001361 }
1362}
1363
dbainbri4d3a0dc2020-12-02 00:33:42 +00001364func (oFsm *UniVlanConfigFsm) processOmciVlanMessages(ctx context.Context) { //ctx context.Context?
1365 logger.Debugw(ctx, "Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001366loop:
1367 for {
mpagenkodff5dda2020-08-28 11:52:01 +00001368 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00001369 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001370 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301371 message, ok := <-oFsm.pAdaptFsm.commChan
1372 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001373 logger.Info(ctx, "UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301374 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1375 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1376 break loop
1377 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001378 logger.Debugw(ctx, "UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301379
1380 switch message.Type {
1381 case TestMsg:
1382 msg, _ := message.Data.(TestMessage)
1383 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001384 logger.Infow(ctx, "UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001385 break loop
1386 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001387 logger.Warnw(ctx, "UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301388 case OMCI:
1389 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001390 oFsm.handleOmciVlanConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301391 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001392 logger.Warn(ctx, "UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301393 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +00001394 }
1395 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001396 logger.Infow(ctx, "End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001397}
1398
dbainbri4d3a0dc2020-12-02 00:33:42 +00001399func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(ctx context.Context, msg OmciMessage) {
1400 logger.Debugw(ctx, "Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001401 "msgType": msg.OmciMsg.MessageType})
1402
1403 switch msg.OmciMsg.MessageType {
1404 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001405 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001406 if err := oFsm.handleOmciCreateResponseMessage(ctx, msg.OmciPacket); err != nil {
1407 logger.Warnw(ctx, "CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +00001408 return
1409 }
mpagenkodff5dda2020-08-28 11:52:01 +00001410 } //CreateResponseType
1411 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001412 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +00001413 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1414 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001415 logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001416 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001417 return
1418 }
1419 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1420 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001421 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001422 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001423 return
1424 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001425 logger.Debugw(ctx, "UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +00001426 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001427 logger.Errorw(ctx, "UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001428 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +00001429 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1430 return
1431 }
mpagenko01e726e2020-10-23 09:45:29 +00001432 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1433 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1434 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001435 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData", "MulticastOperationsProfile":
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001436 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +00001437 oFsm.omciMIdsResponseReceived <- true
1438 }
1439 }
1440 }
1441 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +00001442 case omci.DeleteResponseType:
1443 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001444 if err := oFsm.handleOmciDeleteResponseMessage(ctx, msg.OmciPacket); err != nil {
1445 logger.Warnw(ctx, "DeleteResponse handling aborted", log.Fields{"err": err})
mpagenko01e726e2020-10-23 09:45:29 +00001446 return
1447 }
1448 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +00001449 default:
1450 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001451 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001452 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001453 return
1454 }
1455 }
1456}
1457
dbainbri4d3a0dc2020-12-02 00:33:42 +00001458func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001459 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
1460 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001461 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001462 log.Fields{"device-id": oFsm.deviceID})
1463 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
1464 oFsm.deviceID)
1465 }
1466 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1467 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001468 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001469 log.Fields{"device-id": oFsm.deviceID})
1470 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
1471 oFsm.deviceID)
1472 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001473 logger.Debugw(ctx, "UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001474 if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001475 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
mpagenko01e726e2020-10-23 09:45:29 +00001476 "Error": msgObj.Result})
1477 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1478 return fmt.Errorf("omci CreateResponse Error for device-id %x",
1479 oFsm.deviceID)
1480 }
1481 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1482 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1483 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
1484 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001485 case "VlanTaggingFilterData", "MulticastOperationsProfile",
1486 "MulticastSubscriberConfigInfo", "MacBridgePortConfigurationData",
1487 "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001488 {
1489 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
1490 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
1491 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
1492 } else { // let the MultiEntity config proceed by stopping the wait function
1493 oFsm.omciMIdsResponseReceived <- true
1494 }
1495 }
1496 }
1497 }
1498 return nil
1499}
1500
dbainbri4d3a0dc2020-12-02 00:33:42 +00001501func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001502 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1503 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001504 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001505 log.Fields{"device-id": oFsm.deviceID})
1506 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1507 oFsm.deviceID)
1508 }
1509 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1510 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001511 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001512 log.Fields{"device-id": oFsm.deviceID})
1513 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1514 oFsm.deviceID)
1515 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001516 logger.Debugw(ctx, "UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko01e726e2020-10-23 09:45:29 +00001517 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001518 logger.Errorw(ctx, "UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001519 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1520 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1521 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1522 oFsm.deviceID)
1523 }
1524 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1525 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1526 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001527 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001528 { // let the MultiEntity config proceed by stopping the wait function
1529 oFsm.omciMIdsResponseReceived <- true
1530 }
1531 }
1532 }
1533 return nil
1534}
1535
dbainbri4d3a0dc2020-12-02 00:33:42 +00001536func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(ctx context.Context, aFlowEntryNo uint8) error {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001537 if aFlowEntryNo == 0 {
1538 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001539 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1540 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
dbainbri4d3a0dc2020-12-02 00:33:42 +00001541 logger.Debugw(ctx, "UniVlanConfigFsm Tx Create::EVTOCD", log.Fields{
mpagenkodff5dda2020-08-28 11:52:01 +00001542 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1543 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001544 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001545 associationType := 2 // default to uniPPTP
1546 if oFsm.pOnuUniPort.portType == uniVEIP {
1547 associationType = 10
1548 }
1549 // Create the EVTOCD ME
mpagenkodff5dda2020-08-28 11:52:01 +00001550 meParams := me.ParamData{
1551 EntityID: oFsm.evtocdID,
1552 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001553 "AssociationType": uint8(associationType),
1554 "AssociatedMePointer": oFsm.pOnuUniPort.entityID,
mpagenkodff5dda2020-08-28 11:52:01 +00001555 },
1556 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001557 meInstance := oFsm.pOmciCC.sendCreateEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001558 oFsm.pAdaptFsm.commChan, meParams)
1559 //accept also nil as (error) return value for writing to LastTx
1560 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001561 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001562
1563 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001564 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001565 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001566 logger.Errorw(ctx, "Evtocd create failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001567 log.Fields{"device-id": oFsm.deviceID})
1568 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1569 return fmt.Errorf("evtocd create failed %s, error %s", oFsm.deviceID, err)
1570 }
1571
1572 // Set the EVTOCD ME default params
1573 meParams = me.ParamData{
1574 EntityID: oFsm.evtocdID,
1575 Attributes: me.AttributeValueMap{
1576 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1577 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1578 "DownstreamMode": uint8(cDefaultDownstreamMode),
1579 },
1580 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001581 meInstance = oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001582 oFsm.pAdaptFsm.commChan, meParams)
1583 //accept also nil as (error) return value for writing to LastTx
1584 // - this avoids misinterpretation of new received OMCI messages
1585 oFsm.pLastTxMeInstance = meInstance
1586
1587 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001588 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001589 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001590 logger.Errorw(ctx, "Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001591 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301592 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001593 return fmt.Errorf("evtocd set TPID failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001594 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001595 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001596
mpagenko551a4d42020-12-08 18:09:20 +00001597 oFsm.mutexFlowParams.RLock()
mpagenko9a304ea2020-12-16 15:54:01 +00001598 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001599 //transparent transmission required
mpagenko551a4d42020-12-08 18:09:20 +00001600 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001601 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001602 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001603 sliceEvtocdRule := make([]uint8, 16)
1604 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1605 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1606 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1607 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1608 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1609
1610 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1611 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1612 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1613 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1614 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1615
1616 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1617 0<<cTreatTTROffset| // Do not pop any tags
1618 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1619 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1620 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1621
1622 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1623 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1624 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1625 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1626
1627 meParams := me.ParamData{
1628 EntityID: oFsm.evtocdID,
1629 Attributes: me.AttributeValueMap{
1630 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1631 },
1632 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001633 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001634 oFsm.pAdaptFsm.commChan, meParams)
1635 //accept also nil as (error) return value for writing to LastTx
1636 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001637 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001638
1639 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001640 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001641 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001642 logger.Errorw(ctx, "Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001643 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301644 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001645 return fmt.Errorf("evtocd set transparent singletagged rule failed %s, error %s", oFsm.deviceID, err)
1646
mpagenkodff5dda2020-08-28 11:52:01 +00001647 }
1648 } else {
1649 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1650 if oFsm.acceptIncrementalEvtoOption {
mpagenko9a304ea2020-12-16 15:54:01 +00001651 matchPcp := oFsm.actualUniVlanConfigRule.MatchPcp
1652 matchVid := oFsm.actualUniVlanConfigRule.MatchVid
1653 setPcp := oFsm.actualUniVlanConfigRule.SetPcp
1654 setVid := oFsm.actualUniVlanConfigRule.SetVid
mpagenkodff5dda2020-08-28 11:52:01 +00001655 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001656 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001657 "match-pcp": matchPcp, "match-vid": matchVid, "set-pcp": setPcp, "set-vid:": setVid, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001658 sliceEvtocdRule := make([]uint8, 16)
1659 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1660 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1661 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1662 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1663 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1664
1665 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001666 oFsm.actualUniVlanConfigRule.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1667 oFsm.actualUniVlanConfigRule.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001668 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1669 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1670
1671 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001672 oFsm.actualUniVlanConfigRule.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001673 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1674 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1675 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1676
1677 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001678 oFsm.actualUniVlanConfigRule.SetPcp<<cTreatPrioOffset| // as configured in flow
1679 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001680 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001681 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001682
1683 meParams := me.ParamData{
1684 EntityID: oFsm.evtocdID,
1685 Attributes: me.AttributeValueMap{
1686 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1687 },
1688 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001689 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001690 oFsm.pAdaptFsm.commChan, meParams)
1691 //accept also nil as (error) return value for writing to LastTx
1692 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001693 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001694
1695 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001696 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001697 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001698 logger.Errorw(ctx, "Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001699 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301700 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001701 return fmt.Errorf("evtocd set singletagged translation rule failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001702 }
1703 } else {
1704 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1705 { // just for local var's
1706 // this defines stacking scenario: untagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001707 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001708 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001709 sliceEvtocdRule := make([]uint8, 16)
1710 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1711 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1712 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1713 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1714 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1715
1716 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1717 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1718 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1719 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1720 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1721
1722 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1723 0<<cTreatTTROffset| // Do not pop any tags
1724 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1725 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1726 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1727
1728 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1729 0<<cTreatPrioOffset| // vlan prio set to 0
1730 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko9a304ea2020-12-16 15:54:01 +00001731 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001732 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1733
mpagenko551a4d42020-12-08 18:09:20 +00001734 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001735 meParams := me.ParamData{
1736 EntityID: oFsm.evtocdID,
1737 Attributes: me.AttributeValueMap{
1738 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1739 },
1740 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001741 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001742 oFsm.pAdaptFsm.commChan, meParams)
1743 //accept also nil as (error) return value for writing to LastTx
1744 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001745 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001746
1747 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001748 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001749 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001750 logger.Errorw(ctx, "Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001751 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301752 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001753 return fmt.Errorf("evtocd set untagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1754
mpagenkodff5dda2020-08-28 11:52:01 +00001755 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001756 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001757 { // just for local var's
1758 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001759 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001760 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001761 sliceEvtocdRule := make([]uint8, 16)
1762 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1763 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1764 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1765 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1766 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1767
1768 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1769 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1770 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1771 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1772 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1773
1774 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1775 1<<cTreatTTROffset| // pop the prio-tag
1776 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1777 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1778 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1779
mpagenko551a4d42020-12-08 18:09:20 +00001780 oFsm.mutexFlowParams.RLock()
mpagenkodff5dda2020-08-28 11:52:01 +00001781 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1782 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1783 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko9a304ea2020-12-16 15:54:01 +00001784 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001785 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001786 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001787
1788 meParams := me.ParamData{
1789 EntityID: oFsm.evtocdID,
1790 Attributes: me.AttributeValueMap{
1791 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1792 },
1793 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001794 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001795 oFsm.pAdaptFsm.commChan, meParams)
1796 //accept also nil as (error) return value for writing to LastTx
1797 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001798 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001799
1800 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001801 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001802 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001803 logger.Errorw(ctx, "Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001804 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301805 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001806 return fmt.Errorf("evtocd set priotagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1807
mpagenkodff5dda2020-08-28 11:52:01 +00001808 }
1809 } //just for local var's
1810 }
1811 }
1812
mpagenkofc4f56e2020-11-04 17:17:49 +00001813 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001814 logger.Debugw(ctx, "EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001815 oFsm.configuredUniFlow++ // one (more) flow configured
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001816 return nil
mpagenkodff5dda2020-08-28 11:52:01 +00001817}
1818
dbainbri4d3a0dc2020-12-02 00:33:42 +00001819func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(ctx context.Context, aRuleParams uniVlanRuleParams) {
mpagenko01e726e2020-10-23 09:45:29 +00001820 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1821 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1822 //transparent transmission was set
1823 //perhaps the config is not needed for removal,
1824 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
dbainbri4d3a0dc2020-12-02 00:33:42 +00001825 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001826 "device-id": oFsm.deviceID})
1827 sliceEvtocdRule := make([]uint8, 16)
1828 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1829 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1830 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1831 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1832 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1833
1834 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1835 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1836 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1837 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1838 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1839
1840 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1841 0<<cTreatTTROffset| // Do not pop any tags
1842 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1843 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1844 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1845
1846 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1847 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1848 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1849 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1850
1851 meParams := me.ParamData{
1852 EntityID: oFsm.evtocdID,
1853 Attributes: me.AttributeValueMap{
1854 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1855 },
1856 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001857 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001858 oFsm.pAdaptFsm.commChan, meParams)
1859 //accept also nil as (error) return value for writing to LastTx
1860 // - this avoids misinterpretation of new received OMCI messages
1861 oFsm.pLastTxMeInstance = meInstance
1862
1863 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001864 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001865 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001866 logger.Errorw(ctx, "Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001867 log.Fields{"device-id": oFsm.deviceID})
1868 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1869 return
1870 }
1871 } else {
1872 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1873 if oFsm.acceptIncrementalEvtoOption {
1874 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001875 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001876 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1877 sliceEvtocdRule := make([]uint8, 16)
1878 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1879 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1880 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1881 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1882 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1883
1884 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1885 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1886 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1887 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1888 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1889
1890 // delete indication for the indicated Filter
1891 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1892 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1893
1894 meParams := me.ParamData{
1895 EntityID: oFsm.evtocdID,
1896 Attributes: me.AttributeValueMap{
1897 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1898 },
1899 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001900 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001901 oFsm.pAdaptFsm.commChan, meParams)
1902 //accept also nil as (error) return value for writing to LastTx
1903 // - this avoids misinterpretation of new received OMCI messages
1904 oFsm.pLastTxMeInstance = meInstance
1905
1906 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001907 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001908 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001909 logger.Errorw(ctx, "Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001910 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1911 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1912 return
1913 }
1914 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001915 // VOL-3685
1916 // NOTE: With ALPHA ONUs it was seen that just resetting a particular entry in the EVTOCD table
1917 // and re-configuring a new entry would not work. The old entry is removed and new entry is created
1918 // indeed, but the traffic landing upstream would carry old vlan sometimes.
1919 // This is only a WORKAROUND which basically deletes the entire EVTOCD ME and re-creates it again
1920 // later when the flow is being re-installed.
1921 // Of course this is applicable to case only where single service (or single tcont) is in use and
1922 // there is only one service vlan (oFsm.acceptIncrementalEvtoOption is false in this case).
1923 // Interstingly this problem has not been observed in multi-tcont (or multi-service) scenario (in
1924 // which case the oFsm.acceptIncrementalEvtoOption is set to true).
1925 if oFsm.configuredUniFlow == 0 && !oFsm.acceptIncrementalEvtoOption {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001926 logger.Debugw(ctx, "UniVlanConfigFsm Tx Remove::EVTOCD", log.Fields{"device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001927 // When there are no more EVTOCD vlan configurations on the ONU and acceptIncrementalEvtoOption
1928 // is not enabled, delete the EVTOCD ME.
mpagenko01e726e2020-10-23 09:45:29 +00001929 meParams := me.ParamData{
1930 EntityID: oFsm.evtocdID,
mpagenko01e726e2020-10-23 09:45:29 +00001931 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001932 meInstance := oFsm.pOmciCC.sendDeleteEvtocd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001933 oFsm.pAdaptFsm.commChan, meParams)
1934 //accept also nil as (error) return value for writing to LastTx
1935 // - this avoids misinterpretation of new received OMCI messages
1936 oFsm.pLastTxMeInstance = meInstance
1937
1938 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001939 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001940 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001941 logger.Errorw(ctx, "Evtocd delete rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001942 log.Fields{"device-id": oFsm.deviceID})
1943 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1944 return
1945 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001946 } else {
1947 // NOTE : We should ideally never ether this section when oFsm.acceptIncrementalEvtoOption is set to false
1948 // This is true for only ATT/DT workflow
dbainbri4d3a0dc2020-12-02 00:33:42 +00001949 logger.Debugw(ctx, "UniVlanConfigFsm: Remove EVTOCD set operation",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001950 log.Fields{"configured-flow": oFsm.configuredUniFlow, "incremental-evto": oFsm.acceptIncrementalEvtoOption})
1951 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1952 { // just for local var's
1953 // this defines stacking scenario: untagged->singletagged
1954 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1955 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1956 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1957 // delete now assumes there is only one such rule!
dbainbri4d3a0dc2020-12-02 00:33:42 +00001958 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001959 "device-id": oFsm.deviceID})
1960 sliceEvtocdRule := make([]uint8, 16)
1961 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1962 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1963 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1964 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1965 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
mpagenko01e726e2020-10-23 09:45:29 +00001966
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001967 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1968 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1969 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1970 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1971 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
mpagenko01e726e2020-10-23 09:45:29 +00001972
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001973 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1974 0<<cTreatTTROffset| // Do not pop any tags
1975 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1976 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1977 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
mpagenko01e726e2020-10-23 09:45:29 +00001978
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001979 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1980 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1981 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1982 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
mpagenko01e726e2020-10-23 09:45:29 +00001983
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001984 meParams := me.ParamData{
1985 EntityID: oFsm.evtocdID,
1986 Attributes: me.AttributeValueMap{
1987 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1988 },
1989 }
1990 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1991 oFsm.pAdaptFsm.commChan, meParams)
1992 //accept also nil as (error) return value for writing to LastTx
1993 // - this avoids misinterpretation of new received OMCI messages
1994 oFsm.pLastTxMeInstance = meInstance
1995
1996 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001997 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001998 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001999 logger.Errorw(ctx, "Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002000 log.Fields{"device-id": oFsm.deviceID})
2001 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
2002 return
2003 }
2004 } // just for local var's
2005 { // just for local var's
2006 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00002007 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002008 "device-id": oFsm.deviceID})
2009 sliceEvtocdRule := make([]uint8, 16)
2010 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
2011 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
2012 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
2013 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
2014 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
2015
2016 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
2017 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
2018 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
2019 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
2020 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
2021
2022 // delete indication for the indicated Filter
2023 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
2024 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
2025
2026 meParams := me.ParamData{
2027 EntityID: oFsm.evtocdID,
2028 Attributes: me.AttributeValueMap{
2029 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
2030 },
2031 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00002032 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002033 oFsm.pAdaptFsm.commChan, meParams)
2034 //accept also nil as (error) return value for writing to LastTx
2035 // - this avoids misinterpretation of new received OMCI messages
2036 oFsm.pLastTxMeInstance = meInstance
2037
2038 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002039 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002040 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002041 logger.Errorw(ctx, "Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002042 log.Fields{"device-id": oFsm.deviceID})
2043 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
2044 return
2045 }
mpagenko01e726e2020-10-23 09:45:29 +00002046 }
2047 } //just for local var's
2048 }
2049 }
2050
mpagenkofc4f56e2020-11-04 17:17:49 +00002051 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00002052 logger.Debugw(ctx, "EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra26a40922021-01-29 17:14:34 -08002053 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone, aRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00002054}
2055
dbainbri4d3a0dc2020-12-02 00:33:42 +00002056func (oFsm *UniVlanConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenkodff5dda2020-08-28 11:52:01 +00002057 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05302058 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00002059 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00002060 // logger.Infow(ctx,"LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00002061 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
dbainbri4d3a0dc2020-12-02 00:33:42 +00002062 logger.Warnw(ctx, "UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002063 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002064 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05302065 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002066 logger.Debug(ctx, "UniVlanConfigFsm multi entity response received")
mpagenkodff5dda2020-08-28 11:52:01 +00002067 return nil
2068 }
2069 // should not happen so far
dbainbri4d3a0dc2020-12-02 00:33:42 +00002070 logger.Warnw(ctx, "UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002071 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002072 }
2073}
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002074
mpagenko551a4d42020-12-08 18:09:20 +00002075func (oFsm *UniVlanConfigFsm) performSettingMulticastME(ctx context.Context, tpID uint8, multicastGemPortID uint16, vlanID uint32) error {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002076 logger.Debugw(ctx, "Setting Multicast MEs", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002077 "multicastGemPortID": multicastGemPortID, "vlanID": vlanID})
dbainbri4d3a0dc2020-12-02 00:33:42 +00002078 errCreateMOP := oFsm.performCreatingMulticastOperationProfile(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002079 if errCreateMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002080 logger.Errorw(ctx, "MulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002081 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002082 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002083 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMOP)
2084 }
2085
dbainbri4d3a0dc2020-12-02 00:33:42 +00002086 errSettingMOP := oFsm.performSettingMulticastOperationProfile(ctx, multicastGemPortID, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002087 if errSettingMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002088 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002089 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002090 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002091 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errSettingMOP)
2092 }
2093
dbainbri4d3a0dc2020-12-02 00:33:42 +00002094 errCreateMSCI := oFsm.performCreatingMulticastSubscriberConfigInfo(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002095 if errCreateMSCI != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002096 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002097 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002098 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002099 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMSCI)
2100 }
2101
2102 meParams := me.ParamData{
2103 EntityID: macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2104 Attributes: me.AttributeValueMap{
2105 "BridgeIdPointer": macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2106 "PortNum": 0xf0, //fixed unique ANI side indication
2107 "TpType": 6, //MCGemIWTP
2108 "TpPointer": multicastGemPortID,
2109 },
2110 }
2111 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
2112 oFsm.pAdaptFsm.commChan, meParams)
2113 //accept also nil as (error) return value for writing to LastTx
2114 // - this avoids misinterpretation of new received OMCI messages
2115 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002116 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002117 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002118 logger.Errorw(ctx, "CreateMBPConfigData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002119 log.Fields{"device-id": oFsm.deviceID, "MBPConfigDataID": macBridgeServiceProfileEID})
mpagenko9a304ea2020-12-16 15:54:01 +00002120 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002121 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, err)
2122 }
2123
2124 // ==> Start creating VTFD for mcast vlan
2125
2126 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
2127 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
2128 mcastVtfdID := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
2129
dbainbri4d3a0dc2020-12-02 00:33:42 +00002130 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD for mcast", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002131 "EntitytId": strconv.FormatInt(int64(mcastVtfdID), 16), "mcastVlanID": vlanID,
2132 "in state": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
2133 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
2134
2135 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
2136 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
2137 // new vlan associated with a different TP.
2138 vtfdFilterList[0] = uint16(vlanID)
2139
2140 meParams = me.ParamData{
2141 EntityID: mcastVtfdID,
2142 Attributes: me.AttributeValueMap{
2143 "VlanFilterList": vtfdFilterList,
2144 "ForwardOperation": uint8(0x10), //VID investigation
2145 "NumberOfEntries": oFsm.numVlanFilterEntries,
2146 },
2147 }
2148 meInstance = oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
2149 oFsm.pAdaptFsm.commChan, meParams)
2150 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002151 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002152 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002153 logger.Errorw(ctx, "CreateMcastVlanFilterData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002154 log.Fields{"device-id": oFsm.deviceID, "mcastVtfdID": mcastVtfdID})
mpagenko9a304ea2020-12-16 15:54:01 +00002155 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002156 return fmt.Errorf("createMcastVlanFilterData responseError %s, error %s", oFsm.deviceID, err)
2157 }
2158
2159 return nil
2160}
2161
dbainbri4d3a0dc2020-12-02 00:33:42 +00002162func (oFsm *UniVlanConfigFsm) performCreatingMulticastSubscriberConfigInfo(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002163 instID, err := oFsm.pDeviceHandler.getUniPortMEEntityID(oFsm.pOnuUniPort.portNo)
2164 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002165 logger.Errorw(ctx, "error fetching uni port me instance",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002166 log.Fields{"device-id": oFsm.deviceID, "portNo": oFsm.pOnuUniPort.portNo})
2167 return err
2168 }
2169 meParams := me.ParamData{
2170 EntityID: instID,
2171 Attributes: me.AttributeValueMap{
2172 "MeType": 0,
2173 //Direct reference to the Operation profile
2174 //TODO ANI side used on UNI side, not the clearest option.
2175 "MulticastOperationsProfilePointer": macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo),
2176 },
2177 }
2178 meInstance := oFsm.pOmciCC.sendCreateMulticastSubConfigInfoVar(context.TODO(), ConstDefaultOmciTimeout, true,
2179 oFsm.pAdaptFsm.commChan, meParams)
2180 //accept also nil as (error) return value for writing to LastTx
2181 // - this avoids misinterpretation of new received OMCI messages
2182 oFsm.pLastTxMeInstance = meInstance
2183 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002184 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002185 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002186 logger.Errorw(ctx, "CreateMulticastSubConfigInfo create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002187 log.Fields{"device-id": oFsm.deviceID, "MulticastSubConfigInfo": instID})
2188 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s", oFsm.deviceID)
2189 }
2190 return nil
2191}
2192
dbainbri4d3a0dc2020-12-02 00:33:42 +00002193func (oFsm *UniVlanConfigFsm) performCreatingMulticastOperationProfile(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002194 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2195 meParams := me.ParamData{
2196 EntityID: instID,
2197 Attributes: me.AttributeValueMap{
2198 "IgmpVersion": 2,
2199 "IgmpFunction": 0,
2200 //0 means false
2201 "ImmediateLeave": 0,
2202 "Robustness": 2,
2203 "QuerierIp": 0,
2204 "QueryInterval": 125,
2205 "QuerierMaxResponseTime": 100,
2206 "LastMemberResponseTime": 10,
2207 //0 means false
2208 "UnauthorizedJoinBehaviour": 0,
2209 },
2210 }
2211 meInstance := oFsm.pOmciCC.sendCreateMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2212 oFsm.pAdaptFsm.commChan, meParams)
2213 //accept also nil as (error) return value for writing to LastTx
2214 // - this avoids misinterpretation of new received OMCI messages
2215 oFsm.pLastTxMeInstance = meInstance
2216 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002217 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002218 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002219 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002220 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2221 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2222 }
2223 return nil
2224}
2225
dbainbri4d3a0dc2020-12-02 00:33:42 +00002226func (oFsm *UniVlanConfigFsm) performSettingMulticastOperationProfile(ctx context.Context, multicastGemPortID uint16, vlanID uint32) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002227 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2228 //TODO check that this is correct
2229 // Table control
2230 //setCtrl = 1
2231 //rowPartId = 0
2232 //test = 0
2233 //rowKey = 0
2234 tableCtrlStr := "0100000000000000"
2235 tableCtrl := AsByteSlice(tableCtrlStr)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002236 dynamicAccessCL := make([]uint8, 24)
2237 copy(dynamicAccessCL, tableCtrl)
2238 //Multicast GemPortId
2239 binary.BigEndian.PutUint16(dynamicAccessCL[2:], multicastGemPortID)
2240 // python version waits for installation of flows, see line 723 onward of
2241 // brcm_openomci_onu_handler.py
2242 binary.BigEndian.PutUint16(dynamicAccessCL[4:], uint16(vlanID))
2243 //Source IP all to 0
2244 binary.BigEndian.PutUint32(dynamicAccessCL[6:], IPToInt32(net.IPv4(0, 0, 0, 0)))
2245 //TODO start and end are hardcoded, get from TP
2246 // Destination IP address start of range
2247 binary.BigEndian.PutUint32(dynamicAccessCL[10:], IPToInt32(net.IPv4(225, 0, 0, 0)))
2248 // Destination IP address end of range
2249 binary.BigEndian.PutUint32(dynamicAccessCL[14:], IPToInt32(net.IPv4(239, 255, 255, 255)))
2250 //imputed group bandwidth
2251 binary.BigEndian.PutUint16(dynamicAccessCL[18:], 0)
2252
2253 meParams := me.ParamData{
2254 EntityID: instID,
2255 Attributes: me.AttributeValueMap{
2256 "DynamicAccessControlListTable": dynamicAccessCL,
2257 },
2258 }
2259 meInstance := oFsm.pOmciCC.sendSetMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2260 oFsm.pAdaptFsm.commChan, meParams)
2261 //accept also nil as (error) return value for writing to LastTx
2262 // - this avoids misinterpretation of new received OMCI messages
2263 oFsm.pLastTxMeInstance = meInstance
2264 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002265 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002266 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002267 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002268 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2269 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2270 }
2271 return nil
2272}
Girish Gowdra26a40922021-01-29 17:14:34 -08002273
2274// IsFlowRemovePending returns true if there are pending flows to remove, else false.
2275func (oFsm *UniVlanConfigFsm) IsFlowRemovePending() bool {
2276 oFsm.mutexFlowParams.RLock()
2277 defer oFsm.mutexFlowParams.RUnlock()
2278 return len(oFsm.uniRemoveFlowsSlice) > 0
2279}