[VOL-4553] openonuAdapterGo - reconciling with wrong MDS is not working in TT multi-UNI scenario
Change-Id: I3a49d3560c942168fbac53e0c503abfea785be23
diff --git a/internal/pkg/avcfg/omci_vlan_config.go b/internal/pkg/avcfg/omci_vlan_config.go
index 3194242..668d2c6 100755
--- a/internal/pkg/avcfg/omci_vlan_config.go
+++ b/internal/pkg/avcfg/omci_vlan_config.go
@@ -1327,15 +1327,15 @@
}(pConfigVlanStateBaseFsm)
return
}
+ if oFsm.lastFlowToReconcile {
+ //note: lastFlowToReconcile does not mean that this block may run only once within reconcilement here,
+ // due to asynchronous event processing from SetUniFlowParams() it may be executed multiple times
+ logger.Debugw(ctx, "reconciling - flow processing finished", log.Fields{
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.UniID})
+ oFsm.pDeviceHandler.SendChUniVlanConfigFinished(uint16(oFsm.pOnuUniPort.UniID))
+ }
if oFsm.pDeviceHandler.IsSkipOnuConfigReconciling() {
oFsm.ConfiguredUniFlow = oFsm.NumUniFlows
- if oFsm.lastFlowToReconcile {
- //note: lastFlowToReconcile does not mean that this block may run only once within reconcilement here,
- // due to asynchronous event processing from SetUniFlowParams() it may be executed multiple times
- logger.Debugw(ctx, "reconciling - flow processing finished", log.Fields{
- "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.UniID})
- oFsm.pDeviceHandler.SendChUniVlanConfigFinished(uint16(oFsm.pOnuUniPort.UniID))
- }
logger.Debugw(ctx, "reconciling - skip enterVlanConfigDone processing",
log.Fields{"NumUniFlows": oFsm.NumUniFlows, "ConfiguredUniFlow": oFsm.ConfiguredUniFlow, "device-id": oFsm.deviceID})
oFsm.mutexFlowParams.Unlock()
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index fb6d1ff..f74da5a 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -205,6 +205,8 @@
upgradeCanceled bool
reconciling uint8
mutexReconcilingFlag sync.RWMutex
+ reconcilingFirstPass bool
+ mutexReconcilingFirstPassFlag sync.RWMutex
reconcilingReasonUpdate bool
mutexReconcilingReasonUpdate sync.RWMutex
chUniVlanConfigReconcilingDone chan uint16 //channel to indicate that VlanConfig reconciling for a specific UNI has been finished
@@ -253,6 +255,7 @@
dh.UniVlanConfigFsmMap = make(map[uint8]*avcfg.UniVlanConfigFsm)
dh.reconciling = cNoReconciling
dh.reconcilingReasonUpdate = false
+ dh.reconcilingFirstPass = true
dh.chReconcilingFinished = make(chan bool)
dh.reconcileExpiryComplete = adapter.maxTimeoutReconciling //assumption is to have it as duration in s!
rECSeconds := int(dh.reconcileExpiryComplete / time.Second)
@@ -1042,30 +1045,25 @@
dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
return
}
-
- if dh.IsSkipOnuConfigReconciling() {
- //only with 'SkipOnuConfig' we need to wait for all finished-signals
- // from vlanConfig processing of all UNI's.
- logger.Debugw(ctx, "reconciling flows - waiting on ready indication of requested UNIs", log.Fields{
- "device-id": dh.DeviceID, "expiry": dh.reconcileExpiryVlanConfig})
- if executed := loWaitGroupWTO.WaitTimeout(dh.reconcileExpiryVlanConfig); executed {
- logger.Debugw(ctx, "reconciling flows for all UNI's has been finished in time",
- log.Fields{"device-id": dh.DeviceID})
- dh.stopReconciling(ctx, true, cWaitReconcileFlowAbortOnSuccess)
- if pDevEntry != nil {
- pDevEntry.SendChReconcilingFlowsFinished(ctx, true)
- }
- } else {
- logger.Errorw(ctx, "reconciling - timeout waiting for reconciling flows for all UNI's to be finished!",
- log.Fields{"device-id": dh.DeviceID})
- dh.stopReconciling(ctx, false, cWaitReconcileFlowAbortOnError)
- if pDevEntry != nil {
- pDevEntry.SendChReconcilingFlowsFinished(ctx, false)
- }
- return
+ logger.Debugw(ctx, "reconciling flows - waiting on ready indication of requested UNIs", log.Fields{
+ "device-id": dh.DeviceID, "expiry": dh.reconcileExpiryVlanConfig})
+ if executed := loWaitGroupWTO.WaitTimeout(dh.reconcileExpiryVlanConfig); executed {
+ logger.Debugw(ctx, "reconciling flows for all UNI's has been finished in time",
+ log.Fields{"device-id": dh.DeviceID})
+ dh.stopReconciling(ctx, true, cWaitReconcileFlowAbortOnSuccess)
+ if pDevEntry != nil {
+ pDevEntry.SendChReconcilingFlowsFinished(ctx, true)
}
- _ = dh.ReasonUpdate(ctx, cmn.DrOmciFlowsPushed, dh.IsReconcilingReasonUpdate())
+ } else {
+ logger.Errorw(ctx, "reconciling - timeout waiting for reconciling flows for all UNI's to be finished!",
+ log.Fields{"device-id": dh.DeviceID})
+ dh.stopReconciling(ctx, false, cWaitReconcileFlowAbortOnError)
+ if pDevEntry != nil {
+ pDevEntry.SendChReconcilingFlowsFinished(ctx, false)
+ }
+ return
}
+ _ = dh.ReasonUpdate(ctx, cmn.DrOmciFlowsPushed, dh.IsReconcilingReasonUpdate())
}
func (dh *deviceHandler) updateReconcileFlowConfig(ctx context.Context, apUniPort *cmn.OnuUniPort,
@@ -1075,28 +1073,24 @@
lastFlowToReconcile := false
loUniID := apUniPort.UniID
for _, flowData := range aPersFlowParam {
- if dh.IsSkipOnuConfigReconciling() {
- if !(*apFlowsFound) {
- *apFlowsFound = true
- syncChannel := make(chan struct{})
- // start go routine with select() on reconciling vlan config channel before
- // starting vlan config reconciling process to prevent loss of any signal
- // this routine just collects all the received 'flow-reconciled' signals - possibly from different UNI's
- go dh.waitOnUniVlanConfigReconcilingReady(ctx, syncChannel, apWaitGroup)
- //block until the wait routine is really blocked on channel input
- // in order to prevent to early ready signal from VlanConfig processing
- <-syncChannel
- }
- if flowsProcessed == len(aPersFlowParam)-1 {
- var uniAdded bool
- lastFlowToReconcile = true
- if aUniVlanConfigEntries, uniAdded = dh.appendIfMissing(aUniVlanConfigEntries, loUniID); uniAdded {
- apWaitGroup.Add(1) //increment the waiting group
- }
+ if !(*apFlowsFound) {
+ *apFlowsFound = true
+ syncChannel := make(chan struct{})
+ // start go routine with select() on reconciling vlan config channel before
+ // starting vlan config reconciling process to prevent loss of any signal
+ // this routine just collects all the received 'flow-reconciled' signals - possibly from different UNI's
+ go dh.waitOnUniVlanConfigReconcilingReady(ctx, syncChannel, apWaitGroup)
+ //block until the wait routine is really blocked on channel input
+ // in order to prevent to early ready signal from VlanConfig processing
+ <-syncChannel
+ }
+ if flowsProcessed == len(aPersFlowParam)-1 {
+ var uniAdded bool
+ lastFlowToReconcile = true
+ if aUniVlanConfigEntries, uniAdded = dh.appendIfMissing(aUniVlanConfigEntries, loUniID); uniAdded {
+ apWaitGroup.Add(1) //increment the waiting group
}
}
- // note for above block: also lastFlowToReconcile (as parameter to flow config below)
- // is only relevant in the vlanConfig processing for IsSkipOnuConfigReconciling = true
logger.Debugw(ctx, "reconciling - add flow with cookie slice", log.Fields{
"device-id": dh.DeviceID, "uni-id": loUniID,
"flowsProcessed": flowsProcessed, "cookies": flowData.CookieSlice})
@@ -1205,11 +1199,6 @@
}
}
-func (dh *deviceHandler) reconcileEnd(ctx context.Context) {
- logger.Debugw(ctx, "reconciling - completed!", log.Fields{"device-id": dh.DeviceID})
- dh.stopReconciling(ctx, true, cWaitReconcileFlowNoActivity)
-}
-
func (dh *deviceHandler) deleteDevicePersistencyData(ctx context.Context) error {
logger.Debugw(ctx, "delete device persistency data", log.Fields{"device-id": dh.DeviceID})
@@ -2408,7 +2397,7 @@
pDevEntry.MutexPersOnuConfig.RUnlock()
logger.Debugw(ctx, "reconciling - uni-ports were disabled by admin before adapter restart - keep the ports locked",
log.Fields{"device-id": dh.DeviceID})
- go dh.ReconcileDeviceTechProf(ctx)
+ dh.ReconcileDeviceTechProf(ctx)
// reconcilement will be continued after ani config is done
} else {
pDevEntry.MutexPersOnuConfig.RUnlock()
@@ -2444,7 +2433,7 @@
} else {
logger.Debugw(ctx, "reconciling - don't notify core that onu went to active but trigger tech profile config",
log.Fields{"device-id": dh.DeviceID})
- go dh.ReconcileDeviceTechProf(ctx)
+ dh.ReconcileDeviceTechProf(ctx)
// reconcilement will be continued after ani config is done
}
}
@@ -2540,7 +2529,15 @@
_ = dh.ReasonUpdate(ctx, cmn.DrTechProfileConfigDownloadSuccess, !dh.IsReconciling() || dh.IsReconcilingReasonUpdate())
}
if dh.IsReconciling() {
- go dh.ReconcileDeviceFlowConfig(ctx)
+ // during reconciling with OMCI configuration in TT multi-UNI scenario, OmciAniConfigDone is reached several times
+ // therefore it must be ensured that reconciling of flow config is only started on the first pass of this code position
+ dh.mutexReconcilingFirstPassFlag.Lock()
+ if dh.reconcilingFirstPass {
+ logger.Debugw(ctx, "reconciling - OmciAniConfigDone first pass, start flow processing", log.Fields{"device-id": dh.DeviceID})
+ dh.reconcilingFirstPass = false
+ go dh.ReconcileDeviceFlowConfig(ctx)
+ }
+ dh.mutexReconcilingFirstPassFlag.Unlock()
}
} else { // should be the OmciAniResourceRemoved block
logger.Debugw(ctx, "OmciAniResourceRemoved event received", log.Fields{"device-id": dh.DeviceID})
@@ -2564,9 +2561,6 @@
// which may be the case from some previous activity on another UNI Port of the ONU
// or even some previous flow add activity on the same port
_ = dh.ReasonUpdate(ctx, cmn.DrOmciFlowsPushed, !dh.IsReconciling() || dh.IsReconcilingReasonUpdate())
- if dh.IsReconciling() {
- go dh.reconcileEnd(ctx)
- }
}
} else {
if dh.getDeviceReason() != cmn.DrOmciFlowsDeleted {
@@ -4066,6 +4060,7 @@
dh.reconciling = cNoReconciling
dh.mutexReconcilingFlag.Unlock()
dh.SetReconcilingReasonUpdate(false)
+ dh.SetReconcilingFirstPass(true)
if onuDevEntry := dh.GetOnuDeviceEntry(ctx, true); onuDevEntry == nil {
logger.Errorw(ctx, "No valid OnuDevice", log.Fields{"device-id": dh.DeviceID})
@@ -4109,6 +4104,12 @@
return dh.reconciling == cSkipOnuConfigReconciling
}
+func (dh *deviceHandler) SetReconcilingFirstPass(value bool) {
+ dh.mutexReconcilingFirstPassFlag.Lock()
+ dh.reconcilingFirstPass = value
+ dh.mutexReconcilingFirstPassFlag.Unlock()
+}
+
func (dh *deviceHandler) SetReconcilingReasonUpdate(value bool) {
dh.mutexReconcilingReasonUpdate.Lock()
dh.reconcilingReasonUpdate = value