blob: cfec8e827e0399c213cbbd4fb8cc3c2cf268b82d [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
mpagenko01e726e2020-10-23 09:45:29 +000090 vlanEvStart = "vlanEvStart"
91 vlanEvWaitTechProf = "vlanEvWaitTechProf"
92 vlanEvContinueConfig = "vlanEvContinueConfig"
93 vlanEvStartConfig = "vlanEvStartConfig"
94 vlanEvRxConfigVtfd = "vlanEvRxConfigVtfd"
95 vlanEvRxConfigEvtocd = "vlanEvRxConfigEvtocd"
mpagenko551a4d42020-12-08 18:09:20 +000096 vlanEvWaitTPIncr = "vlanEvWaitTPIncr"
mpagenko01e726e2020-10-23 09:45:29 +000097 vlanEvIncrFlowConfig = "vlanEvIncrFlowConfig"
mpagenkofc4f56e2020-11-04 17:17:49 +000098 vlanEvRenew = "vlanEvRenew"
mpagenko01e726e2020-10-23 09:45:29 +000099 vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
100 vlanEvRemFlowDone = "vlanEvRemFlowDone"
101 vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000102 //vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
103 //vlanEvTimeoutMids = "vlanEvTimeoutMids"
Himani Chawla4d908332020-08-31 12:30:20 +0530104 vlanEvReset = "vlanEvReset"
105 vlanEvRestart = "vlanEvRestart"
mpagenkodff5dda2020-08-28 11:52:01 +0000106)
mpagenko01e726e2020-10-23 09:45:29 +0000107
mpagenkodff5dda2020-08-28 11:52:01 +0000108const (
Holger Hildebrandt10d98192021-01-27 15:29:31 +0000109 // states of config UNI port VLAN FSM
mpagenkodff5dda2020-08-28 11:52:01 +0000110 vlanStDisabled = "vlanStDisabled"
111 vlanStStarting = "vlanStStarting"
112 vlanStWaitingTechProf = "vlanStWaitingTechProf"
113 vlanStConfigVtfd = "vlanStConfigVtfd"
114 vlanStConfigEvtocd = "vlanStConfigEvtocd"
115 vlanStConfigDone = "vlanStConfigDone"
mpagenko551a4d42020-12-08 18:09:20 +0000116 vlanStIncrFlowWaitTP = "vlanStIncrFlowWaitTP"
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000117 vlanStConfigIncrFlow = "vlanStConfigIncrFlow"
mpagenko01e726e2020-10-23 09:45:29 +0000118 vlanStRemoveFlow = "vlanStRemoveFlow"
mpagenkodff5dda2020-08-28 11:52:01 +0000119 vlanStCleanupDone = "vlanStCleanupDone"
120 vlanStResetting = "vlanStResetting"
121)
mpagenkof1fc3862021-02-16 10:09:52 +0000122const cVlanFsmIdleState = vlanStConfigDone // state where no OMCI activity is done (for a longer time)
123const cVlanFsmConfiguredState = vlanStConfigDone // state that indicates that at least some valid user related VLAN configuration should exist
mpagenkodff5dda2020-08-28 11:52:01 +0000124
mpagenko01e726e2020-10-23 09:45:29 +0000125type uniVlanRuleParams struct {
mpagenko551a4d42020-12-08 18:09:20 +0000126 TpID uint8 `json:"tp_id"`
mpagenko01e726e2020-10-23 09:45:29 +0000127 MatchVid uint32 `json:"match_vid"` //use uint32 types for allowing immediate bitshifting
128 MatchPcp uint32 `json:"match_pcp"`
129 TagsToRemove uint32 `json:"tags_to_remove"`
130 SetVid uint32 `json:"set_vid"`
131 SetPcp uint32 `json:"set_pcp"`
132}
133
134type uniVlanFlowParams struct {
135 CookieSlice []uint64 `json:"cookie_slice"`
136 VlanRuleParams uniVlanRuleParams `json:"vlan_rule_params"`
137}
138
139type uniRemoveVlanFlowParams struct {
140 cookie uint64 //just the last cookie valid for removal
141 vlanRuleParams uniVlanRuleParams
142}
143
mpagenkodff5dda2020-08-28 11:52:01 +0000144//UniVlanConfigFsm defines the structure for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
145type UniVlanConfigFsm struct {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530146 pDeviceHandler *deviceHandler
mpagenko01e726e2020-10-23 09:45:29 +0000147 deviceID string
Himani Chawla6d2ae152020-09-02 13:11:20 +0530148 pOmciCC *omciCC
149 pOnuUniPort *onuUniPort
150 pUniTechProf *onuUniTechProf
151 pOnuDB *onuDeviceDB
mpagenkodff5dda2020-08-28 11:52:01 +0000152 requestEvent OnuDeviceEvent
153 omciMIdsResponseReceived chan bool //seperate channel needed for checking multiInstance OMCI message responses
154 pAdaptFsm *AdapterFsm
155 acceptIncrementalEvtoOption bool
mpagenko2418ab02020-11-12 12:58:06 +0000156 clearPersistency bool
mpagenko551a4d42020-12-08 18:09:20 +0000157 mutexFlowParams sync.RWMutex
mpagenkof1fc3862021-02-16 10:09:52 +0000158 chCookieDeleted chan bool //channel to indicate that a specificly indicated cookie was deleted
mpagenko9a304ea2020-12-16 15:54:01 +0000159 actualUniVlanConfigRule uniVlanRuleParams
mpagenko01e726e2020-10-23 09:45:29 +0000160 uniVlanFlowParamsSlice []uniVlanFlowParams
161 uniRemoveFlowsSlice []uniRemoveVlanFlowParams
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000162 numUniFlows uint8 // expected number of flows should be less than 12
163 configuredUniFlow uint8
mpagenko01e726e2020-10-23 09:45:29 +0000164 numRemoveFlows uint8
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000165 numVlanFilterEntries uint8
mpagenko01e726e2020-10-23 09:45:29 +0000166 vlanFilterList [cVtfdTableSize]uint16
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000167 evtocdID uint16
mpagenko01e726e2020-10-23 09:45:29 +0000168 pLastTxMeInstance *me.ManagedEntity
mpagenkofc4f56e2020-11-04 17:17:49 +0000169 requestEventOffset uint8
mpagenko551a4d42020-12-08 18:09:20 +0000170 TpIDWaitingFor uint8
mpagenkof1fc3862021-02-16 10:09:52 +0000171 //cookie value that indicates that a rule to add is delayed by waiting for deletion of some other existing rule with the same cookie
172 delayNewRuleCookie uint64
mpagenkodff5dda2020-08-28 11:52:01 +0000173}
174
mpagenko01e726e2020-10-23 09:45:29 +0000175//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
176// of ONU UNI ports via OMCI
dbainbri4d3a0dc2020-12-02 00:33:42 +0000177func NewUniVlanConfigFsm(ctx context.Context, apDeviceHandler *deviceHandler, apDevOmciCC *omciCC, apUniPort *onuUniPort,
mpagenko551a4d42020-12-08 18:09:20 +0000178 apUniTechProf *onuUniTechProf, apOnuDB *onuDeviceDB, aTechProfileID uint8,
mpagenko01e726e2020-10-23 09:45:29 +0000179 aRequestEvent OnuDeviceEvent, aName string, aCommChannel chan Message, aAcceptIncrementalEvto bool,
180 aCookieSlice []uint64, aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) *UniVlanConfigFsm {
mpagenkodff5dda2020-08-28 11:52:01 +0000181 instFsm := &UniVlanConfigFsm{
182 pDeviceHandler: apDeviceHandler,
mpagenko01e726e2020-10-23 09:45:29 +0000183 deviceID: apDeviceHandler.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +0000184 pOmciCC: apDevOmciCC,
185 pOnuUniPort: apUniPort,
186 pUniTechProf: apUniTechProf,
187 pOnuDB: apOnuDB,
mpagenkodff5dda2020-08-28 11:52:01 +0000188 requestEvent: aRequestEvent,
189 acceptIncrementalEvtoOption: aAcceptIncrementalEvto,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000190 numUniFlows: 0,
191 configuredUniFlow: 0,
mpagenko01e726e2020-10-23 09:45:29 +0000192 numRemoveFlows: 0,
mpagenko2418ab02020-11-12 12:58:06 +0000193 clearPersistency: true,
mpagenkodff5dda2020-08-28 11:52:01 +0000194 }
195
mpagenko01e726e2020-10-23 09:45:29 +0000196 instFsm.pAdaptFsm = NewAdapterFsm(aName, instFsm.deviceID, aCommChannel)
mpagenkodff5dda2020-08-28 11:52:01 +0000197 if instFsm.pAdaptFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000198 logger.Errorw(ctx, "UniVlanConfigFsm's AdapterFsm could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000199 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000200 return nil
201 }
mpagenkodff5dda2020-08-28 11:52:01 +0000202 instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
203 vlanStDisabled,
204 fsm.Events{
205 {Name: vlanEvStart, Src: []string{vlanStDisabled}, Dst: vlanStStarting},
206 {Name: vlanEvWaitTechProf, Src: []string{vlanStStarting}, Dst: vlanStWaitingTechProf},
207 {Name: vlanEvContinueConfig, Src: []string{vlanStWaitingTechProf}, Dst: vlanStConfigVtfd},
208 {Name: vlanEvStartConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigVtfd},
209 {Name: vlanEvRxConfigVtfd, Src: []string{vlanStConfigVtfd}, Dst: vlanStConfigEvtocd},
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000210 {Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
211 Dst: vlanStConfigDone},
mpagenko551a4d42020-12-08 18:09:20 +0000212 {Name: vlanEvRenew, Src: []string{vlanStConfigDone}, Dst: vlanStStarting},
213 {Name: vlanEvWaitTPIncr, Src: []string{vlanStConfigDone}, Dst: vlanStIncrFlowWaitTP},
214 {Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone, vlanStIncrFlowWaitTP},
215 Dst: vlanStConfigIncrFlow},
mpagenko01e726e2020-10-23 09:45:29 +0000216 {Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
217 {Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
218 {Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000219 /*
220 {Name: vlanEvTimeoutSimple, Src: []string{
221 vlanStCreatingDot1PMapper, vlanStCreatingMBPCD, vlanStSettingTconts, vlanStSettingDot1PMapper}, Dst: vlanStStarting},
222 {Name: vlanEvTimeoutMids, Src: []string{
223 vlanStCreatingGemNCTPs, vlanStCreatingGemIWs, vlanStSettingPQs}, Dst: vlanStStarting},
224 */
225 // exceptional treatment for all states except vlanStResetting
226 {Name: vlanEvReset, Src: []string{vlanStStarting, vlanStWaitingTechProf,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000227 vlanStConfigVtfd, vlanStConfigEvtocd, vlanStConfigDone, vlanStConfigIncrFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000228 vlanStRemoveFlow, vlanStCleanupDone},
mpagenkodff5dda2020-08-28 11:52:01 +0000229 Dst: vlanStResetting},
230 // the only way to get to resource-cleared disabled state again is via "resseting"
231 {Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
232 },
mpagenkodff5dda2020-08-28 11:52:01 +0000233 fsm.Callbacks{
dbainbri4d3a0dc2020-12-02 00:33:42 +0000234 "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
235 "enter_" + vlanStStarting: func(e *fsm.Event) { instFsm.enterConfigStarting(ctx, e) },
236 "enter_" + vlanStConfigVtfd: func(e *fsm.Event) { instFsm.enterConfigVtfd(ctx, e) },
237 "enter_" + vlanStConfigEvtocd: func(e *fsm.Event) { instFsm.enterConfigEvtocd(ctx, e) },
238 "enter_" + vlanStConfigDone: func(e *fsm.Event) { instFsm.enterVlanConfigDone(ctx, e) },
239 "enter_" + vlanStConfigIncrFlow: func(e *fsm.Event) { instFsm.enterConfigIncrFlow(ctx, e) },
240 "enter_" + vlanStRemoveFlow: func(e *fsm.Event) { instFsm.enterRemoveFlow(ctx, e) },
241 "enter_" + vlanStCleanupDone: func(e *fsm.Event) { instFsm.enterVlanCleanupDone(ctx, e) },
242 "enter_" + vlanStResetting: func(e *fsm.Event) { instFsm.enterResetting(ctx, e) },
243 "enter_" + vlanStDisabled: func(e *fsm.Event) { instFsm.enterDisabled(ctx, e) },
mpagenkodff5dda2020-08-28 11:52:01 +0000244 },
245 )
246 if instFsm.pAdaptFsm.pFsm == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000247 logger.Errorw(ctx, "UniVlanConfigFsm's Base FSM could not be instantiated!!", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000248 "device-id": instFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000249 return nil
250 }
251
dbainbri4d3a0dc2020-12-02 00:33:42 +0000252 _ = instFsm.initUniFlowParams(ctx, aTechProfileID, aCookieSlice, aMatchVlan, aSetVlan, aSetPcp)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000253
dbainbri4d3a0dc2020-12-02 00:33:42 +0000254 logger.Debugw(ctx, "UniVlanConfigFsm created", log.Fields{"device-id": instFsm.deviceID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000255 "accIncrEvto": instFsm.acceptIncrementalEvtoOption})
mpagenkodff5dda2020-08-28 11:52:01 +0000256 return instFsm
257}
258
mpagenko01e726e2020-10-23 09:45:29 +0000259//initUniFlowParams is a simplified form of SetUniFlowParams() used for first flow parameters configuration
mpagenko551a4d42020-12-08 18:09:20 +0000260func (oFsm *UniVlanConfigFsm) initUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000261 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
262 loRuleParams := uniVlanRuleParams{
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000263 TpID: aTpID,
264 MatchVid: uint32(aMatchVlan),
265 SetVid: uint32(aSetVlan),
266 SetPcp: uint32(aSetPcp),
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000267 }
268 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
mpagenko01e726e2020-10-23 09:45:29 +0000269 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
270 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000271
mpagenko01e726e2020-10-23 09:45:29 +0000272 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000273 //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 +0000274 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000275 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
276 } else {
277 if !oFsm.acceptIncrementalEvtoOption {
278 //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 +0000279 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000280 }
281 }
282
mpagenko01e726e2020-10-23 09:45:29 +0000283 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000284 // no prio/vid filtering requested
mpagenko01e726e2020-10-23 09:45:29 +0000285 loRuleParams.TagsToRemove = 0 //no tag pop action
286 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
287 if loRuleParams.SetPcp == cCopyPrioFromInner {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000288 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
289 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
290 // might collide with NoMatchVid/CopyPrio(/setVid) setting
291 // this was some precondition setting taken over from py adapter ..
mpagenko01e726e2020-10-23 09:45:29 +0000292 loRuleParams.SetPcp = 0
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000293 }
294 }
mpagenko01e726e2020-10-23 09:45:29 +0000295
296 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
297 loFlowParams.CookieSlice = make([]uint64, 0)
298 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
299
300 //no mutex protection is required for initial access and adding the first flow is always possible
301 oFsm.uniVlanFlowParamsSlice = make([]uniVlanFlowParams, 0)
302 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000303 logger.Debugw(ctx, "first UniVlanConfigFsm flow added", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000304 "Cookies": oFsm.uniVlanFlowParamsSlice[0].CookieSlice,
305 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
306 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
307 "SetPcp": loRuleParams.SetPcp,
308 "device-id": oFsm.deviceID})
309 oFsm.numUniFlows = 1
310 oFsm.uniRemoveFlowsSlice = make([]uniRemoveVlanFlowParams, 0) //initially nothing to remove
311
312 //permanently store flow config for reconcile case
dbainbri4d3a0dc2020-12-02 00:33:42 +0000313 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
mpagenkof1fc3862021-02-16 10:09:52 +0000314 &oFsm.uniVlanFlowParamsSlice, true); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000315 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000316 return err
317 }
318
319 return nil
320}
321
mpagenko551a4d42020-12-08 18:09:20 +0000322//GetWaitingTpID returns the TpId that the FSM might be waiting for continuation (0 if none)
323func (oFsm *UniVlanConfigFsm) GetWaitingTpID() uint8 {
324 //mutex protection is required for possible concurrent access to FSM members
325 oFsm.mutexFlowParams.RLock()
326 defer oFsm.mutexFlowParams.RUnlock()
327 return oFsm.TpIDWaitingFor
328}
329
mpagenko2418ab02020-11-12 12:58:06 +0000330//RequestClearPersistency sets the internal flag to not clear persistency data (false=NoClear)
331func (oFsm *UniVlanConfigFsm) RequestClearPersistency(aClear bool) {
332 //mutex protection is required for possible concurrent access to FSM members
mpagenko551a4d42020-12-08 18:09:20 +0000333 oFsm.mutexFlowParams.RLock()
334 defer oFsm.mutexFlowParams.RUnlock()
mpagenko2418ab02020-11-12 12:58:06 +0000335 oFsm.clearPersistency = aClear
336}
337
mpagenko01e726e2020-10-23 09:45:29 +0000338//SetUniFlowParams verifies on existence of flow parameters to be configured,
339// optionally udates the cookie list or appends a new flow if there is space
340// if possible the FSM is trigggerd to start with the processing
mpagenko551a4d42020-12-08 18:09:20 +0000341// ignore complexity by now
342// nolint: gocyclo
343func (oFsm *UniVlanConfigFsm) SetUniFlowParams(ctx context.Context, aTpID uint8, aCookieSlice []uint64,
mpagenko01e726e2020-10-23 09:45:29 +0000344 aMatchVlan uint16, aSetVlan uint16, aSetPcp uint8) error {
345 loRuleParams := uniVlanRuleParams{
346 TpID: aTpID,
347 MatchVid: uint32(aMatchVlan),
348 SetVid: uint32(aSetVlan),
349 SetPcp: uint32(aSetPcp),
350 }
351 // some automatic adjustments on the filter/treat parameters as not specifically configured/ensured by flow configuration parameters
352 loRuleParams.TagsToRemove = 1 //one tag to remove as default setting
353 loRuleParams.MatchPcp = cPrioDoNotFilter // do not Filter on prio as default
354
355 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
356 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
357 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
358 //TODO!!: maybe be needed to be re-checked at flow deletion (but assume all flows are always deleted togehther)
359 } else {
360 if !oFsm.acceptIncrementalEvtoOption {
361 //then matchVlan is don't care and should be overwritten to 'transparent' here to avoid unneeded multiple flow entries
362 loRuleParams.MatchVid = uint32(of.OfpVlanId_OFPVID_PRESENT)
363 }
364 }
365
366 if loRuleParams.MatchVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
367 // no prio/vid filtering requested
368 loRuleParams.TagsToRemove = 0 //no tag pop action
369 loRuleParams.MatchPcp = cPrioIgnoreTag // no vlan tag filtering
370 if loRuleParams.SetPcp == cCopyPrioFromInner {
371 //in case of no filtering and configured PrioCopy ensure default prio setting to 0
372 // which is required for stacking of untagged, but obviously also ensures prio setting for prio/singletagged
373 // might collide with NoMatchVid/CopyPrio(/setVid) setting
374 // this was some precondition setting taken over from py adapter ..
375 loRuleParams.SetPcp = 0
376 }
377 }
378
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000379 flowEntryMatch := false
mpagenko01e726e2020-10-23 09:45:29 +0000380 flowCookieModify := false
mpagenkof1fc3862021-02-16 10:09:52 +0000381 requestAppendRule := false
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000382 //mutex protection is required for possible concurrent access to FSM members
383 oFsm.mutexFlowParams.Lock()
mpagenko01e726e2020-10-23 09:45:29 +0000384 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
385 //TODO: Verify if using e.g. hashes for the structures here for comparison may generate
386 // countable run time optimization (perhaps with including the hash in kvStore storage?)
387 if storedUniFlowParams.VlanRuleParams == loRuleParams {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000388 flowEntryMatch = true
dbainbri4d3a0dc2020-12-02 00:33:42 +0000389 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - rule already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000390 "device-id": oFsm.deviceID})
391 var cookieMatch bool
392 for _, newCookie := range aCookieSlice { // for all cookies available in the arguments
393 cookieMatch = false
394 for _, cookie := range storedUniFlowParams.CookieSlice {
395 if cookie == newCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000396 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - and cookie already exists", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000397 "device-id": oFsm.deviceID, "cookie": cookie})
398 cookieMatch = true
399 break //found new cookie - no further search for this requested cookie
400 }
401 }
402 if !cookieMatch {
mpagenkof1fc3862021-02-16 10:09:52 +0000403 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
404 if delayedCookie != 0 {
405 //a delay for adding the cookie to this rule is requested
406 // take care of the mutex which is already locked here, need to unlock/lock accordingly to prevent deadlock in suspension
407 oFsm.mutexFlowParams.Unlock()
408 oFsm.suspendNewRule(ctx)
409 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
410 oFsm.mutexFlowParams.Lock()
411 } else {
412 logger.Debugw(ctx, "UniVlanConfigFsm flow setting -adding new cookie", log.Fields{
413 "device-id": oFsm.deviceID, "cookie": newCookie})
414 //as range works with copies of the slice we have to write to the original slice!!
415 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
416 newCookie)
417 flowCookieModify = true
418 }
mpagenko01e726e2020-10-23 09:45:29 +0000419 }
420 } //for all new cookies
421 break // found rule - no further rule search
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000422 }
423 }
mpagenkof1fc3862021-02-16 10:09:52 +0000424 oFsm.mutexFlowParams.Unlock()
425
426 if !flowEntryMatch { //it is (was) a new rule
427 delayedCookie := oFsm.suspendIfRequiredNewRule(ctx, aCookieSlice)
428 requestAppendRule = true //default assumption here is that rule is to be appended
429 flowCookieModify = true //and that the the flow data base is to be updated
430 if delayedCookie != 0 { //it was suspended
431 flowCookieModify, requestAppendRule = oFsm.reviseFlowConstellation(ctx, delayedCookie, loRuleParams)
432 }
433 }
434 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
435 if requestAppendRule {
436 oFsm.mutexFlowParams.Lock()
437 defer oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000438 if oFsm.numUniFlows < cMaxAllowedFlows {
mpagenko01e726e2020-10-23 09:45:29 +0000439 loFlowParams := uniVlanFlowParams{VlanRuleParams: loRuleParams}
440 loFlowParams.CookieSlice = make([]uint64, 0)
441 loFlowParams.CookieSlice = append(loFlowParams.CookieSlice, aCookieSlice...)
442 oFsm.uniVlanFlowParamsSlice = append(oFsm.uniVlanFlowParamsSlice, loFlowParams)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000443 logger.Debugw(ctx, "UniVlanConfigFsm flow add", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000444 "Cookies": oFsm.uniVlanFlowParamsSlice[oFsm.numUniFlows].CookieSlice,
445 "MatchVid": strconv.FormatInt(int64(loRuleParams.MatchVid), 16),
446 "SetVid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
Girish Gowdra041dcb32020-11-16 16:54:30 -0800447 "SetPcp": loRuleParams.SetPcp, "numberofFlows": oFsm.numUniFlows + 1,
mpagenko01e726e2020-10-23 09:45:29 +0000448 "device-id": oFsm.deviceID})
449
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000450 oFsm.numUniFlows++
mpagenko01e726e2020-10-23 09:45:29 +0000451 // note: theoretical it would be possible to clear the same rule from the remove slice
452 // (for entries that have not yet been started with removal)
453 // but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
454 // 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 +0000455
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000456 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
457 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
458 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
mpagenko551a4d42020-12-08 18:09:20 +0000459 if oFsm.configuredUniFlow == 0 {
460 // this is a restart with a complete new flow, we can re-use the initial flow config control
461 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000462 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000463 go func(a_pBaseFsm *fsm.FSM) {
464 _ = a_pBaseFsm.Event(vlanEvRenew)
465 }(pConfigVlanStateBaseFsm)
466 } else {
467 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000468 //store the actual rule that shall be worked upon in the following transient states
469 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000470 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000471 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000472 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
473 oFsm.TpIDWaitingFor = tpID
mpagenko9a304ea2020-12-16 15:54:01 +0000474 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request (on setConfig)", log.Fields{
475 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
476 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
477
mpagenko551a4d42020-12-08 18:09:20 +0000478 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
479 if aTechProfDone {
480 // let the vlan processing continue with next rule
481 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
482 } else {
483 // set to waiting for Techprofile
484 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
485 }
486 }(pConfigVlanStateBaseFsm, loTechProfDone)
487 }
mpagenko01e726e2020-10-23 09:45:29 +0000488 } // if not in the appropriate state a new entry will be automatically considered later
489 // when the configDone state is reached
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000490 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000491 logger.Errorw(ctx, "UniVlanConfigFsm flow limit exceeded", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000492 "device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
493 return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
494 }
mpagenkofc4f56e2020-11-04 17:17:49 +0000495 } else {
496 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000497 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenkofc4f56e2020-11-04 17:17:49 +0000498 if oFsm.numUniFlows == oFsm.configuredUniFlow {
499 //all requested rules really have been configured
500 // state transition notification is checked in deviceHandler
501 if oFsm.pDeviceHandler != nil {
502 //also the related TechProfile was already configured
dbainbri4d3a0dc2020-12-02 00:33:42 +0000503 logger.Debugw(ctx, "UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +0000504 "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000505 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
506 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetAddNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000507 }
508 } else {
509 // avoid device reason update as the rule config connected to this flow may still be in progress
510 // and the device reason should only be updated on success of rule config
dbainbri4d3a0dc2020-12-02 00:33:42 +0000511 logger.Debugw(ctx, "UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
mpagenkofc4f56e2020-11-04 17:17:49 +0000512 log.Fields{"device-id": oFsm.deviceID,
513 "NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
514 }
515 }
mpagenko01e726e2020-10-23 09:45:29 +0000516
mpagenkof1fc3862021-02-16 10:09:52 +0000517 if flowCookieModify { // some change was done to the flow entries
mpagenko01e726e2020-10-23 09:45:29 +0000518 //permanently store flow config for reconcile case
mpagenkof1fc3862021-02-16 10:09:52 +0000519 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
520 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000521 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000522 return err
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000523 }
524 }
525 return nil
526}
527
mpagenkof1fc3862021-02-16 10:09:52 +0000528// VOL-3828 flow config sequence workaround ########### start ##########
529func (oFsm *UniVlanConfigFsm) delayNewRuleForCookie(ctx context.Context, aCookieSlice []uint64) uint64 {
530 //assumes mutexFlowParams.Lock() protection from caller!
531 if oFsm.delayNewRuleCookie == 0 && len(aCookieSlice) == 1 {
532 // if not already waiting, limitation for this workaround is to just have one overlapping cookie/rule
533 // suspend check is done only of there is only one cookie in the request
534 // background: more elements only expected in reconcile use case, where no conflicting sequence is to be expected
535 newCookie := aCookieSlice[0]
536 for _, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
537 for _, cookie := range storedUniFlowParams.CookieSlice {
538 if cookie == newCookie {
539 logger.Debugw(ctx, "UniVlanConfigFsm flow setting - new cookie still exists for some rule", log.Fields{
540 "device-id": oFsm.deviceID, "cookie": cookie, "exists with SetVlan": storedUniFlowParams.VlanRuleParams.SetVid})
541 oFsm.delayNewRuleCookie = newCookie
542 return newCookie //found new cookie in some existing rule
543 }
544 } // for all stored cookies of the actual inspected rule
545 } //for all rules
546 }
547 return 0 //no delay requested
548}
549func (oFsm *UniVlanConfigFsm) suspendNewRule(ctx context.Context) {
550 oFsm.mutexFlowParams.RLock()
551 logger.Infow(ctx, "Need to suspend adding this rule as long as the cookie is still connected to some other rule", log.Fields{
552 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
553 oFsm.mutexFlowParams.RUnlock()
554 select {
555 case <-oFsm.chCookieDeleted:
556 logger.Infow(ctx, "resume adding this rule after having deleted cookie in some other rule", log.Fields{
557 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
558 case <-time.After(time.Duration(cWaitForCookieDeletion) * time.Second):
559 logger.Errorw(ctx, "timeout waiting for deletion of cookie in some other rule, just try to continue", log.Fields{
560 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
561 }
562 oFsm.mutexFlowParams.Lock()
563 oFsm.delayNewRuleCookie = 0
564 oFsm.mutexFlowParams.Unlock()
565}
566func (oFsm *UniVlanConfigFsm) suspendIfRequiredNewRule(ctx context.Context, aCookieSlice []uint64) uint64 {
567 oFsm.mutexFlowParams.Lock()
568 delayedCookie := oFsm.delayNewRuleForCookie(ctx, aCookieSlice)
569 oFsm.mutexFlowParams.Unlock()
570
571 if delayedCookie != 0 {
572 oFsm.suspendNewRule(ctx)
573 }
574 return delayedCookie
575}
576
577//returns flowModified, RuleAppendRequest
578func (oFsm *UniVlanConfigFsm) reviseFlowConstellation(ctx context.Context, aCookie uint64, aUniVlanRuleParams uniVlanRuleParams) (bool, bool) {
579 flowEntryMatch := false
580 oFsm.mutexFlowParams.Lock()
581 defer oFsm.mutexFlowParams.Unlock()
582 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
583 if storedUniFlowParams.VlanRuleParams == aUniVlanRuleParams {
584 flowEntryMatch = true
585 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - rule already exists", log.Fields{
586 "device-id": oFsm.deviceID})
587 cookieMatch := false
588 for _, cookie := range storedUniFlowParams.CookieSlice {
589 if cookie == aCookie {
590 logger.Debugw(ctx, "UniVlanConfigFsm flow revise - and cookie already exists", log.Fields{
591 "device-id": oFsm.deviceID, "cookie": cookie})
592 cookieMatch = true
593 break //found new cookie - no further search for this requested cookie
594 }
595 }
596 if !cookieMatch {
597 logger.Debugw(ctx, "UniVlanConfigFsm flow revise -adding new cookie", log.Fields{
598 "device-id": oFsm.deviceID, "cookie": aCookie})
599 //as range works with copies of the slice we have to write to the original slice!!
600 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(oFsm.uniVlanFlowParamsSlice[flow].CookieSlice,
601 aCookie)
602 return true, false //flowModified, NoRuleAppend
603 }
604 break // found rule - no further rule search
605 }
606 }
607 if !flowEntryMatch { //it is a new rule
608 return true, true //flowModified, RuleAppend
609 }
610 return false, false //flowNotModified, NoRuleAppend
611}
612
613// VOL-3828 flow config sequence workaround ########### end ##########
614
mpagenko01e726e2020-10-23 09:45:29 +0000615//RemoveUniFlowParams verifies on existence of flow cookie,
616// if found removes cookie from flow cookie list and if this is empty
617// initiates removal of the flow related configuration from the ONU (via OMCI)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000618func (oFsm *UniVlanConfigFsm) RemoveUniFlowParams(ctx context.Context, aCookie uint64) error {
mpagenkof1fc3862021-02-16 10:09:52 +0000619 var deletedCookie uint64
mpagenko01e726e2020-10-23 09:45:29 +0000620 flowCookieMatch := false
621 //mutex protection is required for possible concurrent access to FSM members
622 oFsm.mutexFlowParams.Lock()
623 defer oFsm.mutexFlowParams.Unlock()
mpagenkof1fc3862021-02-16 10:09:52 +0000624remove_loop:
mpagenko01e726e2020-10-23 09:45:29 +0000625 for flow, storedUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
626 for i, cookie := range storedUniFlowParams.CookieSlice {
627 if cookie == aCookie {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000628 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - cookie found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000629 "device-id": oFsm.deviceID, "cookie": cookie})
630 flowCookieMatch = true
mpagenkof1fc3862021-02-16 10:09:52 +0000631 deletedCookie = aCookie
632 kvStoreWrite := false //default setting is to not write to kvStore immediately - will be done on FSM execution finally
mpagenko01e726e2020-10-23 09:45:29 +0000633 //remove the cookie from the cookie slice and verify it is getting empty
634 if len(storedUniFlowParams.CookieSlice) == 1 {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000635 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - full flow removal", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000636 "device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +0000637
638 //create a new element for the removeVlanFlow slice
639 loRemoveParams := uniRemoveVlanFlowParams{
640 vlanRuleParams: storedUniFlowParams.VlanRuleParams,
mpagenkof1fc3862021-02-16 10:09:52 +0000641 cookie: aCookie,
mpagenko01e726e2020-10-23 09:45:29 +0000642 }
643 oFsm.uniRemoveFlowsSlice = append(oFsm.uniRemoveFlowsSlice, loRemoveParams)
644
645 //and remove the actual element from the addVlanFlow slice
646 // oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = nil //automatically done by garbage collector
647 if len(oFsm.uniVlanFlowParamsSlice) <= 1 {
648 oFsm.numUniFlows = 0 //no more flows
649 oFsm.configuredUniFlow = 0 //no more flows configured
650 oFsm.uniVlanFlowParamsSlice = nil //reset the slice
mpagenko2418ab02020-11-12 12:58:06 +0000651 //at this point it is evident that no flow anymore refers to a still possibly active Techprofile
652 //request that this profile gets deleted before a new flow add is allowed
mpagenko551a4d42020-12-08 18:09:20 +0000653 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, loRemoveParams.vlanRuleParams.TpID, true)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000654 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - no more flows", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000655 "device-id": oFsm.deviceID})
656 } else {
657 oFsm.numUniFlows--
658 if oFsm.configuredUniFlow > 0 {
659 oFsm.configuredUniFlow--
660 //TODO!! might be needed to consider still outstanding configure requests ..
661 // so a flow at removal might still not be configured !?!
662 }
mpagenko2418ab02020-11-12 12:58:06 +0000663 usedTpID := storedUniFlowParams.VlanRuleParams.TpID
mpagenko01e726e2020-10-23 09:45:29 +0000664 //cut off the requested flow by slicing out this element
665 oFsm.uniVlanFlowParamsSlice = append(
666 oFsm.uniVlanFlowParamsSlice[:flow], oFsm.uniVlanFlowParamsSlice[flow+1:]...)
mpagenko2418ab02020-11-12 12:58:06 +0000667 //here we have to check, if there are still other flows referencing to the actual ProfileId
668 // before we can request that this profile gets deleted before a new flow add is allowed
mpagenkof1fc3862021-02-16 10:09:52 +0000669 // (needed to extract to function due to lint complexity)
670 oFsm.updateTechProfileToDelete(ctx, usedTpID)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000671 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow removed from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000672 "device-id": oFsm.deviceID})
673 }
674 //trigger the FSM to remove the relevant rule
675 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
676 if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
mpagenko9a304ea2020-12-16 15:54:01 +0000677 logger.Debugw(ctx, "UniVlanConfigFsm rule removal request", log.Fields{
678 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
679 "tp-id": loRemoveParams.vlanRuleParams.TpID,
680 "set-Vlan": loRemoveParams.vlanRuleParams.SetVid})
mpagenko01e726e2020-10-23 09:45:29 +0000681 //have to re-trigger the FSM to proceed with outstanding incremental flow configuration
mpagenko9a304ea2020-12-16 15:54:01 +0000682 // Can't call FSM Event directly, decoupling it
mpagenko01e726e2020-10-23 09:45:29 +0000683 go func(a_pBaseFsm *fsm.FSM) {
684 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
685 }(pConfigVlanStateBaseFsm)
686 } // if not in the appropriate state a new entry will be automatically considered later
687 // when the configDone state is reached
688 } else {
mpagenko01e726e2020-10-23 09:45:29 +0000689 //cut off the requested cookie by slicing out this element
690 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
691 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
692 oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
mpagenkofc4f56e2020-11-04 17:17:49 +0000693 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
mpagenkof1fc3862021-02-16 10:09:52 +0000694 kvStoreWrite = true // ensure actual data write to kvStore immediately (no FSM activity)
mpagenkofc4f56e2020-11-04 17:17:49 +0000695 // state transition notification is checked in deviceHandler
696 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000697 // success indication without the need to write to kvStore (done already below with updated data from storePersUniFlowConfig())
698 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000699 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000700 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - rule persists with still valid cookies", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000701 "device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
mpagenkof1fc3862021-02-16 10:09:52 +0000702 if deletedCookie == oFsm.delayNewRuleCookie {
703 //the delayedNewCookie is the one that is currently deleted, but the rule still exist with other cookies
704 //as long as there are further cookies for this rule indicate there is still some cookie to be deleted
705 //simply use the first one
706 oFsm.delayNewRuleCookie = oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[0]
707 logger.Debugw(ctx, "UniVlanConfigFsm remaining cookie awaited for deletion before new rule add", log.Fields{
708 "device-id": oFsm.deviceID, "cookie": oFsm.delayNewRuleCookie})
709 }
mpagenko01e726e2020-10-23 09:45:29 +0000710 }
mpagenko01e726e2020-10-23 09:45:29 +0000711 //permanently store the modified flow config for reconcile case
mpagenkofc4f56e2020-11-04 17:17:49 +0000712 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000713 if err := oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID,
714 &oFsm.uniVlanFlowParamsSlice, kvStoreWrite); err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000715 logger.Errorw(ctx, err.Error(), log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +0000716 return err
717 }
mpagenko01e726e2020-10-23 09:45:29 +0000718 }
mpagenkof1fc3862021-02-16 10:09:52 +0000719 break remove_loop //found the cookie - no further search for this requested cookie
mpagenko01e726e2020-10-23 09:45:29 +0000720 }
721 }
mpagenko01e726e2020-10-23 09:45:29 +0000722 } //search all flows
723 if !flowCookieMatch { //some cookie remove-request for a cookie that does not exist in the FSM data
dbainbri4d3a0dc2020-12-02 00:33:42 +0000724 logger.Warnw(ctx, "UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000725 "device-id": oFsm.deviceID, "remove-cookie": aCookie})
726 // but accept the request with success as no such cookie (flow) does exist
mpagenkofc4f56e2020-11-04 17:17:49 +0000727 // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
728 // state transition notification is checked in deviceHandler
729 if oFsm.pDeviceHandler != nil {
mpagenkof1fc3862021-02-16 10:09:52 +0000730 // success indication without the need to write to kvStore (no change)
731 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(oFsm.requestEvent+cDeviceEventOffsetRemoveNoKvStore))
mpagenkofc4f56e2020-11-04 17:17:49 +0000732 }
mpagenko01e726e2020-10-23 09:45:29 +0000733 return nil
734 } //unknown cookie
735
736 return nil
737}
738
mpagenkof1fc3862021-02-16 10:09:52 +0000739func (oFsm *UniVlanConfigFsm) updateTechProfileToDelete(ctx context.Context, usedTpID uint8) {
740 //here we have to check, if there are still other flows referencing to the actual ProfileId
741 // before we can request that this profile gets deleted before a new flow add is allowed
742 tpIDInOtherFlows := false
743 for _, tpUniFlowParams := range oFsm.uniVlanFlowParamsSlice {
744 if tpUniFlowParams.VlanRuleParams.TpID == usedTpID {
745 tpIDInOtherFlows = true
746 break // search loop can be left
747 }
748 }
749 if tpIDInOtherFlows {
750 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is still used in other flows", log.Fields{
751 "device-id": oFsm.deviceID, "tp-id": usedTpID})
752 } else {
753 logger.Debugw(ctx, "UniVlanConfigFsm tp-id used in deleted flow is not used anymore", log.Fields{
754 "device-id": oFsm.deviceID, "tp-id": usedTpID})
755 //request that this profile gets deleted before a new flow add is allowed
756 oFsm.pUniTechProf.setProfileToDelete(oFsm.pOnuUniPort.uniID, usedTpID, true)
757 }
758}
759
dbainbri4d3a0dc2020-12-02 00:33:42 +0000760func (oFsm *UniVlanConfigFsm) enterConfigStarting(ctx context.Context, e *fsm.Event) {
761 logger.Debugw(ctx, "UniVlanConfigFsm start", log.Fields{"in state": e.FSM.Current(),
mpagenko01e726e2020-10-23 09:45:29 +0000762 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000763
764 // this FSM is not intended for re-start, needs always new creation for a new run
mpagenko01e726e2020-10-23 09:45:29 +0000765 // (self-destroying - compare enterDisabled())
mpagenkodff5dda2020-08-28 11:52:01 +0000766 oFsm.omciMIdsResponseReceived = make(chan bool)
mpagenkof1fc3862021-02-16 10:09:52 +0000767 oFsm.chCookieDeleted = make(chan bool)
mpagenkodff5dda2020-08-28 11:52:01 +0000768 // start go routine for processing of LockState messages
dbainbri4d3a0dc2020-12-02 00:33:42 +0000769 go oFsm.processOmciVlanMessages(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +0000770 //let the state machine run forward from here directly
771 pConfigVlanStateAFsm := oFsm.pAdaptFsm
772 if pConfigVlanStateAFsm != nil {
mpagenko551a4d42020-12-08 18:09:20 +0000773 oFsm.mutexFlowParams.Lock()
mpagenko9a304ea2020-12-16 15:54:01 +0000774
775 //possibly the entry is not valid anymore based on intermediate delete requests
776 //just a basic protection ...
777 if len(oFsm.uniVlanFlowParamsSlice) == 0 {
778 oFsm.mutexFlowParams.Unlock()
779 logger.Debugw(ctx, "UniVlanConfigFsm start: no rule entry anymore available", log.Fields{
780 "device-id": oFsm.deviceID})
781 // Can't call FSM Event directly, decoupling it
782 go func(a_pAFsm *AdapterFsm) {
783 _ = a_pAFsm.pFsm.Event(vlanEvReset)
784 }(pConfigVlanStateAFsm)
785 return
786 }
787
788 //access to uniVlanFlowParamsSlice is done on first element only here per definition
789 //store the actual rule that shall be worked upon in the following transient states
790 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000791 oFsm.mutexFlowParams.Unlock()
mpagenko9a304ea2020-12-16 15:54:01 +0000792 tpID := oFsm.actualUniVlanConfigRule.TpID
793 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000794 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID))
mpagenko9a304ea2020-12-16 15:54:01 +0000795 logger.Debugw(ctx, "UniVlanConfigFsm - start with first rule", log.Fields{
796 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
797 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
mpagenko551a4d42020-12-08 18:09:20 +0000798 //cmp also usage in EVTOCDE create in omci_cc
799 oFsm.evtocdID = macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
mpagenko9a304ea2020-12-16 15:54:01 +0000800 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000801 go func(aPAFsm *AdapterFsm, aTechProfDone bool) {
802 if aPAFsm != nil && aPAFsm.pFsm != nil {
803 if aTechProfDone {
mpagenkodff5dda2020-08-28 11:52:01 +0000804 // let the vlan processing begin
mpagenko551a4d42020-12-08 18:09:20 +0000805 _ = aPAFsm.pFsm.Event(vlanEvStartConfig)
mpagenkodff5dda2020-08-28 11:52:01 +0000806 } else {
807 // set to waiting for Techprofile
mpagenko551a4d42020-12-08 18:09:20 +0000808 _ = aPAFsm.pFsm.Event(vlanEvWaitTechProf)
mpagenkodff5dda2020-08-28 11:52:01 +0000809 }
810 }
mpagenko551a4d42020-12-08 18:09:20 +0000811 }(pConfigVlanStateAFsm, loTechProfDone)
812 } else {
813 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
814 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
815 //should never happen, else: recovery would be needed from outside the FSM
816 return
mpagenkodff5dda2020-08-28 11:52:01 +0000817 }
818}
819
dbainbri4d3a0dc2020-12-02 00:33:42 +0000820func (oFsm *UniVlanConfigFsm) enterConfigVtfd(ctx context.Context, e *fsm.Event) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000821 //mutex protection is required for possible concurrent access to FSM members
822 oFsm.mutexFlowParams.Lock()
mpagenko551a4d42020-12-08 18:09:20 +0000823 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
mpagenko9a304ea2020-12-16 15:54:01 +0000824 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +0000825 // meaning transparent setup - no specific VTFD setting required
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000826 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000827 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000828 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +0000829 // let the FSM proceed ... (from within this state all internal pointers may be expected to be correct)
mpagenkodff5dda2020-08-28 11:52:01 +0000830 pConfigVlanStateAFsm := oFsm.pAdaptFsm
mpagenko9a304ea2020-12-16 15:54:01 +0000831 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +0000832 go func(a_pAFsm *AdapterFsm) {
Himani Chawla4d908332020-08-31 12:30:20 +0530833 _ = a_pAFsm.pFsm.Event(vlanEvRxConfigVtfd)
mpagenkodff5dda2020-08-28 11:52:01 +0000834 }(pConfigVlanStateAFsm)
835 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300836 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
837 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +0000838 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
dbainbri4d3a0dc2020-12-02 00:33:42 +0000839 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300840 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000841 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
842 // setVid is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +0000843 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000844 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000845 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000846 vtfdFilterList[0] = oFsm.vlanFilterList[0]
847 oFsm.numVlanFilterEntries = 1
mpagenkodff5dda2020-08-28 11:52:01 +0000848 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300849 EntityID: vtfdID,
mpagenkodff5dda2020-08-28 11:52:01 +0000850 Attributes: me.AttributeValueMap{
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000851 "VlanFilterList": vtfdFilterList, //omci lib wants a slice for serialization
852 "ForwardOperation": uint8(0x10), //VID investigation
853 "NumberOfEntries": oFsm.numVlanFilterEntries,
mpagenkodff5dda2020-08-28 11:52:01 +0000854 },
855 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000856 logger.Debugw(ctx, "UniVlanConfigFsm sendcreate VTFD", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000857 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000858 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +0000859 oFsm.pAdaptFsm.commChan, meParams)
860 //accept also nil as (error) return value for writing to LastTx
861 // - this avoids misinterpretation of new received OMCI messages
862 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
863 // send shall return (dual format) error code that can be used here for immediate error treatment
864 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +0000865 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +0000866 }
867}
868
dbainbri4d3a0dc2020-12-02 00:33:42 +0000869func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(ctx context.Context, e *fsm.Event) {
870 logger.Debugw(ctx, "UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000871 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkof1fc3862021-02-16 10:09:52 +0000872 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300873 go func() {
mpagenko9a304ea2020-12-16 15:54:01 +0000874 //using the first element in the slice because it's the first flow per definition here
875 errEvto := oFsm.performConfigEvtocdEntries(ctx, 0)
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300876 //This is correct passing scenario
877 if errEvto == nil {
mpagenko9a304ea2020-12-16 15:54:01 +0000878 tpID := oFsm.actualUniVlanConfigRule.TpID
879 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +0000880 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
881 logger.Infow(ctx, "Setting multicast MEs, with first flow", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300882 "techProfile": tpID, "gemPort": gemPort, "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
dbainbri4d3a0dc2020-12-02 00:33:42 +0000883 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort,
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300884 vlanID)
885 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000886 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300887 log.Fields{"device-id": oFsm.deviceID})
888 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
889 }
890 }
891 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
892 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
893 }
894 }()
mpagenkodff5dda2020-08-28 11:52:01 +0000895}
896
dbainbri4d3a0dc2020-12-02 00:33:42 +0000897func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(ctx context.Context, e *fsm.Event) {
mpagenko9a304ea2020-12-16 15:54:01 +0000898 oFsm.mutexFlowParams.RLock()
899 defer oFsm.mutexFlowParams.RUnlock()
900
mpagenkof1fc3862021-02-16 10:09:52 +0000901 logger.Infow(ctx, "UniVlanConfigFsm config done - checking on more flows", log.Fields{
mpagenko551a4d42020-12-08 18:09:20 +0000902 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
903 "overall-uni-rules": oFsm.numUniFlows, "configured-uni-rules": oFsm.configuredUniFlow})
904 pConfigVlanStateAFsm := oFsm.pAdaptFsm
905 if pConfigVlanStateAFsm == nil {
mpagenko551a4d42020-12-08 18:09:20 +0000906 logger.Errorw(ctx, "UniVlanConfigFsm abort: invalid FSM pointer", log.Fields{
907 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
908 //should never happen, else: recovery would be needed from outside the FSM
909 return
910 }
911 pConfigVlanStateBaseFsm := pConfigVlanStateAFsm.pFsm
mpagenko01e726e2020-10-23 09:45:29 +0000912 if len(oFsm.uniRemoveFlowsSlice) > 0 {
913 //some further flows are to be removed, removal always starts with the first element
mpagenko9a304ea2020-12-16 15:54:01 +0000914 logger.Debugw(ctx, "UniVlanConfigFsm rule removal from ConfigDone", log.Fields{
915 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
916 "tp-id": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.TpID,
917 "set-Vlan": oFsm.uniRemoveFlowsSlice[0].vlanRuleParams.SetVid})
918 // Can't call FSM Event directly, decoupling it
mpagenko01e726e2020-10-23 09:45:29 +0000919 go func(a_pBaseFsm *fsm.FSM) {
920 _ = a_pBaseFsm.Event(vlanEvRemFlowConfig)
921 }(pConfigVlanStateBaseFsm)
922 return
923 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000924 if oFsm.numUniFlows > oFsm.configuredUniFlow {
mpagenko551a4d42020-12-08 18:09:20 +0000925 if oFsm.configuredUniFlow == 0 {
mpagenko551a4d42020-12-08 18:09:20 +0000926 // this is a restart with a complete new flow, we can re-use the initial flow config control
927 // including the check, if the related techProfile is (still) available (probably also removed in between)
mpagenko9a304ea2020-12-16 15:54:01 +0000928 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000929 go func(a_pBaseFsm *fsm.FSM) {
930 _ = a_pBaseFsm.Event(vlanEvRenew)
931 }(pConfigVlanStateBaseFsm)
932 return
933 }
934
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000935 //some further flows are to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000936 //store the actual rule that shall be worked upon in the following transient states
937 oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +0000938 //tpId of the next rule to be configured
mpagenko9a304ea2020-12-16 15:54:01 +0000939 tpID := oFsm.actualUniVlanConfigRule.TpID
mpagenko551a4d42020-12-08 18:09:20 +0000940 oFsm.TpIDWaitingFor = tpID
mpagenko551a4d42020-12-08 18:09:20 +0000941 loTechProfDone := oFsm.pUniTechProf.getTechProfileDone(ctx, oFsm.pOnuUniPort.uniID, tpID)
mpagenko9a304ea2020-12-16 15:54:01 +0000942 logger.Debugw(ctx, "UniVlanConfigFsm - incremental config request", log.Fields{
943 "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
944 "set-Vlan": oFsm.actualUniVlanConfigRule.SetVid, "tp-id": tpID, "ProfDone": loTechProfDone})
945 // Can't call FSM Event directly, decoupling it
mpagenko551a4d42020-12-08 18:09:20 +0000946 go func(aPBaseFsm *fsm.FSM, aTechProfDone bool) {
947 if aTechProfDone {
948 // let the vlan processing continue with next rule
949 _ = aPBaseFsm.Event(vlanEvIncrFlowConfig)
950 } else {
951 // set to waiting for Techprofile
952 _ = aPBaseFsm.Event(vlanEvWaitTPIncr)
953 }
954 }(pConfigVlanStateBaseFsm, loTechProfDone)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000955 return
956 }
dbainbri4d3a0dc2020-12-02 00:33:42 +0000957 logger.Debugw(ctx, "UniVlanConfigFsm - VLAN config done: send dh event notification", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000958 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000959 // it might appear that some flows are requested also after 'flowPushed' event has been generated ...
960 // state transition notification is checked in deviceHandler
mpagenko551a4d42020-12-08 18:09:20 +0000961 // note: 'flowPushed' event is only generated if all 'pending' rules are configured
mpagenkodff5dda2020-08-28 11:52:01 +0000962 if oFsm.pDeviceHandler != nil {
mpagenkofc4f56e2020-11-04 17:17:49 +0000963 //making use of the add->remove successor enum assumption/definition
dbainbri4d3a0dc2020-12-02 00:33:42 +0000964 go oFsm.pDeviceHandler.deviceProcStatusUpdate(ctx, OnuDeviceEvent(uint8(oFsm.requestEvent)+oFsm.requestEventOffset))
mpagenkodff5dda2020-08-28 11:52:01 +0000965 }
966}
967
dbainbri4d3a0dc2020-12-02 00:33:42 +0000968func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(ctx context.Context, e *fsm.Event) {
969 logger.Debugw(ctx, "UniVlanConfigFsm - start config further incremental flow", log.Fields{
Girish Gowdra041dcb32020-11-16 16:54:30 -0800970 "in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
mpagenko01e726e2020-10-23 09:45:29 +0000971 "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000972 oFsm.mutexFlowParams.Lock()
mpagenko551a4d42020-12-08 18:09:20 +0000973 oFsm.TpIDWaitingFor = 0 //reset indication to avoid misinterpretation
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000974
mpagenko9a304ea2020-12-16 15:54:01 +0000975 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000976 // meaning transparent setup - no specific VTFD setting required
977 oFsm.mutexFlowParams.Unlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +0000978 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD config required", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +0000979 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000980 } else {
981 if oFsm.numVlanFilterEntries == 0 {
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300982 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
983 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
mpagenko9a304ea2020-12-16 15:54:01 +0000984 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(oFsm.actualUniVlanConfigRule.TpID)
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000985 //no VTFD yet created
dbainbri4d3a0dc2020-12-02 00:33:42 +0000986 logger.Debugw(ctx, "UniVlanConfigFsm create VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300987 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +0000988 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300989 // 'SetVid' below is assumed to be masked already by the caller to 12 bit
mpagenko9a304ea2020-12-16 15:54:01 +0000990 oFsm.vlanFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300991
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000992 oFsm.mutexFlowParams.Unlock()
mpagenko01e726e2020-10-23 09:45:29 +0000993 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000994 vtfdFilterList[0] = oFsm.vlanFilterList[0]
995 oFsm.numVlanFilterEntries = 1
996 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +0300997 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +0000998 Attributes: me.AttributeValueMap{
999 "VlanFilterList": vtfdFilterList,
1000 "ForwardOperation": uint8(0x10), //VID investigation
1001 "NumberOfEntries": oFsm.numVlanFilterEntries,
1002 },
1003 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001004 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001005 oFsm.pAdaptFsm.commChan, meParams)
1006 //accept also nil as (error) return value for writing to LastTx
1007 // - this avoids misinterpretation of new received OMCI messages
1008 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1009 // send shall return (dual format) error code that can be used here for immediate error treatment
1010 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001011 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001012 } else {
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.
mpagenko551a4d42020-12-08 18:09:20 +00001015 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID +
mpagenko9a304ea2020-12-16 15:54:01 +00001016 uint16(oFsm.actualUniVlanConfigRule.TpID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001017
dbainbri4d3a0dc2020-12-02 00:33:42 +00001018 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001019 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001020 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001021 // setVid is assumed to be masked already by the caller to 12 bit
1022 oFsm.vlanFilterList[oFsm.numVlanFilterEntries] =
mpagenko9a304ea2020-12-16 15:54:01 +00001023 uint16(oFsm.actualUniVlanConfigRule.SetVid)
mpagenko01e726e2020-10-23 09:45:29 +00001024 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001025
1026 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
1027 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
1028 // new vlan associated with a different TP.
mpagenko9a304ea2020-12-16 15:54:01 +00001029 vtfdFilterList[0] = uint16(oFsm.actualUniVlanConfigRule.SetVid)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001030 oFsm.mutexFlowParams.Unlock()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001031
1032 oFsm.numVlanFilterEntries++
1033 meParams := me.ParamData{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001034 EntityID: vtfdID,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001035 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001036 "VlanFilterList": vtfdFilterList,
1037 "ForwardOperation": uint8(0x10), //VID investigation
1038 "NumberOfEntries": oFsm.numVlanFilterEntries,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001039 },
1040 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001041 meInstance := oFsm.pOmciCC.sendCreateVtfdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001042 oFsm.pAdaptFsm.commChan, meParams)
1043 //accept also nil as (error) return value for writing to LastTx
1044 // - this avoids misinterpretation of new received OMCI messages
1045 //TODO!!: refactoring improvement requested, here as an example for [VOL-3457]:
1046 // send shall return (dual format) error code that can be used here for immediate error treatment
1047 // (relevant to all used sendXX() methods in this (and other) FSM's)
mpagenko01e726e2020-10-23 09:45:29 +00001048 oFsm.pLastTxMeInstance = meInstance
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001049 }
1050 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001051 err := oFsm.waitforOmciResponse(ctx)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001052 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001053 logger.Errorw(ctx, "VTFD create/set failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001054 log.Fields{"device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001055 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
mpagenko9a304ea2020-12-16 15:54:01 +00001056 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001057 go func(a_pBaseFsm *fsm.FSM) {
1058 _ = a_pBaseFsm.Event(vlanEvReset)
1059 }(pConfigVlanStateBaseFsm)
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001060 return
1061 }
1062 }
mpagenkof1fc3862021-02-16 10:09:52 +00001063 oFsm.requestEventOffset = uint8(cDeviceEventOffsetAddWithKvStore) //0 offset for last flow-add activity
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001064 go func() {
mpagenko9a304ea2020-12-16 15:54:01 +00001065 tpID := oFsm.actualUniVlanConfigRule.TpID
dbainbri4d3a0dc2020-12-02 00:33:42 +00001066 errEvto := oFsm.performConfigEvtocdEntries(ctx, oFsm.configuredUniFlow)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001067 //This is correct passing scenario
1068 if errEvto == nil {
1069 //TODO Possibly insert new state for multicast --> possibly another jira/later time.
dbainbri4d3a0dc2020-12-02 00:33:42 +00001070 for _, gemPort := range oFsm.pUniTechProf.getMulticastGemPorts(ctx, oFsm.pOnuUniPort.uniID, uint8(tpID)) {
mpagenko9a304ea2020-12-16 15:54:01 +00001071 vlanID := oFsm.actualUniVlanConfigRule.SetVid
dbainbri4d3a0dc2020-12-02 00:33:42 +00001072 logger.Infow(ctx, "Setting multicast MEs for additional flows", log.Fields{"deviceID": oFsm.deviceID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001073 "techProfile": tpID, "gemPort": gemPort,
1074 "vlanID": vlanID, "configuredUniFlow": oFsm.configuredUniFlow})
dbainbri4d3a0dc2020-12-02 00:33:42 +00001075 errCreateAllMulticastME := oFsm.performSettingMulticastME(ctx, tpID, gemPort, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001076 if errCreateAllMulticastME != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001077 logger.Errorw(ctx, "Multicast ME create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001078 log.Fields{"device-id": oFsm.deviceID})
1079 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1080 }
1081 }
1082 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
1083 }
1084 }()
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001085}
1086
dbainbri4d3a0dc2020-12-02 00:33:42 +00001087func (oFsm *UniVlanConfigFsm) enterRemoveFlow(ctx context.Context, e *fsm.Event) {
mpagenko551a4d42020-12-08 18:09:20 +00001088 oFsm.mutexFlowParams.RLock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001089 logger.Debugw(ctx, "UniVlanConfigFsm - start removing the top remove-flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001090 "in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
1091 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001092
mpagenkofc4f56e2020-11-04 17:17:49 +00001093 pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
1094 loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
mpagenko01e726e2020-10-23 09:45:29 +00001095 loVlanEntryClear := uint8(0)
1096 loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
1097 //shallow copy is sufficient as no reference variables are used within struct
1098 loRuleParams := oFsm.uniRemoveFlowsSlice[0].vlanRuleParams
mpagenko551a4d42020-12-08 18:09:20 +00001099 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001100 logger.Debugw(ctx, "UniVlanConfigFsm - remove-flow parameters are", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001101 "match vid": loRuleParams.MatchVid, "match Pcp": loRuleParams.MatchPcp,
1102 "set vid": strconv.FormatInt(int64(loRuleParams.SetVid), 16),
1103 "device-id": oFsm.deviceID})
1104
1105 if loRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1106 // meaning transparent setup - no specific VTFD setting required
dbainbri4d3a0dc2020-12-02 00:33:42 +00001107 logger.Debugw(ctx, "UniVlanConfigFsm: no VTFD removal required for transparent flow", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001108 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
1109 } else {
1110 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization and 're-copy'
1111 if oFsm.numVlanFilterEntries == 1 {
mpagenko551a4d42020-12-08 18:09:20 +00001112 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001113 //only one active VLAN entry (hopefully the SetVID we want to remove - should be, but not verified ..)
1114 // so we can just delete the VTFD entry
dbainbri4d3a0dc2020-12-02 00:33:42 +00001115 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD delete (no more vlan filters)",
mpagenko01e726e2020-10-23 09:45:29 +00001116 log.Fields{"current vlan list": oFsm.vlanFilterList,
1117 "in state": e.FSM.Current(), "device-id": oFsm.deviceID})
mpagenkofc4f56e2020-11-04 17:17:49 +00001118 loVlanEntryClear = 1 //full VlanFilter clear request
1119 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001120 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001121 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001122 oFsm.pLastTxMeInstance = meInstance
1123 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001124 logger.Debugw(ctx, "UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001125 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenkofc4f56e2020-11-04 17:17:49 +00001126 }
mpagenko01e726e2020-10-23 09:45:29 +00001127 } else {
1128 //many VTFD already should exists - find and remove the one concerned by the actual remove rule
1129 // by updating the VTFD per set command with new valid list
dbainbri4d3a0dc2020-12-02 00:33:42 +00001130 logger.Debugw(ctx, "UniVlanConfigFsm: VTFD removal of requested VLAN from the list on OMCI",
mpagenko01e726e2020-10-23 09:45:29 +00001131 log.Fields{"current vlan list": oFsm.vlanFilterList,
1132 "set-vlan": loRuleParams.SetVid, "device-id": oFsm.deviceID})
1133 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1134 if loRuleParams.SetVid == uint32(oFsm.vlanFilterList[i]) {
1135 loVlanEntryRmPos = i
1136 break //abort search
1137 }
1138 }
1139 if loVlanEntryRmPos < cVtfdTableSize {
mpagenko551a4d42020-12-08 18:09:20 +00001140 vtfdID := macBridgePortAniEID + oFsm.pOnuUniPort.entityID + uint16(loRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00001141 //valid entry was found - to be eclipsed
1142 loVlanEntryClear = 2 //VlanFilter remove request for a specific entry
1143 for i := uint8(0); i < oFsm.numVlanFilterEntries; i++ {
1144 if i < loVlanEntryRmPos {
1145 vtfdFilterList[i] = oFsm.vlanFilterList[i] //copy original
1146 } else if i < (cVtfdTableSize - 1) {
1147 vtfdFilterList[i] = oFsm.vlanFilterList[i+1] //copy successor (including 0 elements)
1148 } else {
1149 vtfdFilterList[i] = 0 //set last byte if needed
1150 }
1151 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001152 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001153 "EntitytId": strconv.FormatInt(int64(vtfdID), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001154 "new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
1155
mpagenkofc4f56e2020-11-04 17:17:49 +00001156 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001157 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
dbainbri4d3a0dc2020-12-02 00:33:42 +00001158 meInstance := oFsm.pOmciCC.sendDeleteVtfd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001159 oFsm.pAdaptFsm.commChan, vtfdID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001160 oFsm.pLastTxMeInstance = meInstance
1161 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001162 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
Holger Hildebrandt3a644642020-12-02 09:46:18 +00001163 "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
mpagenko01e726e2020-10-23 09:45:29 +00001164 }
mpagenko01e726e2020-10-23 09:45:29 +00001165 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001166 logger.Warnw(ctx, "UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
mpagenko01e726e2020-10-23 09:45:29 +00001167 log.Fields{"device-id": oFsm.deviceID})
1168 }
1169 }
1170 if loVlanEntryClear > 0 {
mpagenkofc4f56e2020-11-04 17:17:49 +00001171 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
1172 //waiting on response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001173 err := oFsm.waitforOmciResponse(ctx)
mpagenkofc4f56e2020-11-04 17:17:49 +00001174 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001175 logger.Errorw(ctx, "VTFD delete/reset failed, aborting VlanConfig FSM!",
mpagenkofc4f56e2020-11-04 17:17:49 +00001176 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001177 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001178 go func(a_pBaseFsm *fsm.FSM) {
1179 _ = a_pBaseFsm.Event(vlanEvReset)
1180 }(pConfigVlanStateBaseFsm)
1181 return
1182 }
mpagenko01e726e2020-10-23 09:45:29 +00001183 }
1184
1185 if loVlanEntryClear == 1 {
1186 oFsm.vlanFilterList[0] = 0 //first entry is the only that can contain the previous only-one element
1187 oFsm.numVlanFilterEntries = 0
1188 } else if loVlanEntryClear == 2 {
1189 // new VlanFilterList should be one entry smaller now - copy from last configured entry
1190 // this loop now includes the 0 element on previous last valid entry
1191 for i := uint8(0); i <= oFsm.numVlanFilterEntries; i++ {
1192 oFsm.vlanFilterList[i] = vtfdFilterList[i]
1193 }
1194 oFsm.numVlanFilterEntries--
1195 }
1196 }
1197 }
1198
mpagenkofc4f56e2020-11-04 17:17:49 +00001199 if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
dbainbri4d3a0dc2020-12-02 00:33:42 +00001200 go oFsm.removeEvtocdEntries(ctx, loRuleParams)
mpagenkofc4f56e2020-11-04 17:17:49 +00001201 } else {
1202 // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
dbainbri4d3a0dc2020-12-02 00:33:42 +00001203 logger.Debugw(ctx, "UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
mpagenkofc4f56e2020-11-04 17:17:49 +00001204 "device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00001205 // Can't call FSM Event directly, decoupling it
mpagenkofc4f56e2020-11-04 17:17:49 +00001206 go func(a_pBaseFsm *fsm.FSM) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001207 _ = a_pBaseFsm.Event(vlanEvRemFlowDone, loRuleParams.TpID)
mpagenkofc4f56e2020-11-04 17:17:49 +00001208 }(pConfigVlanStateBaseFsm)
1209 }
mpagenkodff5dda2020-08-28 11:52:01 +00001210}
1211
dbainbri4d3a0dc2020-12-02 00:33:42 +00001212func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(ctx context.Context, e *fsm.Event) {
Girish Gowdra26a40922021-01-29 17:14:34 -08001213 var tpID uint8
1214 // Extract the tpID
1215 if len(e.Args) > 0 {
1216 tpID = e.Args[0].(uint8)
1217 logger.Debugw(ctx, "UniVlanConfigFsm - flow removed for tp id", log.Fields{"device-id": oFsm.deviceID, "tpID": e.Args[0].(uint8)})
1218 } else {
1219 logger.Warnw(ctx, "UniVlanConfigFsm - tp id not available", log.Fields{"device-id": oFsm.deviceID})
1220 }
mpagenko01e726e2020-10-23 09:45:29 +00001221 oFsm.mutexFlowParams.Lock()
mpagenkof1fc3862021-02-16 10:09:52 +00001222 deletedCookie := oFsm.uniRemoveFlowsSlice[0].cookie
1223 logger.Debugw(ctx, "UniVlanConfigFsm - removing the removal data", log.Fields{
1224 "in state": e.FSM.Current(), "device-id": oFsm.deviceID,
1225 "removed cookie": deletedCookie, "waitForDeleteCookie": oFsm.delayNewRuleCookie})
1226
mpagenko01e726e2020-10-23 09:45:29 +00001227 if len(oFsm.uniRemoveFlowsSlice) <= 1 {
1228 oFsm.uniRemoveFlowsSlice = nil //reset the slice
dbainbri4d3a0dc2020-12-02 00:33:42 +00001229 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - last remove-flow deleted", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001230 "device-id": oFsm.deviceID})
1231 } else {
1232 //cut off the actual flow by slicing out the first element
1233 oFsm.uniRemoveFlowsSlice = append(
1234 oFsm.uniRemoveFlowsSlice[:0],
1235 oFsm.uniRemoveFlowsSlice[1:]...)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001236 logger.Debugw(ctx, "UniVlanConfigFsm flow removal - specific flow deleted from data", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001237 "device-id": oFsm.deviceID})
1238 }
1239 oFsm.mutexFlowParams.Unlock()
1240
mpagenkof1fc3862021-02-16 10:09:52 +00001241 oFsm.requestEventOffset = uint8(cDeviceEventOffsetRemoveWithKvStore) //offset for last flow-remove activity (with kvStore request)
mpagenko01e726e2020-10-23 09:45:29 +00001242 //return to the basic config verification state
mpagenkodff5dda2020-08-28 11:52:01 +00001243 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1244 if pConfigVlanStateAFsm != nil {
mpagenko9a304ea2020-12-16 15:54:01 +00001245 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001246 go func(a_pAFsm *AdapterFsm) {
1247 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
mpagenko01e726e2020-10-23 09:45:29 +00001248 _ = a_pAFsm.pFsm.Event(vlanEvFlowDataRemoved)
mpagenkodff5dda2020-08-28 11:52:01 +00001249 }
1250 }(pConfigVlanStateAFsm)
1251 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001252
1253 oFsm.mutexFlowParams.RLock()
1254 noOfFlowRem := len(oFsm.uniRemoveFlowsSlice)
mpagenkof1fc3862021-02-16 10:09:52 +00001255 if deletedCookie == oFsm.delayNewRuleCookie {
1256 // flush the channel CookieDeleted to ensure it is not lingering from some previous (aborted) activity
1257 select {
1258 case <-oFsm.chCookieDeleted:
1259 logger.Debug(ctx, "flushed CookieDeleted")
1260 default:
1261 }
1262 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue
1263 }
Girish Gowdra26a40922021-01-29 17:14:34 -08001264 oFsm.mutexFlowParams.RUnlock()
1265 // If all pending flow removes are completed and TP ID is valid, processing any pending TP delete
1266 if noOfFlowRem == 0 && tpID > 0 {
1267 logger.Debugw(ctx, "processing pending tp delete", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID})
1268 // If we are here then all flows are removed.
1269 oFsm.pDeviceHandler.ProcessPendingTpDelete(ctx, oFsm.pOnuUniPort, tpID)
1270 }
mpagenkodff5dda2020-08-28 11:52:01 +00001271}
1272
dbainbri4d3a0dc2020-12-02 00:33:42 +00001273func (oFsm *UniVlanConfigFsm) enterResetting(ctx context.Context, e *fsm.Event) {
1274 logger.Debugw(ctx, "UniVlanConfigFsm resetting", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001275
1276 pConfigVlanStateAFsm := oFsm.pAdaptFsm
1277 if pConfigVlanStateAFsm != nil {
1278 // abort running message processing
1279 fsmAbortMsg := Message{
1280 Type: TestMsg,
1281 Data: TestMessage{
1282 TestMessageVal: AbortMessageProcessing,
1283 },
1284 }
1285 pConfigVlanStateAFsm.commChan <- fsmAbortMsg
1286
mpagenko9a304ea2020-12-16 15:54:01 +00001287 //try to restart the FSM to 'disabled'
1288 // Can't call FSM Event directly, decoupling it
mpagenkodff5dda2020-08-28 11:52:01 +00001289 go func(a_pAFsm *AdapterFsm) {
1290 if a_pAFsm != nil && a_pAFsm.pFsm != nil {
Himani Chawla4d908332020-08-31 12:30:20 +05301291 _ = a_pAFsm.pFsm.Event(vlanEvRestart)
mpagenkodff5dda2020-08-28 11:52:01 +00001292 }
1293 }(pConfigVlanStateAFsm)
1294 }
1295}
1296
dbainbri4d3a0dc2020-12-02 00:33:42 +00001297func (oFsm *UniVlanConfigFsm) enterDisabled(ctx context.Context, e *fsm.Event) {
1298 logger.Debugw(ctx, "UniVlanConfigFsm enters disabled state", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001299 oFsm.pLastTxMeInstance = nil
mpagenkodff5dda2020-08-28 11:52:01 +00001300 if oFsm.pDeviceHandler != nil {
mpagenko2418ab02020-11-12 12:58:06 +00001301 //TODO: to clarify with improved error treatment for VlanConfigFsm (timeout,reception) errors
1302 // current code removes the complete FSM including all flow/rule configuration done so far
1303 // this might be a bit to much, it would require fully new flow config from rwCore (at least on OnuDown/up)
1304 // maybe a more sophisticated approach is possible without clearing the data
mpagenko9a304ea2020-12-16 15:54:01 +00001305 oFsm.mutexFlowParams.RLock()
mpagenko2418ab02020-11-12 12:58:06 +00001306 if oFsm.clearPersistency {
1307 //permanently remove possibly stored persistent data
1308 if len(oFsm.uniVlanFlowParamsSlice) > 0 {
1309 var emptySlice = make([]uniVlanFlowParams, 0)
mpagenkof1fc3862021-02-16 10:09:52 +00001310 _ = oFsm.pDeviceHandler.storePersUniFlowConfig(ctx, oFsm.pOnuUniPort.uniID, &emptySlice, true) //ignore errors
mpagenko2418ab02020-11-12 12:58:06 +00001311 }
1312 } else {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001313 logger.Debugw(ctx, "UniVlanConfigFsm persistency data not cleared", log.Fields{"device-id": oFsm.deviceID})
mpagenko2418ab02020-11-12 12:58:06 +00001314 }
mpagenkof1fc3862021-02-16 10:09:52 +00001315 if oFsm.delayNewRuleCookie != 0 {
1316 // looks like the waiting AddFlow is stuck
1317 oFsm.chCookieDeleted <- true // let the waiting AddFlow thread continue/treminate
1318 }
mpagenko9a304ea2020-12-16 15:54:01 +00001319 oFsm.mutexFlowParams.RUnlock()
mpagenko2418ab02020-11-12 12:58:06 +00001320 //request removal of 'reference' in the Handler (completely clear the FSM and its data)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001321 go oFsm.pDeviceHandler.RemoveVlanFilterFsm(ctx, oFsm.pOnuUniPort)
mpagenkodff5dda2020-08-28 11:52:01 +00001322 }
1323}
1324
dbainbri4d3a0dc2020-12-02 00:33:42 +00001325func (oFsm *UniVlanConfigFsm) processOmciVlanMessages(ctx context.Context) { //ctx context.Context?
1326 logger.Debugw(ctx, "Start UniVlanConfigFsm Msg processing", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001327loop:
1328 for {
mpagenkodff5dda2020-08-28 11:52:01 +00001329 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00001330 // logger.Info(ctx,"MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001331 // break loop
Himani Chawla4d908332020-08-31 12:30:20 +05301332 message, ok := <-oFsm.pAdaptFsm.commChan
1333 if !ok {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001334 logger.Info(ctx, "UniVlanConfigFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301335 // but then we have to ensure a restart of the FSM as well - as exceptional procedure
1336 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1337 break loop
1338 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001339 logger.Debugw(ctx, "UniVlanConfigFsm Rx Msg", log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301340
1341 switch message.Type {
1342 case TestMsg:
1343 msg, _ := message.Data.(TestMessage)
1344 if msg.TestMessageVal == AbortMessageProcessing {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001345 logger.Infow(ctx, "UniVlanConfigFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001346 break loop
1347 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001348 logger.Warnw(ctx, "UniVlanConfigFsm unknown TestMessage", log.Fields{"device-id": oFsm.deviceID, "MessageVal": msg.TestMessageVal})
Himani Chawla4d908332020-08-31 12:30:20 +05301349 case OMCI:
1350 msg, _ := message.Data.(OmciMessage)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001351 oFsm.handleOmciVlanConfigMessage(ctx, msg)
Himani Chawla4d908332020-08-31 12:30:20 +05301352 default:
dbainbri4d3a0dc2020-12-02 00:33:42 +00001353 logger.Warn(ctx, "UniVlanConfigFsm Rx unknown message", log.Fields{"device-id": oFsm.deviceID,
Himani Chawla4d908332020-08-31 12:30:20 +05301354 "message.Type": message.Type})
mpagenkodff5dda2020-08-28 11:52:01 +00001355 }
1356 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001357 logger.Infow(ctx, "End UniVlanConfigFsm Msg processing", log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001358}
1359
dbainbri4d3a0dc2020-12-02 00:33:42 +00001360func (oFsm *UniVlanConfigFsm) handleOmciVlanConfigMessage(ctx context.Context, msg OmciMessage) {
1361 logger.Debugw(ctx, "Rx OMCI UniVlanConfigFsm Msg", log.Fields{"device-id": oFsm.deviceID,
mpagenkodff5dda2020-08-28 11:52:01 +00001362 "msgType": msg.OmciMsg.MessageType})
1363
1364 switch msg.OmciMsg.MessageType {
1365 case omci.CreateResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001366 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001367 if err := oFsm.handleOmciCreateResponseMessage(ctx, msg.OmciPacket); err != nil {
1368 logger.Warnw(ctx, "CreateResponse handling aborted", log.Fields{"err": err})
mpagenkodff5dda2020-08-28 11:52:01 +00001369 return
1370 }
mpagenkodff5dda2020-08-28 11:52:01 +00001371 } //CreateResponseType
1372 case omci.SetResponseType:
mpagenko01e726e2020-10-23 09:45:29 +00001373 { //leave that here as direct code as most often used
mpagenkodff5dda2020-08-28 11:52:01 +00001374 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1375 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001376 logger.Errorw(ctx, "Omci Msg layer could not be detected for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001377 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001378 return
1379 }
1380 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1381 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001382 logger.Errorw(ctx, "Omci Msg layer could not be assigned for SetResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001383 log.Fields{"device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001384 return
1385 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001386 logger.Debugw(ctx, "UniVlanConfigFsm SetResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenkodff5dda2020-08-28 11:52:01 +00001387 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001388 logger.Errorw(ctx, "UniVlanConfigFsm Omci SetResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001389 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
mpagenkodff5dda2020-08-28 11:52:01 +00001390 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1391 return
1392 }
mpagenko01e726e2020-10-23 09:45:29 +00001393 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1394 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1395 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001396 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData", "MulticastOperationsProfile":
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001397 { // let the MultiEntity config proceed by stopping the wait function
mpagenkodff5dda2020-08-28 11:52:01 +00001398 oFsm.omciMIdsResponseReceived <- true
1399 }
1400 }
1401 }
1402 } //SetResponseType
mpagenko01e726e2020-10-23 09:45:29 +00001403 case omci.DeleteResponseType:
1404 { // had to shift that to a method to cope with StaticCodeAnalysis restrictions :-(
dbainbri4d3a0dc2020-12-02 00:33:42 +00001405 if err := oFsm.handleOmciDeleteResponseMessage(ctx, msg.OmciPacket); err != nil {
1406 logger.Warnw(ctx, "DeleteResponse handling aborted", log.Fields{"err": err})
mpagenko01e726e2020-10-23 09:45:29 +00001407 return
1408 }
1409 } //DeleteResponseType
mpagenkodff5dda2020-08-28 11:52:01 +00001410 default:
1411 {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001412 logger.Errorw(ctx, "Rx OMCI unhandled MsgType",
mpagenko01e726e2020-10-23 09:45:29 +00001413 log.Fields{"omciMsgType": msg.OmciMsg.MessageType, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001414 return
1415 }
1416 }
1417}
1418
dbainbri4d3a0dc2020-12-02 00:33:42 +00001419func (oFsm *UniVlanConfigFsm) handleOmciCreateResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001420 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeCreateResponse)
1421 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001422 logger.Errorw(ctx, "Omci Msg layer could not be detected for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001423 log.Fields{"device-id": oFsm.deviceID})
1424 return fmt.Errorf("omci msg layer could not be detected for CreateResponse for device-id %x",
1425 oFsm.deviceID)
1426 }
1427 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
1428 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001429 logger.Errorw(ctx, "Omci Msg layer could not be assigned for CreateResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001430 log.Fields{"device-id": oFsm.deviceID})
1431 return fmt.Errorf("omci msg layer could not be assigned for CreateResponse for device-id %x",
1432 oFsm.deviceID)
1433 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001434 logger.Debugw(ctx, "UniVlanConfigFsm CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001435 if msgObj.Result != me.Success && msgObj.Result != me.InstanceExists {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001436 logger.Errorw(ctx, "Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"device-id": oFsm.deviceID,
mpagenko01e726e2020-10-23 09:45:29 +00001437 "Error": msgObj.Result})
1438 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1439 return fmt.Errorf("omci CreateResponse Error for device-id %x",
1440 oFsm.deviceID)
1441 }
1442 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1443 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1444 // to satisfy StaticCodeAnalysis I had to move the small processing into a separate method :-(
1445 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001446 case "VlanTaggingFilterData", "MulticastOperationsProfile",
1447 "MulticastSubscriberConfigInfo", "MacBridgePortConfigurationData",
1448 "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001449 {
1450 if oFsm.pAdaptFsm.pFsm.Current() == vlanStConfigVtfd {
1451 // Only if CreateResponse is received from first flow entry - let the FSM proceed ...
1452 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigVtfd)
1453 } else { // let the MultiEntity config proceed by stopping the wait function
1454 oFsm.omciMIdsResponseReceived <- true
1455 }
1456 }
1457 }
1458 }
1459 return nil
1460}
1461
dbainbri4d3a0dc2020-12-02 00:33:42 +00001462func (oFsm *UniVlanConfigFsm) handleOmciDeleteResponseMessage(ctx context.Context, apOmciPacket *gp.Packet) error {
mpagenko01e726e2020-10-23 09:45:29 +00001463 msgLayer := (*apOmciPacket).Layer(omci.LayerTypeDeleteResponse)
1464 if msgLayer == nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001465 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be detected for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001466 log.Fields{"device-id": oFsm.deviceID})
1467 return fmt.Errorf("omci msg layer could not be detected for DeleteResponse for device-id %x",
1468 oFsm.deviceID)
1469 }
1470 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
1471 if !msgOk {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001472 logger.Errorw(ctx, "UniVlanConfigFsm - Omci Msg layer could not be assigned for DeleteResponse",
mpagenko01e726e2020-10-23 09:45:29 +00001473 log.Fields{"device-id": oFsm.deviceID})
1474 return fmt.Errorf("omci msg layer could not be assigned for DeleteResponse for device-id %x",
1475 oFsm.deviceID)
1476 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001477 logger.Debugw(ctx, "UniVlanConfigFsm DeleteResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
mpagenko01e726e2020-10-23 09:45:29 +00001478 if msgObj.Result != me.Success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001479 logger.Errorw(ctx, "UniVlanConfigFsm - Omci DeleteResponse Error - later: drive FSM to abort state ?",
mpagenko01e726e2020-10-23 09:45:29 +00001480 log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
1481 // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
1482 return fmt.Errorf("omci DeleteResponse Error for device-id %x",
1483 oFsm.deviceID)
1484 }
1485 if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
1486 msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
1487 switch oFsm.pLastTxMeInstance.GetName() {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001488 case "VlanTaggingFilterData", "ExtendedVlanTaggingOperationConfigurationData":
mpagenko01e726e2020-10-23 09:45:29 +00001489 { // let the MultiEntity config proceed by stopping the wait function
1490 oFsm.omciMIdsResponseReceived <- true
1491 }
1492 }
1493 }
1494 return nil
1495}
1496
dbainbri4d3a0dc2020-12-02 00:33:42 +00001497func (oFsm *UniVlanConfigFsm) performConfigEvtocdEntries(ctx context.Context, aFlowEntryNo uint8) error {
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001498 if aFlowEntryNo == 0 {
1499 // EthType set only at first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001500 // EVTOCD ME is expected to exist at this point already from MIB-Download (with AssociationType/Pointer)
1501 // we need to extend the configuration by EthType definition and, to be sure, downstream 'inverse' mode
dbainbri4d3a0dc2020-12-02 00:33:42 +00001502 logger.Debugw(ctx, "UniVlanConfigFsm Tx Create::EVTOCD", log.Fields{
mpagenkodff5dda2020-08-28 11:52:01 +00001503 "EntitytId": strconv.FormatInt(int64(oFsm.evtocdID), 16),
1504 "i/oEthType": strconv.FormatInt(int64(cDefaultTpid), 16),
mpagenko01e726e2020-10-23 09:45:29 +00001505 "device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001506 associationType := 2 // default to uniPPTP
1507 if oFsm.pOnuUniPort.portType == uniVEIP {
1508 associationType = 10
1509 }
1510 // Create the EVTOCD ME
mpagenkodff5dda2020-08-28 11:52:01 +00001511 meParams := me.ParamData{
1512 EntityID: oFsm.evtocdID,
1513 Attributes: me.AttributeValueMap{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001514 "AssociationType": uint8(associationType),
1515 "AssociatedMePointer": oFsm.pOnuUniPort.entityID,
mpagenkodff5dda2020-08-28 11:52:01 +00001516 },
1517 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001518 meInstance := oFsm.pOmciCC.sendCreateEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001519 oFsm.pAdaptFsm.commChan, meParams)
1520 //accept also nil as (error) return value for writing to LastTx
1521 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001522 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001523
1524 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001525 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001526 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001527 logger.Errorw(ctx, "Evtocd create failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001528 log.Fields{"device-id": oFsm.deviceID})
1529 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1530 return fmt.Errorf("evtocd create failed %s, error %s", oFsm.deviceID, err)
1531 }
1532
1533 // Set the EVTOCD ME default params
1534 meParams = me.ParamData{
1535 EntityID: oFsm.evtocdID,
1536 Attributes: me.AttributeValueMap{
1537 "InputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1538 "OutputTpid": uint16(cDefaultTpid), //could be possibly retrieved from flow config one day, by now just like py-code base
1539 "DownstreamMode": uint8(cDefaultDownstreamMode),
1540 },
1541 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001542 meInstance = oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001543 oFsm.pAdaptFsm.commChan, meParams)
1544 //accept also nil as (error) return value for writing to LastTx
1545 // - this avoids misinterpretation of new received OMCI messages
1546 oFsm.pLastTxMeInstance = meInstance
1547
1548 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001549 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001550 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001551 logger.Errorw(ctx, "Evtocd set TPID failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001552 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301553 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001554 return fmt.Errorf("evtocd set TPID failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001555 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001556 } //first flow element
mpagenkodff5dda2020-08-28 11:52:01 +00001557
mpagenko551a4d42020-12-08 18:09:20 +00001558 oFsm.mutexFlowParams.RLock()
mpagenko9a304ea2020-12-16 15:54:01 +00001559 if oFsm.actualUniVlanConfigRule.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
mpagenkodff5dda2020-08-28 11:52:01 +00001560 //transparent transmission required
mpagenko551a4d42020-12-08 18:09:20 +00001561 oFsm.mutexFlowParams.RUnlock()
dbainbri4d3a0dc2020-12-02 00:33:42 +00001562 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged transparent rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001563 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001564 sliceEvtocdRule := make([]uint8, 16)
1565 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1566 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1567 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1568 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1569 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1570
1571 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1572 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1573 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1574 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1575 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1576
1577 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1578 0<<cTreatTTROffset| // Do not pop any tags
1579 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1580 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1581 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1582
1583 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1584 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1585 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1586 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1587
1588 meParams := me.ParamData{
1589 EntityID: oFsm.evtocdID,
1590 Attributes: me.AttributeValueMap{
1591 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1592 },
1593 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001594 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001595 oFsm.pAdaptFsm.commChan, meParams)
1596 //accept also nil as (error) return value for writing to LastTx
1597 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001598 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001599
1600 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001601 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001602 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001603 logger.Errorw(ctx, "Evtocd set transparent singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001604 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301605 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001606 return fmt.Errorf("evtocd set transparent singletagged rule failed %s, error %s", oFsm.deviceID, err)
1607
mpagenkodff5dda2020-08-28 11:52:01 +00001608 }
1609 } else {
1610 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1611 if oFsm.acceptIncrementalEvtoOption {
mpagenko9a304ea2020-12-16 15:54:01 +00001612 matchPcp := oFsm.actualUniVlanConfigRule.MatchPcp
1613 matchVid := oFsm.actualUniVlanConfigRule.MatchVid
1614 setPcp := oFsm.actualUniVlanConfigRule.SetPcp
1615 setVid := oFsm.actualUniVlanConfigRule.SetVid
mpagenkodff5dda2020-08-28 11:52:01 +00001616 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001617 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD single tagged translation rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001618 "match-pcp": matchPcp, "match-vid": matchVid, "set-pcp": setPcp, "set-vid:": setVid, "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001619 sliceEvtocdRule := make([]uint8, 16)
1620 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1621 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1622 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1623 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1624 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1625
1626 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001627 oFsm.actualUniVlanConfigRule.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1628 oFsm.actualUniVlanConfigRule.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
mpagenkodff5dda2020-08-28 11:52:01 +00001629 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1630 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1631
1632 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001633 oFsm.actualUniVlanConfigRule.TagsToRemove<<cTreatTTROffset| // either 1 or 0
mpagenkodff5dda2020-08-28 11:52:01 +00001634 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1635 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1636 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1637
1638 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
mpagenko9a304ea2020-12-16 15:54:01 +00001639 oFsm.actualUniVlanConfigRule.SetPcp<<cTreatPrioOffset| // as configured in flow
1640 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| //as configured in flow
mpagenkodff5dda2020-08-28 11:52:01 +00001641 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001642 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001643
1644 meParams := me.ParamData{
1645 EntityID: oFsm.evtocdID,
1646 Attributes: me.AttributeValueMap{
1647 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1648 },
1649 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001650 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001651 oFsm.pAdaptFsm.commChan, meParams)
1652 //accept also nil as (error) return value for writing to LastTx
1653 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001654 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001655
1656 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001657 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001658 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001659 logger.Errorw(ctx, "Evtocd set singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001660 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301661 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001662 return fmt.Errorf("evtocd set singletagged translation rule failed %s, error %s", oFsm.deviceID, err)
mpagenkodff5dda2020-08-28 11:52:01 +00001663 }
1664 } else {
1665 //not transparent and not acceptIncrementalEvtoOption untagged/priotagged->singletagged
1666 { // just for local var's
1667 // this defines stacking scenario: untagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001668 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD untagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001669 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001670 sliceEvtocdRule := make([]uint8, 16)
1671 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1672 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1673 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1674 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1675 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1676
1677 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1678 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1679 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1680 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1681 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1682
1683 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1684 0<<cTreatTTROffset| // Do not pop any tags
1685 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1686 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1687 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1688
1689 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1690 0<<cTreatPrioOffset| // vlan prio set to 0
1691 // (as done in Py code, maybe better option would be setPcp here, which still could be 0?)
mpagenko9a304ea2020-12-16 15:54:01 +00001692 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID don't care
mpagenkodff5dda2020-08-28 11:52:01 +00001693 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
1694
mpagenko551a4d42020-12-08 18:09:20 +00001695 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001696 meParams := me.ParamData{
1697 EntityID: oFsm.evtocdID,
1698 Attributes: me.AttributeValueMap{
1699 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1700 },
1701 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001702 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001703 oFsm.pAdaptFsm.commChan, meParams)
1704 //accept also nil as (error) return value for writing to LastTx
1705 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001706 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001707
1708 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001709 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001710 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001711 logger.Errorw(ctx, "Evtocd set untagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001712 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301713 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001714 return fmt.Errorf("evtocd set untagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1715
mpagenkodff5dda2020-08-28 11:52:01 +00001716 }
Holger Hildebrandt394c5522020-09-11 11:23:01 +00001717 } // just for local var's
mpagenkodff5dda2020-08-28 11:52:01 +00001718 { // just for local var's
1719 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001720 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD priotagged->singletagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001721 "device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00001722 sliceEvtocdRule := make([]uint8, 16)
1723 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1724 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1725 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1726 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1727 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1728
1729 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1730 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1731 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1732 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1733 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1734
1735 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1736 1<<cTreatTTROffset| // pop the prio-tag
1737 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1738 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1739 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1740
mpagenko551a4d42020-12-08 18:09:20 +00001741 oFsm.mutexFlowParams.RLock()
mpagenkodff5dda2020-08-28 11:52:01 +00001742 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1743 cCopyPrioFromInner<<cTreatPrioOffset| // vlan copy from PrioTag
1744 // (as done in Py code, maybe better option would be setPcp here, which still could be PrioCopy?)
mpagenko9a304ea2020-12-16 15:54:01 +00001745 oFsm.actualUniVlanConfigRule.SetVid<<cTreatVidOffset| // Outer VID as configured
mpagenkodff5dda2020-08-28 11:52:01 +00001746 cSetOutputTpidCopyDei<<cTreatTpidOffset) // Set TPID = 0x8100
mpagenko551a4d42020-12-08 18:09:20 +00001747 oFsm.mutexFlowParams.RUnlock()
mpagenkodff5dda2020-08-28 11:52:01 +00001748
1749 meParams := me.ParamData{
1750 EntityID: oFsm.evtocdID,
1751 Attributes: me.AttributeValueMap{
1752 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1753 },
1754 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001755 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenkodff5dda2020-08-28 11:52:01 +00001756 oFsm.pAdaptFsm.commChan, meParams)
1757 //accept also nil as (error) return value for writing to LastTx
1758 // - this avoids misinterpretation of new received OMCI messages
mpagenko01e726e2020-10-23 09:45:29 +00001759 oFsm.pLastTxMeInstance = meInstance
mpagenkodff5dda2020-08-28 11:52:01 +00001760
1761 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001762 err := oFsm.waitforOmciResponse(ctx)
mpagenkodff5dda2020-08-28 11:52:01 +00001763 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001764 logger.Errorw(ctx, "Evtocd set priotagged->singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001765 log.Fields{"device-id": oFsm.deviceID})
Himani Chawla4d908332020-08-31 12:30:20 +05301766 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001767 return fmt.Errorf("evtocd set priotagged->singletagged rule failed %s, error %s", oFsm.deviceID, err)
1768
mpagenkodff5dda2020-08-28 11:52:01 +00001769 }
1770 } //just for local var's
1771 }
1772 }
1773
mpagenkofc4f56e2020-11-04 17:17:49 +00001774 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00001775 logger.Debugw(ctx, "EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00001776 oFsm.configuredUniFlow++ // one (more) flow configured
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001777 return nil
mpagenkodff5dda2020-08-28 11:52:01 +00001778}
1779
dbainbri4d3a0dc2020-12-02 00:33:42 +00001780func (oFsm *UniVlanConfigFsm) removeEvtocdEntries(ctx context.Context, aRuleParams uniVlanRuleParams) {
mpagenko01e726e2020-10-23 09:45:29 +00001781 // configured Input/Output TPID is not modified again - no influence if no filter is applied
1782 if aRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
1783 //transparent transmission was set
1784 //perhaps the config is not needed for removal,
1785 // but the specific InnerTpid setting is removed in favor of the real default forwarding rule
dbainbri4d3a0dc2020-12-02 00:33:42 +00001786 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset to default single tagged rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001787 "device-id": oFsm.deviceID})
1788 sliceEvtocdRule := make([]uint8, 16)
1789 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1790 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1791 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1792 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1793 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1794
1795 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1796 cPrioDefaultFilter<<cFilterPrioOffset| // default inner-tag rule
1797 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1798 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1799 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1800
1801 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1802 0<<cTreatTTROffset| // Do not pop any tags
1803 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1804 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1805 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
1806
1807 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1808 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1809 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1810 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
1811
1812 meParams := me.ParamData{
1813 EntityID: oFsm.evtocdID,
1814 Attributes: me.AttributeValueMap{
1815 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1816 },
1817 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001818 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001819 oFsm.pAdaptFsm.commChan, meParams)
1820 //accept also nil as (error) return value for writing to LastTx
1821 // - this avoids misinterpretation of new received OMCI messages
1822 oFsm.pLastTxMeInstance = meInstance
1823
1824 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001825 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001826 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001827 logger.Errorw(ctx, "Evtocd reset singletagged rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001828 log.Fields{"device-id": oFsm.deviceID})
1829 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1830 return
1831 }
1832 } else {
1833 // according to py-code acceptIncrementalEvto program option decides upon stacking or translation scenario
1834 if oFsm.acceptIncrementalEvtoOption {
1835 // this defines VID translation scenario: singletagged->singletagged (if not transparent)
dbainbri4d3a0dc2020-12-02 00:33:42 +00001836 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD clear single tagged translation rule", log.Fields{
mpagenko01e726e2020-10-23 09:45:29 +00001837 "device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1838 sliceEvtocdRule := make([]uint8, 16)
1839 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1840 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1841 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1842 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1843 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1844
1845 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1846 aRuleParams.MatchPcp<<cFilterPrioOffset| // either DNFonPrio or ignore tag (default) on innerVLAN
1847 aRuleParams.MatchVid<<cFilterVidOffset| // either DNFonVid or real filter VID
1848 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1849 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1850
1851 // delete indication for the indicated Filter
1852 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1853 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1854
1855 meParams := me.ParamData{
1856 EntityID: oFsm.evtocdID,
1857 Attributes: me.AttributeValueMap{
1858 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1859 },
1860 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001861 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001862 oFsm.pAdaptFsm.commChan, meParams)
1863 //accept also nil as (error) return value for writing to LastTx
1864 // - this avoids misinterpretation of new received OMCI messages
1865 oFsm.pLastTxMeInstance = meInstance
1866
1867 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001868 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001869 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001870 logger.Errorw(ctx, "Evtocd clear singletagged translation rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001871 log.Fields{"device-id": oFsm.deviceID, "match-vlan": aRuleParams.MatchVid})
1872 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1873 return
1874 }
1875 } else {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001876 // VOL-3685
1877 // NOTE: With ALPHA ONUs it was seen that just resetting a particular entry in the EVTOCD table
1878 // and re-configuring a new entry would not work. The old entry is removed and new entry is created
1879 // indeed, but the traffic landing upstream would carry old vlan sometimes.
1880 // This is only a WORKAROUND which basically deletes the entire EVTOCD ME and re-creates it again
1881 // later when the flow is being re-installed.
1882 // Of course this is applicable to case only where single service (or single tcont) is in use and
1883 // there is only one service vlan (oFsm.acceptIncrementalEvtoOption is false in this case).
1884 // Interstingly this problem has not been observed in multi-tcont (or multi-service) scenario (in
1885 // which case the oFsm.acceptIncrementalEvtoOption is set to true).
1886 if oFsm.configuredUniFlow == 0 && !oFsm.acceptIncrementalEvtoOption {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001887 logger.Debugw(ctx, "UniVlanConfigFsm Tx Remove::EVTOCD", log.Fields{"device-id": oFsm.deviceID})
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001888 // When there are no more EVTOCD vlan configurations on the ONU and acceptIncrementalEvtoOption
1889 // is not enabled, delete the EVTOCD ME.
mpagenko01e726e2020-10-23 09:45:29 +00001890 meParams := me.ParamData{
1891 EntityID: oFsm.evtocdID,
mpagenko01e726e2020-10-23 09:45:29 +00001892 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001893 meInstance := oFsm.pOmciCC.sendDeleteEvtocd(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
mpagenko01e726e2020-10-23 09:45:29 +00001894 oFsm.pAdaptFsm.commChan, meParams)
1895 //accept also nil as (error) return value for writing to LastTx
1896 // - this avoids misinterpretation of new received OMCI messages
1897 oFsm.pLastTxMeInstance = meInstance
1898
1899 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001900 err := oFsm.waitforOmciResponse(ctx)
mpagenko01e726e2020-10-23 09:45:29 +00001901 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001902 logger.Errorw(ctx, "Evtocd delete rule failed, aborting VlanConfig FSM!",
mpagenko01e726e2020-10-23 09:45:29 +00001903 log.Fields{"device-id": oFsm.deviceID})
1904 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1905 return
1906 }
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001907 } else {
1908 // NOTE : We should ideally never ether this section when oFsm.acceptIncrementalEvtoOption is set to false
1909 // This is true for only ATT/DT workflow
dbainbri4d3a0dc2020-12-02 00:33:42 +00001910 logger.Debugw(ctx, "UniVlanConfigFsm: Remove EVTOCD set operation",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001911 log.Fields{"configured-flow": oFsm.configuredUniFlow, "incremental-evto": oFsm.acceptIncrementalEvtoOption})
1912 //not transparent and not acceptIncrementalEvtoOption: untagged/priotagged->singletagged
1913 { // just for local var's
1914 // this defines stacking scenario: untagged->singletagged
1915 //TODO!! in theory there could be different rules running in setting different PCP/VID'S
1916 // for untagged/priotagged, last rule wins (and remains the only one), maybe that should be
1917 // checked already at flow-add (and rejected) - to be observed if such is possible in Voltha
1918 // delete now assumes there is only one such rule!
dbainbri4d3a0dc2020-12-02 00:33:42 +00001919 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD reset untagged rule to default", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001920 "device-id": oFsm.deviceID})
1921 sliceEvtocdRule := make([]uint8, 16)
1922 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1923 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1924 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1925 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1926 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
mpagenko01e726e2020-10-23 09:45:29 +00001927
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001928 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1929 cPrioIgnoreTag<<cFilterPrioOffset| // Not an inner-tag rule
1930 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on inner vid
1931 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1932 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
mpagenko01e726e2020-10-23 09:45:29 +00001933
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001934 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:],
1935 0<<cTreatTTROffset| // Do not pop any tags
1936 cDoNotAddPrio<<cTreatPrioOffset| // do not add outer tag
1937 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1938 cDontCareTpid<<cTreatTpidOffset) // Outer TPID field don't care
mpagenko01e726e2020-10-23 09:45:29 +00001939
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001940 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:],
1941 cDoNotAddPrio<<cTreatPrioOffset| // do not add inner tag
1942 cDontCareVid<<cTreatVidOffset| // Outer VID don't care
1943 cDontCareTpid<<cTreatTpidOffset) // copy TPID and DEI
mpagenko01e726e2020-10-23 09:45:29 +00001944
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001945 meParams := me.ParamData{
1946 EntityID: oFsm.evtocdID,
1947 Attributes: me.AttributeValueMap{
1948 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1949 },
1950 }
1951 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(context.TODO(), ConstDefaultOmciTimeout, true,
1952 oFsm.pAdaptFsm.commChan, meParams)
1953 //accept also nil as (error) return value for writing to LastTx
1954 // - this avoids misinterpretation of new received OMCI messages
1955 oFsm.pLastTxMeInstance = meInstance
1956
1957 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00001958 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001959 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00001960 logger.Errorw(ctx, "Evtocd reset untagged rule to default failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001961 log.Fields{"device-id": oFsm.deviceID})
1962 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
1963 return
1964 }
1965 } // just for local var's
1966 { // just for local var's
1967 // this defines 'stacking' scenario: priotagged->singletagged
dbainbri4d3a0dc2020-12-02 00:33:42 +00001968 logger.Debugw(ctx, "UniVlanConfigFsm Tx Set::EVTOCD delete priotagged rule", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001969 "device-id": oFsm.deviceID})
1970 sliceEvtocdRule := make([]uint8, 16)
1971 // fill vlan tagging operation table bit fields using network=bigEndian order and using slice offset 0 as highest 'word'
1972 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterOuterOffset:],
1973 cPrioIgnoreTag<<cFilterPrioOffset| // Not an outer-tag rule
1974 cDoNotFilterVid<<cFilterVidOffset| // Do not filter on outer vid
1975 cDoNotFilterTPID<<cFilterTpidOffset) // Do not filter on outer TPID field
1976
1977 binary.BigEndian.PutUint32(sliceEvtocdRule[cFilterInnerOffset:],
1978 cPrioDoNotFilter<<cFilterPrioOffset| // Do not Filter on innerprio
1979 0<<cFilterVidOffset| // filter on inner vid 0 (prioTagged)
1980 cDoNotFilterTPID<<cFilterTpidOffset| // Do not filter on inner TPID field
1981 cDoNotFilterEtherType<<cFilterEtherTypeOffset) // Do not filter of EtherType
1982
1983 // delete indication for the indicated Filter
1984 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatOuterOffset:], 0xFFFFFFFF)
1985 binary.BigEndian.PutUint32(sliceEvtocdRule[cTreatInnerOffset:], 0xFFFFFFFF)
1986
1987 meParams := me.ParamData{
1988 EntityID: oFsm.evtocdID,
1989 Attributes: me.AttributeValueMap{
1990 "ReceivedFrameVlanTaggingOperationTable": sliceEvtocdRule,
1991 },
1992 }
dbainbri4d3a0dc2020-12-02 00:33:42 +00001993 meInstance := oFsm.pOmciCC.sendSetEvtocdVar(log.WithSpanFromContext(context.TODO(), ctx), ConstDefaultOmciTimeout, true,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03001994 oFsm.pAdaptFsm.commChan, meParams)
1995 //accept also nil as (error) return value for writing to LastTx
1996 // - this avoids misinterpretation of new received OMCI messages
1997 oFsm.pLastTxMeInstance = meInstance
1998
1999 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002000 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002001 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002002 logger.Errorw(ctx, "Evtocd delete priotagged rule failed, aborting VlanConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002003 log.Fields{"device-id": oFsm.deviceID})
2004 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
2005 return
2006 }
mpagenko01e726e2020-10-23 09:45:29 +00002007 }
2008 } //just for local var's
2009 }
2010 }
2011
mpagenkofc4f56e2020-11-04 17:17:49 +00002012 // if Config has been done for all EVTOCD entries let the FSM proceed
dbainbri4d3a0dc2020-12-02 00:33:42 +00002013 logger.Debugw(ctx, "EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
Girish Gowdra26a40922021-01-29 17:14:34 -08002014 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone, aRuleParams.TpID)
mpagenko01e726e2020-10-23 09:45:29 +00002015}
2016
dbainbri4d3a0dc2020-12-02 00:33:42 +00002017func (oFsm *UniVlanConfigFsm) waitforOmciResponse(ctx context.Context) error {
mpagenkodff5dda2020-08-28 11:52:01 +00002018 select {
Himani Chawla26e555c2020-08-31 12:30:20 +05302019 // maybe be also some outside cancel (but no context modeled for the moment ...)
mpagenkodff5dda2020-08-28 11:52:01 +00002020 // case <-ctx.Done():
dbainbri4d3a0dc2020-12-02 00:33:42 +00002021 // logger.Infow(ctx,"LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.deviceID})
mpagenkodff5dda2020-08-28 11:52:01 +00002022 case <-time.After(30 * time.Second): //AS FOR THE OTHER OMCI FSM's
dbainbri4d3a0dc2020-12-02 00:33:42 +00002023 logger.Warnw(ctx, "UniVlanConfigFsm multi entity timeout", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002024 return fmt.Errorf("uniVlanConfigFsm multi entity timeout %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002025 case success := <-oFsm.omciMIdsResponseReceived:
Himani Chawla4d908332020-08-31 12:30:20 +05302026 if success {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002027 logger.Debug(ctx, "UniVlanConfigFsm multi entity response received")
mpagenkodff5dda2020-08-28 11:52:01 +00002028 return nil
2029 }
2030 // should not happen so far
dbainbri4d3a0dc2020-12-02 00:33:42 +00002031 logger.Warnw(ctx, "UniVlanConfigFsm multi entity response error", log.Fields{"for device-id": oFsm.deviceID})
mpagenko01e726e2020-10-23 09:45:29 +00002032 return fmt.Errorf("uniVlanConfigFsm multi entity responseError %s", oFsm.deviceID)
mpagenkodff5dda2020-08-28 11:52:01 +00002033 }
2034}
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002035
mpagenko551a4d42020-12-08 18:09:20 +00002036func (oFsm *UniVlanConfigFsm) performSettingMulticastME(ctx context.Context, tpID uint8, multicastGemPortID uint16, vlanID uint32) error {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002037 logger.Debugw(ctx, "Setting Multicast MEs", log.Fields{"device-id": oFsm.deviceID, "tpID": tpID,
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002038 "multicastGemPortID": multicastGemPortID, "vlanID": vlanID})
dbainbri4d3a0dc2020-12-02 00:33:42 +00002039 errCreateMOP := oFsm.performCreatingMulticastOperationProfile(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002040 if errCreateMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002041 logger.Errorw(ctx, "MulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002042 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002043 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002044 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMOP)
2045 }
2046
dbainbri4d3a0dc2020-12-02 00:33:42 +00002047 errSettingMOP := oFsm.performSettingMulticastOperationProfile(ctx, multicastGemPortID, vlanID)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002048 if errSettingMOP != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002049 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002050 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002051 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002052 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errSettingMOP)
2053 }
2054
dbainbri4d3a0dc2020-12-02 00:33:42 +00002055 errCreateMSCI := oFsm.performCreatingMulticastSubscriberConfigInfo(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002056 if errCreateMSCI != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002057 logger.Errorw(ctx, "MulticastOperationProfile setting failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002058 log.Fields{"device-id": oFsm.deviceID})
mpagenko9a304ea2020-12-16 15:54:01 +00002059 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002060 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, errCreateMSCI)
2061 }
2062
2063 meParams := me.ParamData{
2064 EntityID: macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2065 Attributes: me.AttributeValueMap{
2066 "BridgeIdPointer": macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo),
2067 "PortNum": 0xf0, //fixed unique ANI side indication
2068 "TpType": 6, //MCGemIWTP
2069 "TpPointer": multicastGemPortID,
2070 },
2071 }
2072 meInstance := oFsm.pOmciCC.sendCreateMBPConfigDataVar(context.TODO(), ConstDefaultOmciTimeout, true,
2073 oFsm.pAdaptFsm.commChan, meParams)
2074 //accept also nil as (error) return value for writing to LastTx
2075 // - this avoids misinterpretation of new received OMCI messages
2076 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002077 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002078 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002079 logger.Errorw(ctx, "CreateMBPConfigData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002080 log.Fields{"device-id": oFsm.deviceID, "MBPConfigDataID": macBridgeServiceProfileEID})
mpagenko9a304ea2020-12-16 15:54:01 +00002081 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002082 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s, error %s", oFsm.deviceID, err)
2083 }
2084
2085 // ==> Start creating VTFD for mcast vlan
2086
2087 // This attribute uniquely identifies each instance of this managed entity. Through an identical ID,
2088 // this managed entity is implicitly linked to an instance of the MAC bridge port configuration data ME.
2089 mcastVtfdID := macBridgeServiceProfileEID + uint16(oFsm.pOnuUniPort.macBpNo)
2090
dbainbri4d3a0dc2020-12-02 00:33:42 +00002091 logger.Debugw(ctx, "UniVlanConfigFsm set VTFD for mcast", log.Fields{
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002092 "EntitytId": strconv.FormatInt(int64(mcastVtfdID), 16), "mcastVlanID": vlanID,
2093 "in state": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
2094 vtfdFilterList := make([]uint16, cVtfdTableSize) //needed for parameter serialization
2095
2096 // FIXME: VOL-3685: Issues with resetting a table entry in EVTOCD ME
2097 // VTFD has to be created afresh with a new entity ID that has the same entity ID as the MBPCD ME for every
2098 // new vlan associated with a different TP.
2099 vtfdFilterList[0] = uint16(vlanID)
2100
2101 meParams = me.ParamData{
2102 EntityID: mcastVtfdID,
2103 Attributes: me.AttributeValueMap{
2104 "VlanFilterList": vtfdFilterList,
2105 "ForwardOperation": uint8(0x10), //VID investigation
2106 "NumberOfEntries": oFsm.numVlanFilterEntries,
2107 },
2108 }
2109 meInstance = oFsm.pOmciCC.sendCreateVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
2110 oFsm.pAdaptFsm.commChan, meParams)
2111 oFsm.pLastTxMeInstance = meInstance
dbainbri4d3a0dc2020-12-02 00:33:42 +00002112 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002113 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002114 logger.Errorw(ctx, "CreateMcastVlanFilterData failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002115 log.Fields{"device-id": oFsm.deviceID, "mcastVtfdID": mcastVtfdID})
mpagenko9a304ea2020-12-16 15:54:01 +00002116 _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002117 return fmt.Errorf("createMcastVlanFilterData responseError %s, error %s", oFsm.deviceID, err)
2118 }
2119
2120 return nil
2121}
2122
dbainbri4d3a0dc2020-12-02 00:33:42 +00002123func (oFsm *UniVlanConfigFsm) performCreatingMulticastSubscriberConfigInfo(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002124 instID, err := oFsm.pDeviceHandler.getUniPortMEEntityID(oFsm.pOnuUniPort.portNo)
2125 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002126 logger.Errorw(ctx, "error fetching uni port me instance",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002127 log.Fields{"device-id": oFsm.deviceID, "portNo": oFsm.pOnuUniPort.portNo})
2128 return err
2129 }
2130 meParams := me.ParamData{
2131 EntityID: instID,
2132 Attributes: me.AttributeValueMap{
2133 "MeType": 0,
2134 //Direct reference to the Operation profile
2135 //TODO ANI side used on UNI side, not the clearest option.
2136 "MulticastOperationsProfilePointer": macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo),
2137 },
2138 }
2139 meInstance := oFsm.pOmciCC.sendCreateMulticastSubConfigInfoVar(context.TODO(), ConstDefaultOmciTimeout, true,
2140 oFsm.pAdaptFsm.commChan, meParams)
2141 //accept also nil as (error) return value for writing to LastTx
2142 // - this avoids misinterpretation of new received OMCI messages
2143 oFsm.pLastTxMeInstance = meInstance
2144 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002145 err = oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002146 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002147 logger.Errorw(ctx, "CreateMulticastSubConfigInfo create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002148 log.Fields{"device-id": oFsm.deviceID, "MulticastSubConfigInfo": instID})
2149 return fmt.Errorf("creatingMulticastSubscriberConfigInfo responseError %s", oFsm.deviceID)
2150 }
2151 return nil
2152}
2153
dbainbri4d3a0dc2020-12-02 00:33:42 +00002154func (oFsm *UniVlanConfigFsm) performCreatingMulticastOperationProfile(ctx context.Context) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002155 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2156 meParams := me.ParamData{
2157 EntityID: instID,
2158 Attributes: me.AttributeValueMap{
2159 "IgmpVersion": 2,
2160 "IgmpFunction": 0,
2161 //0 means false
2162 "ImmediateLeave": 0,
2163 "Robustness": 2,
2164 "QuerierIp": 0,
2165 "QueryInterval": 125,
2166 "QuerierMaxResponseTime": 100,
2167 "LastMemberResponseTime": 10,
2168 //0 means false
2169 "UnauthorizedJoinBehaviour": 0,
2170 },
2171 }
2172 meInstance := oFsm.pOmciCC.sendCreateMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2173 oFsm.pAdaptFsm.commChan, meParams)
2174 //accept also nil as (error) return value for writing to LastTx
2175 // - this avoids misinterpretation of new received OMCI messages
2176 oFsm.pLastTxMeInstance = meInstance
2177 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002178 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002179 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002180 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002181 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2182 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2183 }
2184 return nil
2185}
2186
dbainbri4d3a0dc2020-12-02 00:33:42 +00002187func (oFsm *UniVlanConfigFsm) performSettingMulticastOperationProfile(ctx context.Context, multicastGemPortID uint16, vlanID uint32) error {
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002188 instID := macBridgePortAniEID + uint16(oFsm.pOnuUniPort.macBpNo)
2189 //TODO check that this is correct
2190 // Table control
2191 //setCtrl = 1
2192 //rowPartId = 0
2193 //test = 0
2194 //rowKey = 0
2195 tableCtrlStr := "0100000000000000"
2196 tableCtrl := AsByteSlice(tableCtrlStr)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002197 dynamicAccessCL := make([]uint8, 24)
2198 copy(dynamicAccessCL, tableCtrl)
2199 //Multicast GemPortId
2200 binary.BigEndian.PutUint16(dynamicAccessCL[2:], multicastGemPortID)
2201 // python version waits for installation of flows, see line 723 onward of
2202 // brcm_openomci_onu_handler.py
2203 binary.BigEndian.PutUint16(dynamicAccessCL[4:], uint16(vlanID))
2204 //Source IP all to 0
2205 binary.BigEndian.PutUint32(dynamicAccessCL[6:], IPToInt32(net.IPv4(0, 0, 0, 0)))
2206 //TODO start and end are hardcoded, get from TP
2207 // Destination IP address start of range
2208 binary.BigEndian.PutUint32(dynamicAccessCL[10:], IPToInt32(net.IPv4(225, 0, 0, 0)))
2209 // Destination IP address end of range
2210 binary.BigEndian.PutUint32(dynamicAccessCL[14:], IPToInt32(net.IPv4(239, 255, 255, 255)))
2211 //imputed group bandwidth
2212 binary.BigEndian.PutUint16(dynamicAccessCL[18:], 0)
2213
2214 meParams := me.ParamData{
2215 EntityID: instID,
2216 Attributes: me.AttributeValueMap{
2217 "DynamicAccessControlListTable": dynamicAccessCL,
2218 },
2219 }
2220 meInstance := oFsm.pOmciCC.sendSetMulticastOperationProfileVar(context.TODO(), ConstDefaultOmciTimeout, true,
2221 oFsm.pAdaptFsm.commChan, meParams)
2222 //accept also nil as (error) return value for writing to LastTx
2223 // - this avoids misinterpretation of new received OMCI messages
2224 oFsm.pLastTxMeInstance = meInstance
2225 //verify response
dbainbri4d3a0dc2020-12-02 00:33:42 +00002226 err := oFsm.waitforOmciResponse(ctx)
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002227 if err != nil {
dbainbri4d3a0dc2020-12-02 00:33:42 +00002228 logger.Errorw(ctx, "CreateMulticastOperationProfile create failed, aborting AniConfig FSM!",
ozgecanetsiab5000ef2020-11-27 14:38:20 +03002229 log.Fields{"device-id": oFsm.deviceID, "MulticastOperationProfileID": instID})
2230 return fmt.Errorf("createMulticastOperationProfile responseError %s", oFsm.deviceID)
2231 }
2232 return nil
2233}
Girish Gowdra26a40922021-01-29 17:14:34 -08002234
2235// IsFlowRemovePending returns true if there are pending flows to remove, else false.
2236func (oFsm *UniVlanConfigFsm) IsFlowRemovePending() bool {
2237 oFsm.mutexFlowParams.RLock()
2238 defer oFsm.mutexFlowParams.RUnlock()
2239 return len(oFsm.uniRemoveFlowsSlice) > 0
2240}