VOL-4058 - TCONT allocation changes in ani configuration
Change-Id: If2e9c6b58ad62b5c1aa3b0771282058f2f2f5067
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index c60f28f..fe64bf2 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -408,8 +408,10 @@
logger.Errorw(ctx, "error-parsing-tpid-from-tppath", log.Fields{"err": err, "tp-path": techProfMsg.Path})
return err
}
+ logger.Debugw(ctx, "unmarshal-techprof-msg-body", log.Fields{"uniID": uniID, "tp-path": techProfMsg.Path, "tpID": tpID})
if bTpModify := pDevEntry.updateOnuUniTpPath(ctx, uniID, uint8(tpID), techProfMsg.Path); bTpModify {
+ logger.Debugw(ctx, "onu-uni-tp-path-modified", log.Fields{"uniID": uniID, "tp-path": techProfMsg.Path, "tpID": tpID})
// 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?)
@@ -423,18 +425,30 @@
dctx, cancel := context.WithDeadline(context.Background(), deadline)
dh.pOnuTP.resetTpProcessingErrorIndication(uniID, tpID)
- pDevEntry.resetKvProcessingErrorIndication()
var wg sync.WaitGroup
- wg.Add(2) // for the 2 go routines to finish
+ wg.Add(1) // for the 1 go routine to finish
// attention: deadline completion check and wg.Done is to be done in both routines
go dh.pOnuTP.configureUniTp(log.WithSpanFromContext(dctx, ctx), uniID, techProfMsg.Path, &wg)
- go pDevEntry.updateOnuKvStore(log.WithSpanFromContext(dctx, ctx), &wg)
dh.waitForCompletion(ctx, cancel, &wg, "TechProfDwld") //wait for background process to finish
-
- return dh.combineErrorStrings(dh.pOnuTP.getTpProcessingErrorIndication(uniID, tpID), pDevEntry.getKvProcessingErrorIndication())
+ if tpErr := dh.pOnuTP.getTpProcessingErrorIndication(uniID, tpID); tpErr != nil {
+ logger.Errorw(ctx, "error-processing-tp", log.Fields{"device-id": dh.deviceID, "err": tpErr, "tp-path": techProfMsg.Path})
+ return tpErr
+ }
+ deadline = time.Now().Add(dh.pOpenOnuAc.maxTimeoutInterAdapterComm) //allowed run time to finish before execution
+ dctx2, cancel2 := context.WithDeadline(context.Background(), deadline)
+ pDevEntry.resetKvProcessingErrorIndication()
+ wg.Add(1) // for the 1 go routine to finish
+ go pDevEntry.updateOnuKvStore(log.WithSpanFromContext(dctx2, ctx), &wg)
+ dh.waitForCompletion(ctx, cancel2, &wg, "TechProfDwld") //wait for background process to finish
+ if kvErr := pDevEntry.getKvProcessingErrorIndication(); kvErr != nil {
+ logger.Errorw(ctx, "error-updating-KV", log.Fields{"device-id": dh.deviceID, "err": kvErr, "tp-path": techProfMsg.Path})
+ return kvErr
+ }
+ return nil
}
// no change, nothing really to do - return success
+ logger.Debugw(ctx, "onu-uni-tp-path-not-modified", log.Fields{"uniID": uniID, "tp-path": techProfMsg.Path, "tpID": tpID})
return nil
}
@@ -539,6 +553,7 @@
}
if bTpModify := pDevEntry.updateOnuUniTpPath(ctx, uniID, tpID, ""); bTpModify {
+ pDevEntry.freeTcont(ctx, uint16(delTcontMsg.AllocId))
// 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)
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()
diff --git a/internal/pkg/onuadaptercore/onu_device_db.go b/internal/pkg/onuadaptercore/onu_device_db.go
index 7cc1cd4..46638e1 100644
--- a/internal/pkg/onuadaptercore/onu_device_db.go
+++ b/internal/pkg/onuadaptercore/onu_device_db.go
@@ -22,6 +22,7 @@
"fmt"
"reflect"
"sort"
+ "sync"
me "github.com/opencord/omci-lib-go/generated"
"github.com/opencord/voltha-lib-go/v4/pkg/log"
@@ -34,6 +35,7 @@
ctx context.Context
pOnuDeviceEntry *OnuDeviceEntry
meDb meDbMap
+ meDbLock sync.RWMutex
}
//newOnuDeviceDB returns a new instance for a specific ONU_Device_Entry
@@ -48,7 +50,8 @@
}
func (onuDeviceDB *onuDeviceDB) PutMe(ctx context.Context, meClassID me.ClassID, meEntityID uint16, meAttributes me.AttributeValueMap) {
-
+ onuDeviceDB.meDbLock.Lock()
+ defer onuDeviceDB.meDbLock.Unlock()
//filter out the OnuData
if me.OnuDataClassID == meClassID {
return
@@ -84,7 +87,8 @@
}
func (onuDeviceDB *onuDeviceDB) GetMe(meClassID me.ClassID, meEntityID uint16) me.AttributeValueMap {
-
+ onuDeviceDB.meDbLock.RLock()
+ defer onuDeviceDB.meDbLock.RUnlock()
if meAttributes, present := onuDeviceDB.meDb[meClassID][meEntityID]; present {
/* verbose logging, avoid in >= debug level
logger.Debugw(ctx,"ME found:", log.Fields{"meClassID": meClassID, "meEntityID": meEntityID, "meAttributes": meAttributes,
@@ -123,7 +127,8 @@
func (onuDeviceDB *onuDeviceDB) getSortedInstKeys(ctx context.Context, meClassID me.ClassID) []uint16 {
var meInstKeys []uint16
-
+ onuDeviceDB.meDbLock.RLock()
+ defer onuDeviceDB.meDbLock.RUnlock()
meInstMap := onuDeviceDB.meDb[meClassID]
for k := range meInstMap {
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 4ada5d9..d3e7238 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -245,22 +245,23 @@
}
type onuPersistentData struct {
- PersOnuID uint32 `json:"onu_id"`
- PersIntfID uint32 `json:"intf_id"`
- PersSerialNumber string `json:"serial_number"`
- PersMacAddress string `json:"mac_address"`
- PersVendorID string `json:"vendor_id"`
- PersEquipmentID string `json:"equipment_id"`
- PersActiveSwVersion string `json:"active_sw_version"`
- PersAdminState string `json:"admin_state"`
- PersOperState string `json:"oper_state"`
- PersUniUnlockDone bool `json:"uni_unlock_done"`
- PersUniDisableDone bool `json:"uni_disable_done"`
- PersMibAuditInterval time.Duration `json:"mib_audit_interval"`
- PersMibLastDbSync uint32 `json:"mib_last_db_sync"`
- PersMibDataSyncAdpt uint8 `json:"mib_data_sync_adpt"`
- PersUniConfig []uniPersConfig `json:"uni_config"`
- PersAlarmAuditInterval time.Duration `json:"alarm_audit_interval"`
+ PersOnuID uint32 `json:"onu_id"`
+ PersIntfID uint32 `json:"intf_id"`
+ PersSerialNumber string `json:"serial_number"`
+ PersMacAddress string `json:"mac_address"`
+ PersVendorID string `json:"vendor_id"`
+ PersEquipmentID string `json:"equipment_id"`
+ PersActiveSwVersion string `json:"active_sw_version"`
+ PersAdminState string `json:"admin_state"`
+ PersOperState string `json:"oper_state"`
+ PersUniUnlockDone bool `json:"uni_unlock_done"`
+ PersUniDisableDone bool `json:"uni_disable_done"`
+ PersMibAuditInterval time.Duration `json:"mib_audit_interval"`
+ PersMibLastDbSync uint32 `json:"mib_last_db_sync"`
+ PersMibDataSyncAdpt uint8 `json:"mib_data_sync_adpt"`
+ PersUniConfig []uniPersConfig `json:"uni_config"`
+ PersAlarmAuditInterval time.Duration `json:"alarm_audit_interval"`
+ PersTcontMap map[uint16]uint16 `json:"tcont_map"` //alloc-id to me-instance-id map
}
// OnuDeviceEntry - ONU device info and FSM events.
@@ -305,6 +306,8 @@
// within the FSM event procedures
omciMessageReceived chan bool //seperate channel needed by DownloadFsm
omciRebootMessageReceivedChannel chan Message // channel needed by Reboot request
+
+ mutexTcontMap sync.RWMutex
}
//newOnuDeviceEntry returns a new instance of a OnuDeviceEntry
@@ -319,6 +322,7 @@
onuDeviceEntry.adapterProxy = dh.AdapterProxy
onuDeviceEntry.devState = DeviceStatusInit
onuDeviceEntry.sOnuPersistentData.PersUniConfig = make([]uniPersConfig, 0)
+ onuDeviceEntry.sOnuPersistentData.PersTcontMap = make(map[uint16]uint16)
onuDeviceEntry.chOnuKvProcessingStep = make(chan uint8)
onuDeviceEntry.omciRebootMessageReceivedChannel = make(chan Message, 2048)
//openomciagent.lockDeviceHandlersMap = sync.RWMutex{}
@@ -612,7 +616,7 @@
oo.mutexPersOnuConfig.Lock()
defer oo.mutexPersOnuConfig.Unlock()
oo.sOnuPersistentData =
- onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval}
+ onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
oo.mutexOnuKVStore.RLock()
Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
oo.mutexOnuKVStore.RUnlock()
@@ -666,7 +670,7 @@
oo.sOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector default entry
oo.sOnuPersistentData =
- onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval}
+ onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0), oo.alarmAuditInterval, make(map[uint16]uint16)}
logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
oo.mutexOnuKVStore.Lock()
err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
@@ -756,8 +760,9 @@
for k, v := range oo.sOnuPersistentData.PersUniConfig {
if v.PersUniID == aUniID {
- logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID})
existingPath, ok := oo.sOnuPersistentData.PersUniConfig[k].PersTpPathMap[aTpID]
+ logger.Debugw(ctx, "PersUniConfig-entry exists", log.Fields{"device-id": oo.deviceID, "uniID": aUniID,
+ "tpID": aTpID, "path": aPathString, "existingPath": existingPath, "ok": ok})
if !ok {
logger.Debugw(ctx, "tp-does-not-exist", log.Fields{"device-id": oo.deviceID, "uniID": aUniID, "tpID": aTpID, "path": aPathString})
}
@@ -892,3 +897,42 @@
defer oo.mutexPersOnuConfig.RUnlock()
return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.sOnuPersistentData.PersVendorID, oo.sOnuPersistentData.PersEquipmentID, oo.sOnuPersistentData.PersActiveSwVersion)
}
+
+func (oo *OnuDeviceEntry) allocateFreeTcont(ctx context.Context, allocID uint16) (uint16, bool, error) {
+ logger.Debugw(ctx, "allocate-free-tcont", log.Fields{"device-id": oo.deviceID, "allocID": allocID,
+ "allocated-instances": oo.sOnuPersistentData.PersTcontMap})
+
+ oo.mutexTcontMap.Lock()
+ defer oo.mutexTcontMap.Unlock()
+ if entityID, ok := oo.sOnuPersistentData.PersTcontMap[allocID]; ok {
+ //tcont already allocated before, return the used instance-id
+ return entityID, true, nil
+ }
+ //First allocation of tcont. Find a free instance
+ if tcontInstKeys := oo.pOnuDB.getSortedInstKeys(ctx, me.TContClassID); len(tcontInstKeys) > 0 {
+ logger.Debugw(ctx, "allocate-free-tcont-db-keys", log.Fields{"device-id": oo.deviceID, "keys": tcontInstKeys})
+ for _, instID := range tcontInstKeys {
+ instExist := false
+ //If this instance exist in map, it means it is not empty. It is allocated before
+ for _, v := range oo.sOnuPersistentData.PersTcontMap {
+ if v == instID {
+ instExist = true
+ break
+ }
+ }
+ if !instExist {
+ oo.sOnuPersistentData.PersTcontMap[allocID] = instID
+ return instID, false, nil
+ }
+ }
+ }
+ return 0, false, fmt.Errorf(fmt.Sprintf("no-free-tcont-left-for-device-%s", oo.deviceID))
+
+}
+
+func (oo *OnuDeviceEntry) freeTcont(ctx context.Context, allocID uint16) {
+ logger.Debugw(ctx, "free-tcont", log.Fields{"device-id": oo.deviceID, "alloc": allocID})
+ oo.mutexTcontMap.Lock()
+ defer oo.mutexTcontMap.Unlock()
+ delete(oo.sOnuPersistentData.PersTcontMap, allocID)
+}
diff --git a/internal/pkg/onuadaptercore/platform.go b/internal/pkg/onuadaptercore/platform.go
index 1f9898f..d70d7f8 100644
--- a/internal/pkg/onuadaptercore/platform.go
+++ b/internal/pkg/onuadaptercore/platform.go
@@ -118,7 +118,7 @@
//Mask to indicate which possibly active ONU UNI state is really reported to the core
// compare python code - at the moment restrict active state to the first ONU UNI port
// check is limited to max 16 uni ports - cmp above UNI limit!!!
-var activeUniPortStateUpdateMask = 0x0001
+var activeUniPortStateUpdateMask = 0x00FF
/*
//MinUpstreamPortID value