[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/VERSION b/VERSION
index 86b9e51..52cd72d 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.13-dev136
+0.1.13-dev137
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 414abaf..4dce9b5 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -127,12 +127,13 @@
//onus sync.Map
//portStats *OpenOltStatisticsMgr
//metrics *pmmetrics.PmMetrics
- stopCollector chan bool
- stopHeartbeatCheck chan bool
- activePorts sync.Map
- uniEntityMap map[uint32]*onuUniPort
- UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
- reconciling bool
+ stopCollector chan bool
+ stopHeartbeatCheck chan bool
+ activePorts sync.Map
+ uniEntityMap map[uint32]*onuUniPort
+ UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
+ reconciling bool
+ ReadyForSpecificOmciConfig bool
}
//newDeviceHandler creates a new device handler
@@ -158,6 +159,7 @@
dh.uniEntityMap = make(map[uint32]*onuUniPort)
dh.UniVlanConfigFsmMap = make(map[uint8]*UniVlanConfigFsm)
dh.reconciling = false
+ dh.ReadyForSpecificOmciConfig = false
// Device related state machine
dh.pDeviceStateFsm = fsm.NewFSM(
@@ -284,11 +286,14 @@
log.Fields{"device-id": dh.deviceID})
return fmt.Errorf("techProfile DLMsg request while onuTechProf instance not setup: %s", dh.deviceID)
}
- if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock") {
- // I've seen cases for this request, where the device was already stopped
- logger.Warnw("TechProf stopped: device-unreachable", log.Fields{"device-id": dh.deviceID})
- return fmt.Errorf("device-unreachable: %s", dh.deviceID)
+ if !dh.ReadyForSpecificOmciConfig {
+ logger.Warnw("TechProf-set rejected: improper device state", log.Fields{"device-id": dh.deviceID,
+ "device-state": dh.deviceReason})
+ return fmt.Errorf("improper device state %s on device %s", dh.deviceReason, dh.deviceID)
}
+ //previous state test here was just this one, now extended for more states to reject the SetRequest:
+ // at least 'mib-downloaded' should be reached for processing of this specific ONU configuration
+ // if (dh.deviceReason == "stopping-openomci") || (dh.deviceReason == "omci-admin-lock")
msgBody := msg.GetBody()
techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
@@ -376,25 +381,21 @@
}
uniID := uint8(delGemPortMsg.UniId)
- if bTpModify := pDevEntry.updateOnuUniTpPath(uniID, ""); bTpModify {
- // deadline context to ensure completion of background routines waited for
- deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
- dctx, cancel := context.WithDeadline(context.Background(), deadline)
+ //a removal of some GemPort would never remove the complete TechProfile entry (done on T-Cont)
- dh.pOnuTP.resetTpProcessingErrorIndication()
- pDevEntry.resetKvProcessingErrorIndication()
+ // deadline context to ensure completion of background routines waited for
+ deadline := time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
+ dctx, cancel := context.WithDeadline(context.Background(), deadline)
- var wg sync.WaitGroup
- wg.Add(2) // for the 2 go routines to finish
- go pDevEntry.deleteTpResource(dctx, uniID, delGemPortMsg.TpPath,
- cResourceGemPort, delGemPortMsg.GemPortId, &wg)
- // Removal of the tcont/alloc id mapping represents the removal of the tech profile
- go pDevEntry.updateOnuKvStore(dctx, &wg)
- dh.waitForCompletion(cancel, &wg, "GemDelete") //wait for background process to finish
+ dh.pOnuTP.resetTpProcessingErrorIndication()
- return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(), pDevEntry.getKvProcessingErrorIndication())
- }
- return nil
+ var wg sync.WaitGroup
+ wg.Add(1) // for the 1 go routine to finish
+ go dh.pOnuTP.deleteTpResource(dctx, uniID, delGemPortMsg.TpPath,
+ cResourceGemPort, delGemPortMsg.GemPortId, &wg)
+ dh.waitForCompletion(cancel, &wg, "GemDelete") //wait for background process to finish
+
+ return dh.pOnuTP.getTpProcessingErrorIndication()
}
func (dh *deviceHandler) processInterAdapterDeleteTcontReqMessage(
@@ -442,7 +443,7 @@
var wg sync.WaitGroup
wg.Add(2) // for the 2 go routines to finish
- go pDevEntry.deleteTpResource(dctx, uniID, delTcontMsg.TpPath,
+ go dh.pOnuTP.deleteTpResource(dctx, uniID, delTcontMsg.TpPath,
cResourceTcont, delTcontMsg.AllocId, &wg)
// Removal of the tcont/alloc id mapping represents the removal of the tech profile
go pDevEntry.updateOnuKvStore(dctx, &wg)
@@ -534,7 +535,6 @@
retError = fmt.Errorf("flow-remove inPort not found in UniPorts, inPort %d, device-id %s",
flowInPort, dh.deviceID)
continue
- //return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
}
flowOutPort := flow.GetOutPort(flowItem)
logger.Debugw("flow-remove port indications", log.Fields{
@@ -586,6 +586,18 @@
continue
//return fmt.Errorf("flow-parameter inPort %d not found in internal UniPorts", flowInPort)
}
+ // let's still assume that we receive the flow-add only in some 'active' device state (as so far observed)
+ // if not, we just throw some error here to have an indication about that, if we really need to support that
+ // then we would need to create some means to activate the internal stored flows
+ // after the device gets active automatically (and still with its dependency to the TechProfile)
+ // for state checking compare also code here: processInterAdapterTechProfileDownloadReqMessage
+ // also abort for the other still possible flows here
+ if !dh.ReadyForSpecificOmciConfig {
+ logger.Warnw("flow-add rejected: improper device state", log.Fields{"device-id": dh.deviceID,
+ "last device-reason": dh.deviceReason})
+ return fmt.Errorf("improper device state on device %s", dh.deviceID)
+ }
+
flowOutPort := flow.GetOutPort(flowItem)
logger.Debugw("flow-add port indications", log.Fields{
"device-id": dh.deviceID, "inPort": flowInPort, "outPort": flowOutPort,
@@ -608,27 +620,21 @@
}
//disableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
+//following are the expected device states after this activity:
+//Device Admin-State : down (on rwCore), Port-State: UNKNOWN, Conn-State: REACHABLE, Reason: omci-admin-lock
+// (Conn-State: REACHABLE might conflict with some previous ONU Down indication - maybe to be resolved later)
func (dh *deviceHandler) disableDevice(device *voltha.Device) {
logger.Debugw("disable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
//admin-lock reason can also be used uniquely for setting the DeviceState accordingly
+ //note that disableDevice sequences in some 'ONU active' state may yield also
+ // "tech...delete-success" or "omci-flow-deleted" according to further received requests in the end
// - inblock state checking to prevent possibly unneeded processing (on command repitition)
if dh.deviceReason != "omci-admin-lock" {
- //running FSM's are stopped/reset here to avoid indirect stucking
- // due to blocked OMCI transmission on disabled state
- // but with possibly aborted FSM's there might be complications as the expected state
- // after some re-enable would then be quite undefined
- // maybe after re-enabling some additional checks would be required to possibly enforce new
- // (reconcile-like) config (which would require some indication from 'aborted' FSM's first)
- // for now let's assume no running FSM is active at this time point here ... -> TODO!!!
- if err := dh.resetFsms(); err != nil {
- logger.Errorw("error-disableDevice at FSM stop",
- log.Fields{"device-id": dh.deviceID, "error": err})
- // abort: system behavior is just unstable ...
- return
- }
+ //disable-device shall be just a UNi/ONU-G related admin state setting
+ //all other configurations/FSM's shall not be impacted and shall execute as required by the system
- if dh.deviceReason != "rebooting" {
+ if dh.ReadyForSpecificOmciConfig {
// disable UNI ports/ONU
// *** should generate UniDisableStateDone event - used to disable the port(s) on success
if dh.pLockStateFsm == nil {
@@ -654,14 +660,6 @@
logger.Errorw("error-updating-reason-state", log.Fields{"device-id": dh.deviceID, "error": err})
}
dh.deviceReason = "omci-admin-lock"
-
- //stop the device entry which resets the attached omciCC
- pDevEntry := dh.getOnuDeviceEntry(false)
- if pDevEntry == nil {
- logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
- return
- }
- _ = pDevEntry.stop(context.TODO(), true) //stop deviceEntry with omciCC reset
}
}
}
@@ -670,6 +668,16 @@
func (dh *deviceHandler) reEnableDevice(device *voltha.Device) {
logger.Debugw("reenable-device", log.Fields{"device-id": device.Id, "SerialNumber": device.SerialNumber})
+ //setting ReadyForSpecificOmciConfig here is just a workaround for BBSIM testing in the sequence
+ // OnuSoftReboot-disable-enable, because BBSIM does not generate a new OnuIndication-Up event after SoftReboot
+ // which is the assumption for real ONU's, where the ready-state is then set according to the following MibUpload/Download
+ // for real ONU's that should have nearly no influence
+ // Note that for real ONU's there is anyway a problematic situation with following sequence:
+ // OnuIndication-Dw (or not active at all) (- disable) - enable: here already the LockFsm may run into timeout (no OmciResponse)
+ // but that anyway is hopefully resolved by some OnuIndication-Up event (maybe to be tested)
+ // one could also argue, that a device-enable should also enable attempts for specific omci configuration
+ dh.ReadyForSpecificOmciConfig = true //needed to allow subsequent flow/techProf config (on BBSIM)
+
// enable ONU/UNI ports
// *** should generate UniEnableStateDone event - used to disable the port(s) on success
if dh.pUnlockStateFsm == nil {
@@ -760,7 +768,7 @@
} else {
if err := dh.createVlanFilterFsm(uniPort, flowData.VlanRuleParams.TpID, flowData.CookieSlice,
uint16(flowData.VlanRuleParams.MatchVid), uint16(flowData.VlanRuleParams.SetVid),
- uint8(flowData.VlanRuleParams.SetPcp), OmciVlanFilterDone); err != nil {
+ uint8(flowData.VlanRuleParams.SetPcp), OmciVlanFilterAddDone); err != nil {
logger.Errorw(err.Error(), log.Fields{"device-id": dh.deviceID})
}
}
@@ -831,6 +839,7 @@
return err
}
dh.deviceReason = "rebooting"
+ dh.ReadyForSpecificOmciConfig = false
return nil
}
@@ -1327,6 +1336,7 @@
func (dh *deviceHandler) updateInterface(onuind *oop.OnuIndication) error {
//state checking to prevent unneeded processing (eg. on ONU 'unreachable' and 'down')
+ // (but note that the deviceReason may also have changed to e.g. TechProf*Delete_Success in between)
if dh.deviceReason != "stopping-openomci" {
logger.Debugw("updateInterface-started - stopping-device", log.Fields{"device-id": dh.deviceID})
//stop all running FSM processing - make use of the DH-state as mirrored in the deviceReason
@@ -1361,14 +1371,16 @@
dh.disableUniPortStateUpdate()
+ dh.deviceReason = "stopping-openomci"
+ dh.ReadyForSpecificOmciConfig = false
+
if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "stopping-openomci"); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
- logger.Errorw("error-DeviceReasonUpdate to 'stopping-openomci'",
+ logger.Errorw("error-DeviceReasonUpdate to stopping-openomci",
log.Fields{"device-id": dh.deviceID, "error": err})
// abort: system behavior is just unstable ...
return err
}
- dh.deviceReason = "stopping-openomci"
logger.Debugw("call DeviceStateUpdate upon update interface", log.Fields{"ConnectStatus": voltha.ConnectStatus_UNREACHABLE,
"OperStatus": voltha.OperStatus_DISCOVERED, "device-id": dh.deviceID})
@@ -1444,10 +1456,10 @@
//initiate DevStateUpdate
if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
- logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
+ logger.Errorw("error-DeviceReasonUpdate to mibsync-complete", log.Fields{
"device-id": dh.deviceID, "error": err})
} else {
- logger.Infow("dev reason updated to 'MibSync complete'", log.Fields{"device-id": dh.deviceID})
+ logger.Infow("dev reason updated to MibSync complete", log.Fields{"device-id": dh.deviceID})
}
} else {
logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to mibsync-complete",
@@ -1549,10 +1561,10 @@
if !dh.reconciling {
if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing
- logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
+ logger.Errorw("error-DeviceReasonUpdate to initial-mib-downloaded",
log.Fields{"device-id": dh.deviceID, "error": err})
} else {
- logger.Infow("dev reason updated to 'initial-mib-downloaded'", log.Fields{"device-id": dh.deviceID})
+ logger.Infow("dev reason updated to initial-mib-downloaded", log.Fields{"device-id": dh.deviceID})
}
} else {
logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to initial-mib-downloaded",
@@ -1560,6 +1572,7 @@
}
//set internal state anyway - as it was done
dh.deviceReason = "initial-mib-downloaded"
+ dh.ReadyForSpecificOmciConfig = true
// *** should generate UniUnlockStateDone event *****
if dh.pUnlockStateFsm == nil {
dh.createUniLockFsm(false, UniUnlockStateDone)
@@ -1593,7 +1606,7 @@
logger.Errorw("error-updating-device-state", log.Fields{"device-id": dh.deviceID, "error": err})
}
- logger.Debugw("DeviceReasonUpdate upon re-enable", log.Fields{
+ logger.Debugw("DeviceReasonUpdate upon disable", log.Fields{
"reason": "omci-admin-lock", "device-id": dh.deviceID})
// DeviceReason to update acc.to modified py code as per beginning of Sept 2020
if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
@@ -1604,14 +1617,6 @@
//transfer the modified logical uni port state
dh.disableUniPortStateUpdate()
-
- //stop the device entry which resets the attached omciCC
- pDevEntry := dh.getOnuDeviceEntry(false)
- if pDevEntry == nil {
- logger.Errorw("No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
- return
- }
- _ = pDevEntry.stop(context.TODO(), true) //stop deviceEntry with omciCC reset
}
func (dh *deviceHandler) processUniEnableStateDoneEvent(devEvent OnuDeviceEvent) {
@@ -1637,59 +1642,92 @@
}
func (dh *deviceHandler) processOmciAniConfigDoneEvent(devEvent OnuDeviceEvent) {
- logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
- // attention: the device reason update is done based on ONU-UNI-Port related activity
- // - which may cause some inconsistency
- if dh.deviceReason != "tech-profile-config-download-success" {
- // which may be the case from some previous actvity on another UNI Port of the ONU
- if !dh.reconciling {
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
- //TODO with VOL-3045/VOL-3046: return the error and stop further processing
- logger.Errorw("error-DeviceReasonUpdate to 'tech-profile-config-download-success'",
- log.Fields{"device-id": dh.deviceID, "error": err})
+ if devEvent == OmciAniConfigDone {
+ logger.Debugw("OmciAniConfigDone event received", log.Fields{"device-id": dh.deviceID})
+ // attention: the device reason update is done based on ONU-UNI-Port related activity
+ // - which may cause some inconsistency
+ if dh.deviceReason != "tech-profile-config-download-success" {
+ // which may be the case from some previous actvity even on this UNI Port (but also other UNI ports)
+ if !dh.reconciling {
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-download-success"); err != nil {
+ //TODO with VOL-3045/VOL-3046: return the error and stop further processing
+ logger.Errorw("error-DeviceReasonUpdate to tech-profile-config-download-success",
+ log.Fields{"device-id": dh.deviceID, "error": err})
+ } else {
+ logger.Infow("update dev reason to tech-profile-config-download-success",
+ log.Fields{"device-id": dh.deviceID})
+ }
} else {
- logger.Infow("update dev reason to 'tech-profile-config-download-success'",
+ logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
log.Fields{"device-id": dh.deviceID})
}
- } else {
- logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to tech-profile-config-download-success",
- log.Fields{"device-id": dh.deviceID})
+ //set internal state anyway - as it was done
+ dh.deviceReason = "tech-profile-config-download-success"
}
- //set internal state anyway - as it was done
- dh.deviceReason = "tech-profile-config-download-success"
- }
- if dh.reconciling {
- go dh.reconcileDeviceFlowConfig()
+ if dh.reconciling {
+ go dh.reconcileDeviceFlowConfig()
+ }
+ } else { // should be the OmciAniResourceRemoved block
+ logger.Debugw("OmciAniResourceRemoved event received", log.Fields{"device-id": dh.deviceID})
+ // attention: the device reason update is done based on ONU-UNI-Port related activity
+ // - which may cause some inconsistency
+ if dh.deviceReason != "tech-profile-config-delete-success" {
+ // which may be the case from some previous actvity even on this ONU port (but also other UNI ports)
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "tech-profile-config-delete-success"); err != nil {
+ //TODO with VOL-3045/VOL-3046: return the error and stop further processing
+ logger.Errorw("error-DeviceReasonUpdate to tech-profile-config-delete-success",
+ log.Fields{"device-id": dh.deviceID, "error": err})
+ } else {
+ logger.Infow("update dev reason to tech-profile-config-delete-success",
+ log.Fields{"device-id": dh.deviceID})
+ }
+ //set internal state anyway - as it was done
+ dh.deviceReason = "tech-profile-config-delete-success"
+ }
}
}
-func (dh *deviceHandler) processOmciVlanFilterDoneEvent(devEvent OnuDeviceEvent) {
+func (dh *deviceHandler) processOmciVlanFilterDoneEvent(aDevEvent OnuDeviceEvent) {
logger.Debugw("OmciVlanFilterDone event received",
- log.Fields{"device-id": dh.deviceID})
+ log.Fields{"device-id": dh.deviceID, "event": aDevEvent})
// attention: the device reason update is done based on ONU-UNI-Port related activity
// - which may cause some inconsistency
- // yield self.core_proxy.device_reason_update(self.device_id, 'omci-flows-pushed')
- if dh.deviceReason != "omci-flows-pushed" {
- // which may be the case from some previous actvity on another UNI Port of the ONU
- // or even some previous flow add activity on the same port
- if !dh.reconciling {
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
- logger.Errorw("error-DeviceReasonUpdate to 'omci-flows-pushed'",
- log.Fields{"device-id": dh.deviceID, "error": err})
+ if aDevEvent == OmciVlanFilterAddDone {
+ if dh.deviceReason != "omci-flows-pushed" {
+ // which may be the case from some previous actvity on another UNI Port of the ONU
+ // or even some previous flow add activity on the same port
+ if !dh.reconciling {
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-pushed"); err != nil {
+ logger.Errorw("error-DeviceReasonUpdate to omci-flows-pushed",
+ log.Fields{"device-id": dh.deviceID, "error": err})
+ } else {
+ logger.Infow("updated dev reason to omci-flows-pushed",
+ log.Fields{"device-id": dh.deviceID})
+ }
} else {
- logger.Infow("updated dev reason to ''omci-flows-pushed'",
+ logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to omci-flows-pushed",
log.Fields{"device-id": dh.deviceID})
}
- } else {
- logger.Debugw("reconciling - don't notify core about DeviceReasonUpdate to omci-flows-pushed",
- log.Fields{"device-id": dh.deviceID})
- }
- //set internal state anyway - as it was done
- dh.deviceReason = "omci-flows-pushed"
+ //set internal state anyway - as it was done
+ dh.deviceReason = "omci-flows-pushed"
- if dh.reconciling {
- go dh.reconcileMetrics()
+ if dh.reconciling {
+ go dh.reconcileMetrics()
+ }
+ }
+ } else {
+ if dh.deviceReason != "omci-flows-deleted" {
+ //not relevant for reconcile
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-flows-deleted"); err != nil {
+ logger.Errorw("error-DeviceReasonUpdate to omci-flows-deleted",
+ log.Fields{"device-id": dh.deviceID, "error": err})
+ } else {
+ logger.Infow("updated dev reason to omci-flows-deleted",
+ log.Fields{"device-id": dh.deviceID})
+ }
+ //set internal state anyway - as it was done
+ dh.deviceReason = "omci-flows-deleted"
}
}
}
@@ -1704,32 +1742,26 @@
case MibDownloadDone:
{
dh.processMibDownloadDoneEvent(devEvent)
-
}
case UniUnlockStateDone:
{
dh.processUniUnlockStateDoneEvent(devEvent)
-
}
case UniEnableStateDone:
{
dh.processUniEnableStateDoneEvent(devEvent)
-
}
case UniDisableStateDone:
{
dh.processUniDisableStateDoneEvent(devEvent)
-
}
- case OmciAniConfigDone:
+ case OmciAniConfigDone, OmciAniResourceRemoved:
{
dh.processOmciAniConfigDoneEvent(devEvent)
-
}
- case OmciVlanFilterDone:
+ case OmciVlanFilterAddDone, OmciVlanFilterRemDone:
{
dh.processOmciVlanFilterDoneEvent(devEvent)
-
}
default:
{
@@ -2124,7 +2156,7 @@
loMatchVlan, loSetVlan, loSetPcp)
}
return dh.createVlanFilterFsm(apUniPort, loTpID, loCookieSlice,
- loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterDone)
+ loMatchVlan, loSetVlan, loSetPcp, OmciVlanFilterAddDone)
}
//removeFlowItemFromUniPort parses the actual flow item to remove it from the UniPort
@@ -2136,7 +2168,7 @@
// at flow creation is not assured, that the same cookie is not configured for different flows - just assumed
//additionally it is assumed here, that removal can only be done for one cookie per flow in a sequence (different
// from addFlow - where at reconcilement multiple cookies per flow ) can be configured in one sequence)
- // - some possible 'delete-all' sequence would have be implemented separately (where the cookies are don't care anyway)
+ // - some possible 'delete-all' sequence would have to be implemented separately (where the cookies are don't care anyway)
loCookie := apFlowItem.GetCookie()
logger.Debugw("flow-remove base indications", log.Fields{"device-id": dh.deviceID, "cookie": loCookie})
@@ -2159,9 +2191,12 @@
if _, exist := dh.UniVlanConfigFsmMap[apUniPort.uniID]; exist {
return dh.UniVlanConfigFsmMap[apUniPort.uniID].RemoveUniFlowParams(loCookie)
}
- logger.Warnw("flow-remove called, but no flow is configured (no VlanConfigFsm)",
+ logger.Debugw("flow-remove called, but no flow is configured (no VlanConfigFsm, flow already removed) ",
log.Fields{"device-id": dh.deviceID})
//but as we regard the flow as not existing = removed we respond just ok
+ // and treat the reason accordingly (which in the normal removal procedure is initiated by the FSM)
+ go dh.deviceProcStatusUpdate(OmciVlanFilterRemDone)
+
return nil
}
@@ -2210,6 +2245,26 @@
return nil
}
+//VerifyVlanConfigRequest checks on existence of a given uniPort
+// and starts verification of flow config based on that
+func (dh *deviceHandler) VerifyVlanConfigRequest(aUniID uint8) {
+ //ensure that the given uniID is available (configured) in the UniPort class (used for OMCI entities)
+ var pCurrentUniPort *onuUniPort
+ for _, uniPort := range dh.uniEntityMap {
+ // only if this port is validated for operState transfer
+ if uniPort.uniID == uint8(aUniID) {
+ pCurrentUniPort = uniPort
+ break //found - end search loop
+ }
+ }
+ if pCurrentUniPort == nil {
+ logger.Debugw("VerifyVlanConfig aborted: requested uniID not found in PortDB",
+ log.Fields{"device-id": dh.deviceID, "uni-id": aUniID})
+ return
+ }
+ dh.verifyUniVlanConfigRequest(pCurrentUniPort)
+}
+
//verifyUniVlanConfigRequest checks on existence of flow configuration and starts it accordingly
func (dh *deviceHandler) verifyUniVlanConfigRequest(apUniPort *onuUniPort) {
//TODO!! verify and start pending flow configuration
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index 70f172a..4c5f22f 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -552,30 +552,32 @@
return
}
logger.Debugw("CreateResponse Data", log.Fields{"device-id": oFsm.deviceID, "data-fields": msgObj})
- if msgObj.Result != me.Success {
+ if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
+ //if the result is ok or Instance already exists (latest needed at least as long as we do not clear the OMCI techProfile data)
+ if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
+ // maybe we can use just the same eventName for different state transitions like "forward"
+ // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
+ switch oFsm.pLastTxMeInstance.GetName() {
+ case "Ieee8021PMapperServiceProfile":
+ { // let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
+ }
+ case "MacBridgePortConfigurationData":
+ { // let the FSM proceed ...
+ _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
+ }
+ case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
+ { // let aniConfig Multi-Id processing proceed by stopping the wait function
+ oFsm.omciMIdsResponseReceived <- true
+ }
+ }
+ }
+ } else {
logger.Errorw("Omci CreateResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
return
}
- if msgObj.EntityClass == oFsm.pLastTxMeInstance.GetClassID() &&
- msgObj.EntityInstance == oFsm.pLastTxMeInstance.GetEntityID() {
- // maybe we can use just the same eventName for different state transitions like "forward"
- // - might be checked, but so far I go for sure and have to inspect the concrete state events ...
- switch oFsm.pLastTxMeInstance.GetName() {
- case "Ieee8021PMapperServiceProfile":
- { // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxDot1pmapCResp)
- }
- case "MacBridgePortConfigurationData":
- { // let the FSM proceed ...
- _ = oFsm.pAdaptFsm.pFsm.Event(aniEvRxMbpcdResp)
- }
- case "GemPortNetworkCtp", "GemInterworkingTerminationPoint":
- { // let aniConfig Multi-Id processing proceed by stopping the wait function
- oFsm.omciMIdsResponseReceived <- true
- }
- }
- }
}
func (oFsm *uniPonAniConfigFsm) handleOmciAniConfigSetResponseMessage(msg OmciMessage) {
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 7b10d12..f53479f 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -1656,6 +1656,7 @@
return nil
}
+// nolint: unused
func (oo *omciCC) sendCreateMulticastGemIWTPVar(ctx context.Context, timeout int, highPrio bool,
rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
tid := oo.getNextTid(highPrio)
@@ -1694,6 +1695,7 @@
return nil
}
+// nolint: unused
func (oo *omciCC) sendCreateMulticastOperationProfileVar(ctx context.Context, timeout int, highPrio bool,
rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
tid := oo.getNextTid(highPrio)
@@ -1735,6 +1737,7 @@
return nil
}
+// nolint: unused
func (oo *omciCC) sendSetMulticastOperationProfileVar(ctx context.Context, timeout int, highPrio bool,
rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
tid := oo.getNextTid(highPrio)
@@ -1776,6 +1779,7 @@
return nil
}
+// nolint: unused
func (oo *omciCC) sendCreateMulticastSubConfigInfoVar(ctx context.Context, timeout int, highPrio bool,
rxChan chan Message, params ...me.ParamData) *me.ManagedEntity {
tid := oo.getNextTid(highPrio)
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)
}
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 27c0865..ad683b0 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -118,29 +118,33 @@
// Events of interest to Device Adapters and OpenOMCI State Machines
// DeviceStatusInit - default start state
- DeviceStatusInit OnuDeviceEvent = 0
+ DeviceStatusInit OnuDeviceEvent = iota
// MibDatabaseSync - MIB database sync (upload done)
- MibDatabaseSync OnuDeviceEvent = 1
+ MibDatabaseSync
// OmciCapabilitiesDone - OMCI ME and message type capabilities known
- OmciCapabilitiesDone OnuDeviceEvent = 2
+ OmciCapabilitiesDone
// MibDownloadDone - // MIB download done
- MibDownloadDone OnuDeviceEvent = 3
+ MibDownloadDone
// UniLockStateDone - Uni ports admin set to lock
- UniLockStateDone OnuDeviceEvent = 4
+ UniLockStateDone
// UniUnlockStateDone - Uni ports admin set to unlock
- UniUnlockStateDone OnuDeviceEvent = 5
+ UniUnlockStateDone
// UniDisableStateDone - Uni ports admin set to lock based on device disable
- UniDisableStateDone OnuDeviceEvent = 6
+ UniDisableStateDone
// UniEnableStateDone - Uni ports admin set to unlock based on device re-enable
- UniEnableStateDone OnuDeviceEvent = 7
+ UniEnableStateDone
// PortLinkUp - Port link state change
- PortLinkUp OnuDeviceEvent = 8
+ PortLinkUp
// PortLinkDw - Port link state change
- PortLinkDw OnuDeviceEvent = 9
+ PortLinkDw
// OmciAniConfigDone - AniSide config according to TechProfile done
- OmciAniConfigDone OnuDeviceEvent = 10
- // OmciVlanFilterDone - Omci Vlan config according to flowConfig done
- OmciVlanFilterDone OnuDeviceEvent = 11
+ OmciAniConfigDone
+ // OmciAniResourceRemoved - AniSide TechProfile related resource (Gem/TCont) removed
+ OmciAniResourceRemoved // needs to be the successor of OmciAniConfigDone!
+ // OmciVlanFilterAddDone - Omci Vlan config done according to flow-add
+ OmciVlanFilterAddDone
+ // OmciVlanFilterRemDone - Omci Vlan config done according to flow-remove
+ OmciVlanFilterRemDone // needs to be the successor of OmciVlanFilterAddDone!
// Add other events here as needed (alarms separate???)
)
@@ -646,8 +650,28 @@
return true
}
//entry already exists
- logger.Debugw("UniTp path already exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
- return false
+ if aPathString == "" {
+ //no active TechProfile
+ logger.Debugw("UniTp path has already been removed - no AniSide config to be removed", log.Fields{
+ "device-id": oo.deviceID, "uniID": aUniID})
+ // attention 201105: this block is at the moment entered for each of subsequent GemPortDeletes and TContDelete
+ // as the path is already cleared with the first GemPort - this will probably change with the upcoming real
+ // TechProfile removal (still TODO), but anyway the reasonUpdate initiated here should not harm overall behavior
+ go oo.baseDeviceHandler.deviceProcStatusUpdate(OmciAniResourceRemoved)
+ // no flow config pending on 'remove' so far
+ } else {
+ //the given TechProfile already exists and is assumed to be active - update devReason as if the config has been done here
+ //was needed e.g. in voltha POD Tests:Validate authentication on a disabled ONU
+ // (as here the TechProfile has not been removed with the disable-device before the new enable-device)
+ logger.Debugw("UniTp path already exists - TechProfile supposed to be active", log.Fields{
+ "device-id": oo.deviceID, "uniID": aUniID, "path": aPathString})
+ //no deviceReason update (deviceProcStatusUpdate) here to ensure 'omci_flows_pushed' state within disable/enable procedure of ATT scenario
+ // (during which the flows are removed/re-assigned but the techProf is left active)
+ //and as the TechProfile is regarded as active we have to verify, if some flow configuration still waits on it
+ // (should not be the case, but should not harm or be more robust ...)
+ go oo.baseDeviceHandler.VerifyVlanConfigRequest(aUniID)
+ }
+ return false //indicate 'no change' - nothing more to do, TechProf inter-adapter message is return with success anyway here
}
}
//no entry exists for uniId
@@ -664,25 +688,6 @@
return true
}
-// deleteTpResource removes Resources from the ONU's specified Uni
-func (oo *OnuDeviceEntry) deleteTpResource(ctx context.Context,
- aUniID uint8, aPathString string, aResource resourceEntry, aEntryID uint32,
- wg *sync.WaitGroup) {
- defer wg.Done()
- logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
- "device-id": oo.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
- //TODO!!!
- //delete the given resource from ONU OMCI config and data base - as background routine
- /*
- var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
- go onuTp.deleteAniResource(ctx, processingStep)
- if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
- //timeout or error detected
- return
- }
- */
-}
-
func (oo *OnuDeviceEntry) updateOnuUniFlowConfig(aUniID uint8, aUniVlanFlowParams *[]uniVlanFlowParams) {
for k, v := range oo.sOnuPersistentData.PersUniConfig {
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index e052684..97b4dbd 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -474,6 +474,45 @@
}
}
+// deleteTpResource removes Resources from the ONU's specified Uni
+func (onuTP *onuUniTechProf) deleteTpResource(ctx context.Context,
+ aUniID uint8, aPathString string, aResource resourceEntry, aEntryID uint32,
+ wg *sync.WaitGroup) {
+ defer wg.Done()
+ logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
+ "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
+ if cResourceTcont == aResource {
+ //the TechProfile indicated by path is considered for removal
+ // by now we do not clear the OMCI related configuration (to be done later)
+ // so we use this position here just to remove the internal stored profile data
+ // (needed for checking the existence of the TechProfile after some profile delete)
+ // at the oment we only admit 1 TechProfile (T-Cont), so by now we can just remove the only existing TechProfile
+ // TODO: To be updated with multi-T-Cont implementation
+ logger.Debugw("DeleteTcont clears the existing internal profile", log.Fields{
+ "device-id": onuTP.deviceID, "uniID": aUniID, "path": aPathString, "Resource": aResource})
+ onuTP.clearAniSideConfig(aUniID)
+ // reset also the FSM in order to admit a new OMCI configuration in case a new profile is created
+ // FSM stop maybe encapsulated as OnuTP method - perhaps later in context of module splitting
+ if onuTP.pAniConfigFsm != nil {
+ _ = onuTP.pAniConfigFsm.pAdaptFsm.pFsm.Event(aniEvReset)
+ }
+
+ //TODO!!! - the real processing could look like that (for starting the removal, where the clearAniSideConfig is done implicitly):
+ //delete the given resource from ONU OMCI config and data base - as background routine
+ /*
+ var processingStep uint8 = 1 // used to synchronize the different processing steps with chTpConfigProcessingStep
+ go onuTp.deleteAniResource(ctx, processingStep)
+ if !onuTP.waitForTimeoutOrCompletion(ctx, chTpConfigProcessingStep, processingStep) {
+ //timeout or error detected
+ return
+ }
+ */
+ }
+ //if implemented, the called FSM would generate an adequate event if config has been done,
+ // by now we just stimulate this event here as 'done' - TODO!!: to be removed after full implementation
+ go onuTP.baseDeviceHandler.deviceProcStatusUpdate(OmciAniResourceRemoved)
+}
+
// runAniConfigFsm starts the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
func (onuTP *onuUniTechProf) runAniConfigFsm(aProcessingStep uint8) {
/* Uni related ANI config procedure -
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index 7056cd7..2d1ea5a 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -315,34 +315,28 @@
//Update_flows_incrementally updates (add/remove) the flows on a given device
func (oo *OpenONUAC) Update_flows_incrementally(device *voltha.Device,
flows *openflow_13.FlowChanges, groups *openflow_13.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
- // no point in pushing omci flows if the device isn't reachable
- if device.ConnectStatus != voltha.ConnectStatus_REACHABLE ||
- device.AdminState != voltha.AdminState_ENABLED {
- logger.Warnw("device disabled or offline - skipping flow-update", log.Fields{"ConnectStatus": device.ConnectStatus,
- "AdminState": device.AdminState, "deviceId": device.Id})
- return fmt.Errorf("non-matching device state: %s", device.Id)
- //TODO!!: verify if some flow delete activity as observed in BBSIM tests after ONU-down indication
- // has some system impact on general behavior after ONU up again (as no flow is really removed here)
- // but it may only be related to following device_delete, which anyway should clear up all stuff
- // (testing needed with new device-enable [after device-delete] ...)
- }
+
+ //flow config is relayed to handler even if the device might be in some 'inactive' state
+ // let the handler or related FSM's decide, what to do with the modified flow state info
+ // at least the flow-remove must be done in respect to internal data, while OMCI activity might not be needed here
// For now, there is no support for group changes (as in the actual Py-adapter code)
+ // but processing is continued for flowUpdate possibly also set in the request
if groups.ToAdd != nil && groups.ToAdd.Items != nil {
- logger.Debugw("Update-flow-incr: group add not supported (ignored)", log.Fields{"deviceId": device.Id})
+ logger.Warnw("Update-flow-incr: group add not supported (ignored)", log.Fields{"device-id": device.Id})
}
if groups.ToRemove != nil && groups.ToRemove.Items != nil {
- logger.Debugw("Update-flow-incr: group remove not supported (ignored)", log.Fields{"deviceId": device.Id})
+ logger.Warnw("Update-flow-incr: group remove not supported (ignored)", log.Fields{"device-id": device.Id})
}
if groups.ToUpdate != nil && groups.ToUpdate.Items != nil {
- logger.Debugw("Update-flow-incr: group update not supported (ignored)", log.Fields{"deviceId": device.Id})
+ logger.Warnw("Update-flow-incr: group update not supported (ignored)", log.Fields{"device-id": device.Id})
}
if handler := oo.getDeviceHandler(device.Id); handler != nil {
err := handler.FlowUpdateIncremental(flows, groups, flowMetadata)
return err
}
- logger.Warnw("no handler found for incremental flow update", log.Fields{"deviceId": device.Id})
+ logger.Warnw("no handler found for incremental flow update", log.Fields{"device-id": device.Id})
return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
}