[VOL-4796] openonuAdapterGo: Robustness - verification/correlation of ONU capabilities against configuration requirements
BBSIM mib templates adapted to the increased number of UpstreamPriorityQueues reported during BBSIM mibUpload (patch https://gerrit.opencord.org/c/bbsim/+/33457).
Change-Id: I752986335df99b6d5d5de9423ae25dcbfd828229
diff --git a/VERSION b/VERSION
index 005119b..437459c 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.1
+2.5.0
diff --git a/internal/pkg/avcfg/omci_ani_config.go b/internal/pkg/avcfg/omci_ani_config.go
index ca5e605..f1c838f 100755
--- a/internal/pkg/avcfg/omci_ani_config.go
+++ b/internal/pkg/avcfg/omci_ani_config.go
@@ -386,7 +386,7 @@
// MibDb usage: downstream PrioQueue.RelatedPort = xxyyzzzz with xx=slot, yy=UniPort and zzzz=prio
// i.e.: search PrioQueue list with yy=actual pOnuUniPort.UniID,
// from that list use the PrioQueue.Entity with gemEntry.prioQueueIndex == zzzz (expect 0..7)
- // Note: As we do not maintain any slot numbering, slot number will be excluded from seatch pattern.
+ // Note: As we do not maintain any slot numbering, slot number will be excluded from search pattern.
// Furthermore OMCI Onu port-Id is expected to start with 1 (not 0).
dsQrelPortMask := uint32((((uint32)(oFsm.pOnuUniPort.UniID + 1)) << 16) + uint32(gemEntry.prioQueueIndex))
diff --git a/internal/pkg/avcfg/onu_uni_tp.go b/internal/pkg/avcfg/onu_uni_tp.go
index e19c301..f27cac4 100755
--- a/internal/pkg/avcfg/onu_uni_tp.go
+++ b/internal/pkg/avcfg/onu_uni_tp.go
@@ -38,6 +38,13 @@
//binaryBit1 = '1'
)
+//as defined in G.988
+const (
+ cGemDirUniToAni = 1
+ cGemDirAniToUni = 2
+ cGemDirBiDirect = 3
+)
+
// ResourceEntry - TODO: add comment
type ResourceEntry int
@@ -407,7 +414,7 @@
uint16(content.GemportId)
//direction can be correlated later with Downstream list,
// for now just assume bidirectional (upstream never exists alone)
- onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].direction = 3 //as defined in G.988
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[uint16(content.GemportId)].direction = cGemDirBiDirect
// expected Prio-Queue values 0..7 with 7 for highest PrioQueue, QueueIndex=Prio = 0..7
if content.PriorityQ > 7 {
logger.Errorw(ctx, "PonAniConfig reject on GemPortList - PrioQueue value invalid",
@@ -472,7 +479,7 @@
//Separate McastGemId is derived from OMCI-lib-go, if not needed first needs to be removed there.
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortID = mcastGemID
- onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].direction = 2 // for ANI to UNI as defined in G.988
+ onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].direction = cGemDirAniToUni
if downstreamContent.AesEncryption == "True" {
onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams[mcastGemID].gemPortEncState = 1
@@ -992,6 +999,30 @@
return gemPortInstIDs
}
+// GetNumberOfConfiguredUsGemPorts - provides the number of Gem ports for each UNI/TP combination
+func (onuTP *OnuUniTechProf) GetNumberOfConfiguredUsGemPorts(ctx context.Context) int {
+ onuTP.mutexTPState.RLock()
+ defer onuTP.mutexTPState.RUnlock()
+ usGemPorts := make([]uint16, 0)
+ for _, tcontGemList := range onuTP.mapPonAniConfig {
+ for gemPortID, gemPortParams := range tcontGemList.mapGemPortParams {
+ if gemPortParams.direction == cGemDirBiDirect || gemPortParams.direction == cGemDirUniToAni {
+ alreadyConfigured := false
+ for _, foundUsGemPortID := range usGemPorts {
+ if foundUsGemPortID == gemPortID {
+ alreadyConfigured = true
+ break
+ }
+ }
+ if !alreadyConfigured {
+ usGemPorts = append(usGemPorts, gemPortID)
+ }
+ }
+ }
+ }
+ return len(usGemPorts)
+}
+
// setProfileResetting sets/resets the indication, that a reset of the TechProfileConfig/Removal is ongoing
func (onuTP *OnuUniTechProf) setProfileResetting(ctx context.Context, aUniID uint8, aTpID uint8, aState bool) {
uniTpKey := uniTP{uniID: aUniID, tpID: aTpID}
diff --git a/internal/pkg/common/defines.go b/internal/pkg/common/defines.go
index 9cb4ba8..545892f 100755
--- a/internal/pkg/common/defines.go
+++ b/internal/pkg/common/defines.go
@@ -369,4 +369,10 @@
OnuOmciCommunicationAbortSwUpgrade = "ONU_OMCI_COMMUNICATION_ABORT_SW_UPGRADE"
OnuOmciCommunicationAbortSwUpgradeDesc = "OMCI communication during ONU SW upgrade aborted - max failures reached: stopping device"
+
+ OnuConfigFailureMissingTcont = "ONU_CONFIG_FAILURE_MISSING_TCONT"
+ OnuConfigFailureMissingTcontDesc = "ONU config failed - no further TCONT resources available at ONU"
+
+ OnuConfigFailureMissingUsPriorityQueue = "ONU_CONFIG_FAILURE_MISSING_US_PRIORITY_QUEUE"
+ OnuConfigFailureMissingUsPriorityQueueDesc = "ONU config failed - no further upstream PriorityQueue resources available at ONU"
)
diff --git a/internal/pkg/common/interfaces.go b/internal/pkg/common/interfaces.go
index 69fa26f..ceec3ef 100755
--- a/internal/pkg/common/interfaces.go
+++ b/internal/pkg/common/interfaces.go
@@ -178,6 +178,7 @@
// IonuUniTechProf interface to onuUniTechProf
type IonuUniTechProf interface {
GetAllBidirectionalGemPortIDsForOnu() []uint16
+ GetNumberOfConfiguredUsGemPorts(ctx context.Context) int
SetProfileToDelete(uint8, uint8, bool)
}
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 9ad2b7d..744834a 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -419,6 +419,15 @@
case *ia.TechProfileDownloadMessage_TpInstance:
logger.Debugw(ctx, "onu-uni-tp-path-modified", log.Fields{"device-id": dh.DeviceID,
"uniID": uniID, "tp-path": techProfMsg.TpInstancePath, "tpID": tpID})
+
+ err = dh.CheckAvailableOnuCapabilities(ctx, pDevEntry, *tpInst.TpInstance)
+ if err != nil {
+ logger.Errorw(ctx, "error-checking-available-onu-capabilities-stopping-device",
+ log.Fields{"device-id": dh.DeviceID, "err": err, "tp-path": techProfMsg.TpInstancePath})
+ // stopping all further processing
+ _ = dh.UpdateInterface(ctx)
+ return err
+ }
// if there has been some change for some uni TechProfilePath
//in order to allow concurrent calls to other dh instances we do not wait for execution here
//but doing so we can not indicate problems to the caller (who does what with that then?)
@@ -2752,7 +2761,7 @@
dh.chUniVlanConfigReconcilingDone = make(chan uint16, uniCnt)
for i := 0; i < int(uniCnt); i++ {
dh.flowCbChan[i] = make(chan FlowCb, dh.pOpenOnuAc.config.MaxConcurrentFlowsPerUni)
- dh.stopFlowMonitoringRoutine[i] = make(chan bool)
+ dh.stopFlowMonitoringRoutine[i] = make(chan bool, 1)
}
}
@@ -4423,6 +4432,58 @@
return err
}
+func (dh *deviceHandler) CheckAvailableOnuCapabilities(ctx context.Context, pDevEntry *mib.OnuDeviceEntry, tpInst tech_profile.TechProfileInstance) error {
+ // Check if there are additional TCONT instances necessary/available
+ pDevEntry.MutexPersOnuConfig.Lock()
+ if _, ok := pDevEntry.SOnuPersistentData.PersTcontMap[uint16(tpInst.UsScheduler.AllocId)]; !ok {
+ numberOfTcontMapEntries := len(pDevEntry.SOnuPersistentData.PersTcontMap)
+ pDevEntry.MutexPersOnuConfig.Unlock()
+ numberOfTcontDbInsts := pDevEntry.GetOnuDB().GetNumberOfInst(me.TContClassID)
+ logger.Debugw(ctx, "checking available TCONT instances",
+ log.Fields{"device-id": dh.DeviceID, "numberOfTcontMapEntries": numberOfTcontMapEntries, "numberOfTcontDbInsts": numberOfTcontDbInsts})
+ if numberOfTcontMapEntries >= numberOfTcontDbInsts {
+ logger.Errorw(ctx, "configuration exceeds ONU capabilities - running out of TCONT instances: send ONU device event!",
+ log.Fields{"device-id": dh.device.Id})
+ pDevEntry.SendOnuDeviceEvent(ctx, cmn.OnuConfigFailureMissingTcont, cmn.OnuConfigFailureMissingTcontDesc)
+ return fmt.Errorf(fmt.Sprintf("configuration exceeds ONU capabilities - running out of TCONT instances: device-id: %s", dh.DeviceID))
+ }
+ } else {
+ pDevEntry.MutexPersOnuConfig.Unlock()
+ }
+ // Check if there are enough PrioQueue instances available
+ if dh.pOnuTP != nil {
+ var numberOfUsPrioQueueDbInsts int
+
+ queueInstKeys := pDevEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PriorityQueueClassID)
+ for _, mgmtEntityID := range queueInstKeys {
+ if mgmtEntityID >= 0x8000 && mgmtEntityID <= 0xFFFF {
+ numberOfUsPrioQueueDbInsts++
+ }
+ }
+ // Check if there is an upstream PriorityQueue instance available for each Gem port
+ numberOfConfiguredGemPorts := dh.pOnuTP.GetNumberOfConfiguredUsGemPorts(ctx)
+ logger.Debugw(ctx, "checking available upstream PriorityQueue instances",
+ log.Fields{"device-id": dh.DeviceID,
+ "numberOfConfiguredGemPorts": numberOfConfiguredGemPorts,
+ "tpInst.NumGemPorts": tpInst.NumGemPorts,
+ "numberOfUsPrioQueueDbInsts": numberOfUsPrioQueueDbInsts})
+
+ if numberOfConfiguredGemPorts+int(tpInst.NumGemPorts) > numberOfUsPrioQueueDbInsts {
+ logger.Errorw(ctx, "configuration exceeds ONU capabilities - running out of upstream PrioQueue instances: send ONU device event!",
+ log.Fields{"device-id": dh.device.Id})
+ pDevEntry.SendOnuDeviceEvent(ctx, cmn.OnuConfigFailureMissingUsPriorityQueue, cmn.OnuConfigFailureMissingUsPriorityQueueDesc)
+ return fmt.Errorf(fmt.Sprintf("configuration exceeds ONU capabilities - running out of upstream PrioQueue instances: device-id: %s", dh.DeviceID))
+ }
+ // Downstream PrioQueue instances are evaluated in accordance with ONU MIB upload data in function UniPonAniConfigFsm::prepareAndEnterConfigState().
+ // In case of missing downstream PrioQueues the attribute "Priority queue pointer for downstream" of ME "GEM port network CTP" will be set to "0",
+ // which then alternatively activates the queuing mechanisms of the ONU (refer to Rec. ITU-T G.988 chapter 9.2.3).
+ } else {
+ logger.Warnw(ctx, "onuTechProf instance not set up - check for PriorityQueue instances skipped!",
+ log.Fields{"device-id": dh.DeviceID})
+ }
+ return nil
+}
+
// GetDeviceID - TODO: add comment
func (dh *deviceHandler) GetDeviceID() string {
return dh.DeviceID
diff --git a/internal/pkg/devdb/onu_device_db.go b/internal/pkg/devdb/onu_device_db.go
index 627d31c..9c4e126 100755
--- a/internal/pkg/devdb/onu_device_db.go
+++ b/internal/pkg/devdb/onu_device_db.go
@@ -158,6 +158,13 @@
return meInstKeys
}
+//GetNumberOfInst returns the number of instances of an ME
+func (OnuDeviceDB *OnuDeviceDB) GetNumberOfInst(meClassID me.ClassID) int {
+ OnuDeviceDB.meDbLock.RLock()
+ defer OnuDeviceDB.meDbLock.RUnlock()
+ return len(OnuDeviceDB.MeDb[meClassID])
+}
+
//LogMeDb logs content of internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) LogMeDb(ctx context.Context) {
logger.Debugw(ctx, "ME instances stored for :", log.Fields{"device-id": OnuDeviceDB.deviceID})
diff --git a/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1-1UNI.json b/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1-1UNI.json
index 6f4df81..6413e0f 100644
--- a/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1-1UNI.json
+++ b/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1-1UNI.json
@@ -523,6 +523,134 @@
"TrafficSchedulerPointer": 264,
"Weight": 1
}
+ },
+ "32777": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007945,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32778": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007946,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32779": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007947,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32780": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007948,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32781": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007949,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32782": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007950,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32783": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007951,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32784": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007952,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
}
},
"278": {
diff --git a/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1.json b/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1.json
index 3440284..1dc356d 100644
--- a/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1.json
+++ b/templates/BBSM-v0.0.1-BBSM_IMG_00001-v1.json
@@ -580,6 +580,134 @@
"TrafficSchedulerPointer": 264,
"Weight": 1
}
+ },
+ "32777": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007945,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32778": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007946,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32779": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007947,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32780": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007948,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32781": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007949,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32782": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007950,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32783": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007951,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
+ },
+ "32784": {
+ "Attributes": {
+ "AllocatedQueueSize": 100,
+ "BackPressureClearQueueThreshold": 0,
+ "BackPressureOccurQueueThreshold": 0,
+ "BackPressureOperation": 1,
+ "BackPressureTime": 0,
+ "DiscardBlockCounterResetInterval": 0,
+ "MaximumQueueSize": 100,
+ "QueueConfigurationOption": 0,
+ "RelatedPort": 2148007952,
+ "ThresholdValueForDiscardedBlocksDueToBufferOverflow": 0,
+ "TrafficSchedulerPointer": 264,
+ "Weight": 1
+ }
}
},
"278": {