[VOL-3604] flow/techProfile handling after ONU reboot/down/disable must be revised -> version 0.1.13-dev137
Signed-off-by: mpagenko <michael.pagenkopf@adtran.com>
Change-Id: I8bd846170d62f15c3a83ce6b10911707e0cd6176
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index b8605e0..2fbc5db 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -84,6 +84,7 @@
vlanEvRxConfigVtfd = "vlanEvRxConfigVtfd"
vlanEvRxConfigEvtocd = "vlanEvRxConfigEvtocd"
vlanEvIncrFlowConfig = "vlanEvIncrFlowConfig"
+ vlanEvRenew = "vlanEvRenew"
vlanEvRemFlowConfig = "vlanEvRemFlowConfig"
vlanEvRemFlowDone = "vlanEvRemFlowDone"
vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
@@ -150,6 +151,7 @@
vtfdID uint16
evtocdID uint16
pLastTxMeInstance *me.ManagedEntity
+ requestEventOffset uint8
}
//NewUniVlanConfigFsm is the 'constructor' for the state machine to config the PON ANI ports
@@ -190,6 +192,7 @@
{Name: vlanEvRxConfigEvtocd, Src: []string{vlanStConfigEvtocd, vlanStConfigIncrFlow},
Dst: vlanStConfigDone},
{Name: vlanEvIncrFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStConfigIncrFlow},
+ {Name: vlanEvRenew, Src: []string{vlanStConfigIncrFlow}, Dst: vlanStStarting},
{Name: vlanEvRemFlowConfig, Src: []string{vlanStConfigDone}, Dst: vlanStRemoveFlow},
{Name: vlanEvRemFlowDone, Src: []string{vlanStRemoveFlow}, Dst: vlanStCleanupDone},
{Name: vlanEvFlowDataRemoved, Src: []string{vlanStCleanupDone}, Dst: vlanStConfigDone},
@@ -403,7 +406,25 @@
"device-id": oFsm.deviceID, "flow-number": oFsm.numUniFlows})
return fmt.Errorf(" UniVlanConfigFsm flow limit exceeded %s", oFsm.deviceID)
}
- } //new flow
+ } else {
+ // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
+ if oFsm.numUniFlows == oFsm.configuredUniFlow {
+ //all requested rules really have been configured
+ // state transition notification is checked in deviceHandler
+ if oFsm.pDeviceHandler != nil {
+ //also the related TechProfile was already configured
+ logger.Debugw("UniVlanConfigFsm rule already set - send immediate add-success event for reason update", log.Fields{
+ "device-id": oFsm.deviceID})
+ go oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
+ }
+ } else {
+ // avoid device reason update as the rule config connected to this flow may still be in progress
+ // and the device reason should only be updated on success of rule config
+ logger.Debugw("UniVlanConfigFsm rule already set but configuration ongoing, suppress early add-success event for reason update",
+ log.Fields{"device-id": oFsm.deviceID,
+ "NumberofRules": oFsm.numUniFlows, "Configured rules": oFsm.configuredUniFlow})
+ }
+ }
if !flowEntryMatch || flowCookieModify { // some change was done to the flow entries
//permanently store flow config for reconcile case
@@ -475,20 +496,26 @@
} // if not in the appropriate state a new entry will be automatically considered later
// when the configDone state is reached
} else {
- logger.Debugw("UniVlanConfigFsm flow removal - flow persists with other cookies", log.Fields{
- "device-id": oFsm.deviceID})
//cut off the requested cookie by slicing out this element
oFsm.uniVlanFlowParamsSlice[flow].CookieSlice = append(
oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[:i],
oFsm.uniVlanFlowParamsSlice[flow].CookieSlice[i+1:]...)
- logger.Debugw("UniVlanConfigFsm flow removal - still valid cookies for this flow", log.Fields{
+ // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
+ // state transition notification is checked in deviceHandler
+ if oFsm.pDeviceHandler != nil {
+ //making use of the add->remove successor enum assumption/definition
+ go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + 1)))
+ }
+ logger.Debugw("UniVlanConfigFsm flow removal - rule persists with still valid cookies", log.Fields{
"device-id": oFsm.deviceID, "cookies": oFsm.uniVlanFlowParamsSlice[flow].CookieSlice})
}
//permanently store the modified flow config for reconcile case
- if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
- logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
- return err
+ if oFsm.pDeviceHandler != nil {
+ if err := oFsm.pDeviceHandler.storePersUniFlowConfig(oFsm.pOnuUniPort.uniID, &oFsm.uniVlanFlowParamsSlice); err != nil {
+ logger.Errorw(err.Error(), log.Fields{"device-id": oFsm.deviceID})
+ return err
+ }
}
break //found the cookie - no further search for this requested cookie
@@ -502,6 +529,12 @@
logger.Warnw("UniVlanConfigFsm flow removal - remove-cookie not found", log.Fields{
"device-id": oFsm.deviceID, "remove-cookie": aCookie})
// but accept the request with success as no such cookie (flow) does exist
+ // no activity within the FSM for OMCI processing, the deviceReason may be updated immediately
+ // state transition notification is checked in deviceHandler
+ if oFsm.pDeviceHandler != nil {
+ //making use of the add->remove successor enum assumption/definition
+ go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + 1)))
+ }
return nil
} //unknown cookie
@@ -588,6 +621,7 @@
func (oFsm *UniVlanConfigFsm) enterConfigEvtocd(e *fsm.Event) {
logger.Debugw("UniVlanConfigFsm - start config EVTOCD loop", log.Fields{
"in state": e.FSM.Current(), "device-id": oFsm.deviceID})
+ oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
go oFsm.performConfigEvtocdEntries(0)
}
@@ -617,7 +651,8 @@
// it might appear that some flows are requested also after 'flowPushed' event has been generated ...
// state transition notification is checked in deviceHandler
if oFsm.pDeviceHandler != nil {
- oFsm.pDeviceHandler.deviceProcStatusUpdate(oFsm.requestEvent)
+ //making use of the add->remove successor enum assumption/definition
+ go oFsm.pDeviceHandler.deviceProcStatusUpdate(OnuDeviceEvent((uint8(oFsm.requestEvent) + oFsm.requestEventOffset)))
}
}
@@ -627,6 +662,18 @@
"device-id": oFsm.deviceID})
oFsm.mutexFlowParams.Lock()
+ if oFsm.configuredUniFlow == 0 {
+ oFsm.mutexFlowParams.Unlock()
+ // this is a restart with a complete new flow, we can re-use the initial flow config control
+ // including the check, if the related techProfile is (still) available (probably also removed in between)
+ // calling some FSM event must be decoupled
+ pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvRenew)
+ }(pConfigVlanStateBaseFsm)
+ return
+ }
+
if oFsm.uniVlanFlowParamsSlice[oFsm.configuredUniFlow].VlanRuleParams.SetVid == uint32(of.OfpVlanId_OFPVID_PRESENT) {
// meaning transparent setup - no specific VTFD setting required
oFsm.mutexFlowParams.Unlock()
@@ -697,10 +744,14 @@
if err != nil {
logger.Errorw("VTFD create/set failed, aborting VlanConfig FSM!",
log.Fields{"device-id": oFsm.deviceID})
- _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
+ pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvReset)
+ }(pConfigVlanStateBaseFsm)
return
}
}
+ oFsm.requestEventOffset = 0 //0 offset for last flow-add activity
go oFsm.performConfigEvtocdEntries(oFsm.configuredUniFlow)
}
@@ -710,6 +761,8 @@
"in state": e.FSM.Current(), "with last cookie": oFsm.uniRemoveFlowsSlice[0].cookie,
"device-id": oFsm.deviceID})
+ pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
+ loAllowSpecificOmciConfig := oFsm.pDeviceHandler.ReadyForSpecificOmciConfig
loVlanEntryClear := uint8(0)
loVlanEntryRmPos := uint8(0x80) //with indication 'invalid' in bit 7
//shallow copy is sufficient as no reference variables are used within struct
@@ -732,10 +785,15 @@
logger.Debugw("UniVlanConfigFsm: VTFD delete (no more vlan filters)",
log.Fields{"current vlan list": oFsm.vlanFilterList,
"in state": e.FSM.Current(), "device-id": oFsm.deviceID})
- loVlanEntryClear = 1 //full VlanFilter clear request
- meInstance := oFsm.pOmciCC.sendDeleteVtfd(context.TODO(), ConstDefaultOmciTimeout, true,
- oFsm.pAdaptFsm.commChan, oFsm.vtfdID)
- oFsm.pLastTxMeInstance = meInstance
+ loVlanEntryClear = 1 //full VlanFilter clear request
+ if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
+ meInstance := oFsm.pOmciCC.sendDeleteVtfd(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, oFsm.vtfdID)
+ oFsm.pLastTxMeInstance = meInstance
+ } else {
+ logger.Debugw("UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
+ "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.deviceReason})
+ }
} else {
//many VTFD already should exists - find and remove the one concerned by the actual remove rule
// by updating the VTFD per set command with new valid list
@@ -764,29 +822,39 @@
"EntitytId": strconv.FormatInt(int64(oFsm.vtfdID), 16),
"new vlan list": vtfdFilterList, "device-id": oFsm.deviceID})
- meParams := me.ParamData{
- EntityID: oFsm.vtfdID,
- Attributes: me.AttributeValueMap{
- "VlanFilterList": vtfdFilterList,
- "NumberOfEntries": (oFsm.numVlanFilterEntries - 1), //one element less
- },
+ if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
+ meParams := me.ParamData{
+ EntityID: oFsm.vtfdID,
+ Attributes: me.AttributeValueMap{
+ "VlanFilterList": vtfdFilterList,
+ "NumberOfEntries": (oFsm.numVlanFilterEntries - 1), //one element less
+ },
+ }
+ meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
+ oFsm.pAdaptFsm.commChan, meParams)
+ oFsm.pLastTxMeInstance = meInstance
+ } else {
+ logger.Debugw("UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
+ "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.deviceReason})
}
- meInstance := oFsm.pOmciCC.sendSetVtfdVar(context.TODO(), ConstDefaultOmciTimeout, true,
- oFsm.pAdaptFsm.commChan, meParams)
- oFsm.pLastTxMeInstance = meInstance
} else {
logger.Warnw("UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
log.Fields{"device-id": oFsm.deviceID})
}
}
if loVlanEntryClear > 0 {
- //waiting on response
- err := oFsm.waitforOmciResponse()
- if err != nil {
- logger.Errorw("VTFD delete/reset failed, aborting VlanConfig FSM!",
- log.Fields{"device-id": oFsm.deviceID})
- _ = oFsm.pAdaptFsm.pFsm.Event(vlanEvReset)
- return
+ if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
+ //waiting on response
+ err := oFsm.waitforOmciResponse()
+ if err != nil {
+ logger.Errorw("VTFD delete/reset failed, aborting VlanConfig FSM!",
+ log.Fields{"device-id": oFsm.deviceID})
+ // calling some FSM event must be decoupled
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvReset)
+ }(pConfigVlanStateBaseFsm)
+ return
+ }
}
if loVlanEntryClear == 1 {
@@ -803,7 +871,17 @@
}
}
- go oFsm.removeEvtocdEntries(loRuleParams)
+ if loAllowSpecificOmciConfig { //specific OMCI config is expected to work acc. to the device state
+ go oFsm.removeEvtocdEntries(loRuleParams)
+ } else {
+ // OMCI processing is not done, expectation is to have the ONU in some basic config state accordingly
+ logger.Debugw("UniVlanConfigFsm remove EVTOCD OMCI handling skipped based on device state", log.Fields{
+ "device-id": oFsm.deviceID})
+ // calling some FSM event must be decoupled
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvRemFlowDone)
+ }(pConfigVlanStateBaseFsm)
+ }
}
func (oFsm *UniVlanConfigFsm) enterVlanCleanupDone(e *fsm.Event) {
@@ -825,6 +903,7 @@
}
oFsm.mutexFlowParams.Unlock()
+ oFsm.requestEventOffset = 1 //offset 1 for last flow-remove activity
//return to the basic config verification state
pConfigVlanStateAFsm := oFsm.pAdaptFsm
if pConfigVlanStateAFsm != nil {
@@ -1282,7 +1361,7 @@
}
}
- // if Config has been done for all GemPort instances let the FSM proceed
+ // if Config has been done for all EVTOCD entries let the FSM proceed
logger.Debugw("EVTOCD set loop finished", log.Fields{"device-id": oFsm.deviceID})
oFsm.configuredUniFlow++ // one (more) flow configured
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRxConfigEvtocd)
@@ -1483,7 +1562,7 @@
}
}
- // if Config has been done for all GemPort instances let the FSM proceed
+ // if Config has been done for all EVTOCD entries let the FSM proceed
logger.Debugw("EVTOCD filter remove loop finished", log.Fields{"device-id": oFsm.deviceID})
_ = oFsm.pAdaptFsm.pFsm.Event(vlanEvRemFlowDone)
}