VOL-4058 - TCONT allocation changes in ani configuration
Change-Id: If2e9c6b58ad62b5c1aa3b0771282058f2f2f5067
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index ae70353..5701985 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -85,10 +85,6 @@
)
const cAniFsmIdleState = aniStConfigDone
-const (
- tpIDOffset = 64
-)
-
type ponAniGemPortAttribs struct {
gemPortID uint16
upQueueID uint16
@@ -133,6 +129,7 @@
requestEventOffset uint8 //used to indicate ConfigDone or Removed using successor (enum)
isWaitingForFlowDelete bool
waitFlowDeleteChannel chan bool
+ tcontSetBefore bool
}
//newUniPonAniConfigFsm is the 'constructor' for the state machine to config the PON ANI ports of ONU UNI ports via OMCI
@@ -149,6 +146,7 @@
techProfileID: aTechProfileID,
requestEvent: aRequestEvent,
chanSet: false,
+ tcontSetBefore: false,
}
instFsm.uniTpKey = uniTP{uniID: apUniPort.uniID, tpID: aTechProfileID}
instFsm.waitFlowDeleteChannel = make(chan bool)
@@ -298,8 +296,6 @@
//TODO:visit here for refactoring for gocyclo
func (oFsm *uniPonAniConfigFsm) prepareAndEnterConfigState(ctx context.Context, aPAFsm *AdapterFsm) {
if aPAFsm != nil && aPAFsm.pFsm != nil {
- //stick to pythonAdapter numbering scheme
- //index 0 in naming refers to possible usage of multiple instances (later)
var err error
oFsm.mapperSP0ID, err = generateIeeMaperServiceProfileEID(uint16(oFsm.pOnuUniPort.macBpNo), uint16(oFsm.techProfileID))
if err != nil {
@@ -316,66 +312,29 @@
logger.Debugw(ctx, "generated ids for ani config", log.Fields{"mapperSP0ID": strconv.FormatInt(int64(oFsm.mapperSP0ID), 16),
"macBPCD0ID": strconv.FormatInt(int64(oFsm.macBPCD0ID), 16), "device-id": oFsm.deviceID,
"macBpNo": oFsm.pOnuUniPort.macBpNo, "techProfileID": oFsm.techProfileID})
- if tcontInstKeys := oFsm.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
-
- // FIXME: Ideally the ME configurations on the ONU should constantly be MIB Synced back to the ONU DB
- // So, as soon as we use up a TCONT Entity on the ONU, the DB at ONU adapter should know that the TCONT
- // entity is used up via MIB Sync procedure and it will not use it for subsequent TCONT on that ONU.
- // But, it seems, due to the absence of the constant mib-sync procedure, the TCONT Entities show up as
- // free even though they are already reserved on the ONU. It seems the mib is synced only once, initially
- // when the ONU is discovered.
- /*
- for _, tcontInstID := range tcontInstKeys {
- tconInst := oFsm.pOnuDB.GetMe(me.TContClassID, tcontInstID)
- returnVal := tconInst["AllocId"]
- if returnVal != nil {
- if allocID, err := oFsm.pOnuDB.getUint16Attrib(returnVal); err == nil {
- // If the TCONT Instance ID is set to 0xff or 0xffff, it means it is free to use.
- if allocID == 0xff || allocID == 0xffff {
- foundFreeTcontInstID = true
- oFsm.tcont0ID = uint16(tcontInstID)
- logger.Debugw("Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
- "device-id": oFsm.deviceID})
- break
- }
- } else {
- logger.Errorw("error-converting-alloc-id-to-uint16", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
- }
- } else {
- logger.Errorw("error-extracting-alloc-id-attribute", log.Fields{"device-id": oFsm.deviceID, "tcont-inst": tcontInstID})
- }
- }
- */
-
- // Ensure that the techProfileID is in a valid range so that we can allocate a free Tcont for it.
- if oFsm.techProfileID >= tpIDOffset && oFsm.techProfileID < uint8(tpIDOffset+len(tcontInstKeys)) {
- // For now, as a dirty workaround, use the tpIDOffset to index the TcontEntityID to be used.
- // The first TP ID for the ONU will get the first TcontEntityID, the next will get second and so on.
- // Here the assumption is TP ID will always start from 64 (this is also true to Technology Profile Specification) and the
- // TP ID will increment in single digit
- oFsm.tcont0ID = tcontInstKeys[oFsm.techProfileID-tpIDOffset]
- logger.Debugw(ctx, "Used TcontId:", log.Fields{"TcontId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
- "device-id": oFsm.deviceID})
- } else {
- logger.Errorw(ctx, "tech profile id not in valid range", log.Fields{"device-id": oFsm.deviceID, "tp-id": oFsm.techProfileID, "num-tcont": len(tcontInstKeys)})
- if oFsm.isChanSet() {
- // indicate processing error/abort to the caller
- oFsm.chSuccess <- 0
- oFsm.setChanSet(false) //reset the internal channel state
- }
- //reset the state machine to enable usage on subsequent requests
- _ = aPAFsm.pFsm.Event(aniEvReset)
- return
- }
- } else {
- logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID})
+ pDevEntry := oFsm.pDeviceHandler.getOnuDeviceEntry(ctx, false)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": oFsm.deviceID})
return
}
- /*
- if !foundFreeTcontInstID {
- // This should never happen. If it does, the behavior is unpredictable.
- logger.Warnw("No free TCONT instances found", log.Fields{"device-id": oFsm.deviceID})
- }*/
+ tcontInstID, tcontAlreadyExist, err := pDevEntry.allocateFreeTcont(ctx, oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID)
+ if err != nil {
+ logger.Errorw(ctx, "No TCont instances found", log.Fields{"device-id": oFsm.deviceID, "err": err})
+ if oFsm.chanSet {
+ // indicate processing error/abort to the caller
+ oFsm.chSuccess <- 0
+ oFsm.chanSet = false //reset the internal channel state
+ }
+ //reset the state machine to enable usage on subsequent requests
+ _ = aPAFsm.pFsm.Event(aniEvReset)
+ return
+ }
+ oFsm.tcont0ID = tcontInstID
+ oFsm.tcontSetBefore = tcontAlreadyExist
+ logger.Debugw(ctx, "used-tcont-instance-id", log.Fields{"tcont-inst-id": oFsm.tcont0ID,
+ "alloc-id": oFsm.pUniTechProf.mapPonAniConfig[oFsm.uniTpKey].tcontParams.allocID,
+ "tcontAlreadyExist": tcontAlreadyExist,
+ "device-id": oFsm.deviceID})
// Access critical state with lock
oFsm.pUniTechProf.mutexTPState.Lock()
@@ -590,7 +549,17 @@
logger.Debugw(ctx, "uniPonAniConfigFsm Tx Set::Tcont", log.Fields{
"EntitytId": strconv.FormatInt(int64(oFsm.tcont0ID), 16),
"AllocId": strconv.FormatInt(int64(oFsm.alloc0ID), 16),
- "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID})
+ "device-id": oFsm.deviceID, "uni-id": oFsm.pOnuUniPort.uniID,
+ "tcontExist": oFsm.tcontSetBefore})
+ //If tcont was set before, then no need to set it again. Let state machine to proceed.
+ if oFsm.tcontSetBefore {
+ go func(aPAFsm *AdapterFsm) {
+ if aPAFsm != nil && aPAFsm.pFsm != nil {
+ _ = aPAFsm.pFsm.Event(aniEvRxTcontsResp)
+ }
+ }(oFsm.pAdaptFsm)
+ return
+ }
meParams := me.ParamData{
EntityID: oFsm.tcont0ID,
Attributes: me.AttributeValueMap{
@@ -1219,6 +1188,11 @@
logger.Errorw(ctx, "UniPonAniConfigFsm - Omci SetResponse Error - later: drive FSM to abort state ?",
log.Fields{"device-id": oFsm.deviceID, "Error": msgObj.Result})
// possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+
+ //FIXME: If setting TCONT fails we need to revert the DB back. Because of the concurency,
+ //doing it here may cause a data inconsistency. To fix this problem we need to think on running
+ //the FSMs of different UNIs sequentially instead of running them concurrently.
+
return
}
oFsm.mutexPLastTxMeInstance.RLock()
@@ -1523,6 +1497,19 @@
}
func (oFsm *uniPonAniConfigFsm) performSettingPQs(ctx context.Context) {
+ //If upstream PQs were set before, then no need to set them again. Let state machine to proceed.
+ if oFsm.tcontSetBefore {
+ logger.Debugw(ctx, "No need to set PQs again.", log.Fields{
+ "device-id": oFsm.deviceID, "tcont": oFsm.alloc0ID,
+ "uni-id": oFsm.pOnuUniPort.uniID,
+ "techProfile-id": oFsm.techProfileID})
+ go func(aPAFsm *AdapterFsm) {
+ if aPAFsm != nil && aPAFsm.pFsm != nil {
+ _ = aPAFsm.pFsm.Event(aniEvRxPrioqsResp)
+ }
+ }(oFsm.pAdaptFsm)
+ return
+ }
const cu16StrictPrioWeight uint16 = 0xFFFF
//find all upstream PrioQueues related to this T-Cont
loQueueMap := ordered_map.NewOrderedMap()