[VOL-3834] Avoid ONU service disruption on adapter restart
Change-Id: I21d15b09bdbfe2900edccefac9a72e498d2da9d7
diff --git a/VERSION b/VERSION
index 6cfec74..edbe966 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.2.5-dev173
+1.2.5-dev174
diff --git a/internal/pkg/onuadaptercore/alarm_manager.go b/internal/pkg/onuadaptercore/alarm_manager.go
index 1efc819..fdb17b3 100644
--- a/internal/pkg/onuadaptercore/alarm_manager.go
+++ b/internal/pkg/onuadaptercore/alarm_manager.go
@@ -279,7 +279,7 @@
context := make(map[string]string)
intfID := am.getIntfIDAlarm(ctx, classID, instanceID)
onuID := am.pDeviceHandler.deviceID
- serialNo := am.pDeviceHandler.pOnuOmciDevice.serialNumber
+ serialNo := am.pDeviceHandler.pOnuOmciDevice.sOnuPersistentData.PersSerialNumber
if intfID == nil {
logger.Warn(ctx, "intf-id-for-alarm-not-found", log.Fields{"alarm-no": alarm, "class-id": classID})
return
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 6c4d5ce..3422c43 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -153,6 +153,12 @@
drTechProfileConfigDeleteSuccess: "tech-profile-config-delete-success",
}
+const (
+ cNoReconciling = iota
+ cOnuConfigReconciling
+ cSkipOnuConfigReconciling
+)
+
//deviceHandler will interact with the ONU ? device.
type deviceHandler struct {
deviceID string
@@ -174,17 +180,18 @@
pOpenOnuAc *OpenONUAC
pDeviceStateFsm *fsm.FSM
//pPonPort *voltha.Port
- deviceEntrySet chan bool //channel for DeviceEntry set event
- pOnuOmciDevice *OnuDeviceEntry
- pOnuTP *onuUniTechProf
- pOnuMetricsMgr *onuMetricsManager
- pAlarmMgr *onuAlarmManager
- exitChannel chan int
- lockDevice sync.RWMutex
- pOnuIndication *oop.OnuIndication
- deviceReason uint8
- pLockStateFsm *lockStateFsm
- pUnlockStateFsm *lockStateFsm
+ deviceEntrySet chan bool //channel for DeviceEntry set event
+ pOnuOmciDevice *OnuDeviceEntry
+ pOnuTP *onuUniTechProf
+ pOnuMetricsMgr *onuMetricsManager
+ pAlarmMgr *onuAlarmManager
+ exitChannel chan int
+ lockDevice sync.RWMutex
+ pOnuIndication *oop.OnuIndication
+ deviceReason uint8
+ mutexDeviceReason sync.RWMutex
+ pLockStateFsm *lockStateFsm
+ pUnlockStateFsm *lockStateFsm
//flowMgr *OpenOltFlowMgr
//eventMgr *OpenOltEventMgr
@@ -206,7 +213,7 @@
UniVlanConfigFsmMap map[uint8]*UniVlanConfigFsm
lockUpgradeFsm sync.RWMutex
pOnuUpradeFsm *OnuUpgradeFsm
- reconciling bool
+ reconciling uint8
mutexReconcilingFlag sync.RWMutex
chReconcilingFinished chan bool //channel to indicate that reconciling has been finished
ReadyForSpecificOmciConfig bool
@@ -238,7 +245,7 @@
dh.lockVlanConfig = sync.RWMutex{}
dh.lockUpgradeFsm = sync.RWMutex{}
dh.UniVlanConfigFsmMap = make(map[uint8]*UniVlanConfigFsm)
- dh.reconciling = false
+ dh.reconciling = cNoReconciling
dh.chReconcilingFinished = make(chan bool)
dh.ReadyForSpecificOmciConfig = false
@@ -359,8 +366,8 @@
}
if !dh.ReadyForSpecificOmciConfig {
logger.Errorw(ctx, "TechProf-set rejected: improper device state", log.Fields{"device-id": dh.deviceID,
- "device-state": deviceReasonMap[dh.deviceReason]})
- return fmt.Errorf("improper device state %s on device %s", deviceReasonMap[dh.deviceReason], dh.deviceID)
+ "device-state": dh.getDeviceReasonString()})
+ return fmt.Errorf("improper device state %s on device %s", dh.getDeviceReasonString(), 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
@@ -680,7 +687,7 @@
// also abort for the other still possible flows here
if !dh.ReadyForSpecificOmciConfig {
logger.Errorw(ctx, "flow-add rejected: improper device state", log.Fields{"device-id": dh.deviceID,
- "last device-reason": deviceReasonMap[dh.deviceReason]})
+ "last device-reason": dh.getDeviceReasonString()})
return fmt.Errorf("improper device state on device %s", dh.deviceID)
}
@@ -716,7 +723,7 @@
//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 != drOmciAdminLock {
+ if dh.getDeviceReason() != drOmciAdminLock {
//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
@@ -800,6 +807,7 @@
pDevEntry := dh.getOnuDeviceEntry(ctx, true)
if pDevEntry == nil {
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
return
}
dh.pOnuTP.lockTpProcMutex()
@@ -813,14 +821,16 @@
dh.stopReconciling(ctx)
return
}
+ techProfsFound := false
+ flowsFound := false
for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
//TODO: check for uni-port specific reconcilement in case of multi-uni-port-per-onu-support
if len(uniData.PersTpPathMap) == 0 {
- logger.Debugw(ctx, "reconciling - no TPs have been stored before adapter restart - terminate reconcilement",
+ logger.Debugw(ctx, "reconciling - no TPs stored for uniID",
log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.deviceID})
- dh.stopReconciling(ctx)
- return
+ continue
}
+ techProfsFound = true
for tpID := range uniData.PersTpPathMap {
// deadline context to ensure completion of background routines waited for
//20200721: 10s proved to be less in 8*8 ONU test on local vbox machine with debug, might be further adapted
@@ -836,12 +846,24 @@
logger.Errorw(ctx, err.Error(), log.Fields{"device-id": dh.deviceID})
}
}
- if len(uniData.PersFlowParams) == 0 {
- logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
- log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.deviceID})
- dh.stopReconciling(ctx)
+ if len(uniData.PersFlowParams) != 0 {
+ flowsFound = true
}
}
+ if !techProfsFound {
+ logger.Debugw(ctx, "reconciling - no TPs have been stored before adapter restart - terminate reconcilement",
+ log.Fields{"device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
+ return
+ }
+ if dh.isSkipOnuConfigReconciling() {
+ dh.setDeviceReason(drTechProfileConfigDownloadSuccess)
+ }
+ if !flowsFound {
+ logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
+ log.Fields{"device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
+ }
}
func (dh *deviceHandler) reconcileDeviceFlowConfig(ctx context.Context) {
@@ -850,33 +872,43 @@
pDevEntry := dh.getOnuDeviceEntry(ctx, true)
if pDevEntry == nil {
logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
return
}
pDevEntry.persUniConfigMutex.RLock()
defer pDevEntry.persUniConfigMutex.RUnlock()
+
if len(pDevEntry.sOnuPersistentData.PersUniConfig) == 0 {
logger.Debugw(ctx, "reconciling - no uni-configs have been stored before adapter restart - terminate reconcilement",
log.Fields{"device-id": dh.deviceID})
dh.stopReconciling(ctx)
return
}
+ flowsFound := false
for _, uniData := range pDevEntry.sOnuPersistentData.PersUniConfig {
//TODO: check for uni-port specific reconcilement in case of multi-uni-port-per-onu-support
if len(uniData.PersFlowParams) == 0 {
- logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
+ logger.Debugw(ctx, "reconciling - no flows stored for uniID",
log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.deviceID})
- dh.stopReconciling(ctx)
- return
+ continue
+ }
+ if len(uniData.PersTpPathMap) == 0 {
+ logger.Warnw(ctx, "reconciling - flows but no TPs stored for uniID",
+ log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.deviceID})
}
var uniPort *onuUniPort
var exist bool
uniNo := mkUniPortNum(ctx, dh.pOnuIndication.GetIntfId(), dh.pOnuIndication.GetOnuId(), uint32(uniData.PersUniID))
if uniPort, exist = dh.uniEntityMap[uniNo]; !exist {
- logger.Errorw(ctx, "onuUniPort data not found!", log.Fields{"uniNo": uniNo, "device-id": dh.deviceID})
+ logger.Errorw(ctx, "reconciling - onuUniPort data not found - terminate reconcilement",
+ log.Fields{"uniNo": uniNo, "device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
return
}
+ flowsFound = true
+ flowsProcessed := 0
for _, flowData := range uniData.PersFlowParams {
- logger.Debugw(ctx, "add flow with cookie slice", log.Fields{"device-id": dh.deviceID, "cookies": flowData.CookieSlice})
+ logger.Debugw(ctx, "reconciling - add flow with cookie slice", log.Fields{"device-id": dh.deviceID, "cookies": flowData.CookieSlice})
//the slice can be passed 'by value' here, - which internally passes its reference copy
dh.lockVlanConfig.RLock()
if _, exist = dh.UniVlanConfigFsmMap[uniData.PersUniID]; exist {
@@ -894,12 +926,20 @@
logger.Errorw(ctx, err.Error(), log.Fields{"device-id": dh.deviceID})
}
}
+ flowsProcessed++
}
- if len(uniData.PersTpPathMap) == 0 {
- logger.Debugw(ctx, "reconciling - no TPs have been stored before adapter restart - terminate reconcilement",
- log.Fields{"uni-id": uniData.PersUniID, "device-id": dh.deviceID})
- dh.stopReconciling(ctx)
- }
+ logger.Debugw(ctx, "reconciling - flows processed", log.Fields{"device-id": dh.deviceID, "flowsProcessed": flowsProcessed,
+ "numUniFlows": dh.UniVlanConfigFsmMap[uniData.PersUniID].numUniFlows,
+ "configuredUniFlow": dh.UniVlanConfigFsmMap[uniData.PersUniID].configuredUniFlow})
+ }
+ if !flowsFound {
+ logger.Debugw(ctx, "reconciling - no flows have been stored before adapter restart - terminate reconcilement",
+ log.Fields{"device-id": dh.deviceID})
+ dh.stopReconciling(ctx)
+ return
+ }
+ if dh.isSkipOnuConfigReconciling() {
+ dh.setDeviceReason(drOmciFlowsPushed)
}
}
@@ -1051,7 +1091,7 @@
dh.device.Vendor = "OpenONU"
dh.device.Model = "go"
dh.device.Reason = deviceReasonMap[drActivatingOnu]
- dh.deviceReason = drActivatingOnu
+ dh.setDeviceReason(drActivatingOnu)
dh.logicalDeviceID = dh.deviceID // really needed - what for ??? //TODO!!!
@@ -1533,7 +1573,7 @@
func (dh *deviceHandler) updateInterface(ctx context.Context, 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 != drStoppingOpenomci {
+ if dh.getDeviceReason() != drStoppingOpenomci {
logger.Debugw(ctx, "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
@@ -1674,38 +1714,14 @@
func (dh *deviceHandler) processMibDatabaseSyncEvent(ctx context.Context, devEvent OnuDeviceEvent) {
logger.Debugw(ctx, "MibInSync event received, adding uni ports and locking the ONU interfaces", log.Fields{"device-id": dh.deviceID})
+ // store persistent data collected during MIB upload processing
+ if err := dh.storePersistentData(ctx); err != nil {
+ logger.Warnw(ctx, "store persistent data error - continue as there will be additional write attempts",
+ log.Fields{"device-id": dh.deviceID, "err": err})
+ }
_ = dh.deviceReasonUpdate(ctx, drDiscoveryMibsyncComplete, !dh.isReconciling())
- pDevEntry := dh.getOnuDeviceEntry(ctx, false)
- if pDevEntry == nil {
- logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
- return
- }
- i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
- if pptpInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(
- ctx, me.PhysicalPathTerminationPointEthernetUniClassID); len(pptpInstKeys) > 0 {
- for _, mgmtEntityID := range pptpInstKeys {
- logger.Debugw(ctx, "Add PPTPEthUni port for MIB-stored instance:", log.Fields{
- "device-id": dh.deviceID, "PPTPEthUni EntityID": mgmtEntityID})
- dh.addUniPort(ctx, mgmtEntityID, i, uniPPTP)
- i++
- }
- } else {
- logger.Debugw(ctx, "No UniG instances found", log.Fields{"device-id": dh.deviceID})
- }
- if veipInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(
- ctx, me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
- for _, mgmtEntityID := range veipInstKeys {
- logger.Debugw(ctx, "Add VEIP for MIB-stored instance:", log.Fields{
- "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
- dh.addUniPort(ctx, mgmtEntityID, i, uniVEIP)
- i++
- }
- } else {
- logger.Debugw(ctx, "No VEIP instances found", log.Fields{"device-id": dh.deviceID})
- }
- if i == 0 {
- logger.Warnw(ctx, "No PPTP instances found", log.Fields{"device-id": dh.deviceID})
- }
+ dh.addAllUniPorts(ctx)
+
/* 200605: lock processing after initial MIBUpload removed now as the ONU should be in the lock state per default here */
/* 201117: build_dt-berlin-pod-openonugo_1T8GEM_voltha_DT_openonugo_master_test runs into error TC
* 'Test Disable ONUs and OLT Then Delete ONUs and OLT for DT' with Sercom ONU, which obviously needs
@@ -1733,7 +1749,7 @@
*/
pDevEntry := dh.getOnuDeviceEntry(ctx, false)
if pDevEntry == nil {
- logger.Errorw(ctx, "No valid OnuDevice -aborting", log.Fields{"device-id": dh.deviceID})
+ logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
return
}
pMibDlFsm := pDevEntry.pMibDownloadFsm.pFsm
@@ -1781,17 +1797,6 @@
logger.Debugw(ctx, "dev state updated to 'Oper.Active'", log.Fields{"device-id": dh.deviceID})
}
} else {
- pDevEntry := dh.getOnuDeviceEntry(ctx, false)
- if pDevEntry == nil {
- logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
- return
- }
- if pDevEntry.sOnuPersistentData.PersUniDisableDone {
- logger.Debugw(ctx, "reconciling - uni-ports were disabled by admin before adapter restart - keep the ports locked and wait for re-enabling",
- log.Fields{"device-id": dh.deviceID})
- dh.stopReconciling(ctx)
- return
- }
logger.Debugw(ctx, "reconciling - don't notify core about DeviceStateUpdate to ACTIVE",
log.Fields{"device-id": dh.deviceID})
}
@@ -1805,12 +1810,25 @@
}
dh.ReadyForSpecificOmciConfig = true
- // *** should generate UniUnlockStateDone event *****
- if dh.pUnlockStateFsm == nil {
- dh.createUniLockFsm(ctx, false, UniUnlockStateDone)
- } else { //UnlockStateFSM already init
- dh.pUnlockStateFsm.setSuccessEvent(UniUnlockStateDone)
- dh.runUniLockFsm(ctx, false)
+
+ pDevEntry := dh.getOnuDeviceEntry(ctx, false)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
+ return
+ }
+ if dh.isReconciling() && pDevEntry.sOnuPersistentData.PersUniDisableDone {
+ 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)
+ // reconcilement will be continued after ani config is done
+ } else {
+ // *** should generate UniUnlockStateDone event *****
+ if dh.pUnlockStateFsm == nil {
+ dh.createUniLockFsm(ctx, false, UniUnlockStateDone)
+ } else { //UnlockStateFSM already init
+ dh.pUnlockStateFsm.setSuccessEvent(UniUnlockStateDone)
+ dh.runUniLockFsm(ctx, false)
+ }
}
}
@@ -1901,7 +1919,7 @@
logger.Debugw(ctx, "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 != drTechProfileConfigDownloadSuccess {
+ if dh.getDeviceReason() != drTechProfileConfigDownloadSuccess {
// which may be the case from some previous actvity even on this UNI Port (but also other UNI ports)
_ = dh.deviceReasonUpdate(ctx, drTechProfileConfigDownloadSuccess, !dh.isReconciling())
}
@@ -1912,7 +1930,7 @@
logger.Debugw(ctx, "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 != drTechProfileConfigDeleteSuccess {
+ if dh.getDeviceReason() != drTechProfileConfigDeleteSuccess {
// which may be the case from some previous actvity even on this ONU port (but also other UNI ports)
_ = dh.deviceReasonUpdate(ctx, drTechProfileConfigDeleteSuccess, true)
}
@@ -1926,7 +1944,7 @@
// - which may cause some inconsistency
if aDevEvent == OmciVlanFilterAddDone || aDevEvent == OmciVlanFilterAddDoneNoKvStore {
- if dh.deviceReason != drOmciFlowsPushed {
+ if dh.getDeviceReason() != drOmciFlowsPushed {
// 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
_ = dh.deviceReasonUpdate(ctx, drOmciFlowsPushed, !dh.isReconciling())
@@ -1935,7 +1953,7 @@
}
}
} else {
- if dh.deviceReason != drOmciFlowsDeleted {
+ if dh.getDeviceReason() != drOmciFlowsDeleted {
//not relevant for reconcile
_ = dh.deviceReasonUpdate(ctx, drOmciFlowsDeleted, true)
}
@@ -2021,6 +2039,40 @@
}
}
+func (dh *deviceHandler) addAllUniPorts(ctx context.Context) {
+ pDevEntry := dh.getOnuDeviceEntry(ctx, false)
+ if pDevEntry == nil {
+ logger.Errorw(ctx, "No valid OnuDevice - aborting", log.Fields{"device-id": dh.deviceID})
+ return
+ }
+ i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
+ if pptpInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(
+ ctx, me.PhysicalPathTerminationPointEthernetUniClassID); len(pptpInstKeys) > 0 {
+ for _, mgmtEntityID := range pptpInstKeys {
+ logger.Debugw(ctx, "Add PPTPEthUni port for MIB-stored instance:", log.Fields{
+ "device-id": dh.deviceID, "PPTPEthUni EntityID": mgmtEntityID})
+ dh.addUniPort(ctx, mgmtEntityID, i, uniPPTP)
+ i++
+ }
+ } else {
+ logger.Debugw(ctx, "No PPTP instances found", log.Fields{"device-id": dh.deviceID})
+ }
+ if veipInstKeys := pDevEntry.pOnuDB.getSortedInstKeys(
+ ctx, me.VirtualEthernetInterfacePointClassID); len(veipInstKeys) > 0 {
+ for _, mgmtEntityID := range veipInstKeys {
+ logger.Debugw(ctx, "Add VEIP for MIB-stored instance:", log.Fields{
+ "device-id": dh.deviceID, "VEIP EntityID": mgmtEntityID})
+ dh.addUniPort(ctx, mgmtEntityID, i, uniVEIP)
+ i++
+ }
+ } else {
+ logger.Debugw(ctx, "No VEIP instances found", log.Fields{"device-id": dh.deviceID})
+ }
+ if i == 0 {
+ logger.Warnw(ctx, "No UniG instances found", log.Fields{"device-id": dh.deviceID})
+ }
+}
+
// enableUniPortStateUpdate enables UniPortState and update core port state accordingly
func (dh *deviceHandler) enableUniPortStateUpdate(ctx context.Context) {
// py code was updated 2003xx to activate the real ONU UNI ports per OMCI (VEIP or PPTP)
@@ -2029,7 +2081,7 @@
// # TODO: for now only support the first UNI given no requirement for multiple uni yet. Also needed to reduce flow
// # load on the core
- // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
+ // lock_ports(false) as done in py code here is shifted to separate call from device event processing
for uniNo, uniPort := range dh.uniEntityMap {
// only if this port is validated for operState transfer
@@ -2040,7 +2092,6 @@
//maybe also use getter functions on uniPort - perhaps later ...
go dh.coreProxy.PortStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
} else {
- //TODO there is no retry mechanism, return error
logger.Debugw(ctx, "reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
}
}
@@ -2056,8 +2107,13 @@
if (1<<uniPort.uniID)&activeUniPortStateUpdateMask == (1 << uniPort.uniID) {
logger.Infow(ctx, "onuUniPort-forced-OperState-UNKNOWN", log.Fields{"for PortNo": uniNo})
uniPort.setOperState(vc.OperStatus_UNKNOWN)
- //maybe also use getter functions on uniPort - perhaps later ...
- go dh.coreProxy.PortStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
+ if !dh.isReconciling() {
+ //maybe also use getter functions on uniPort - perhaps later ...
+ go dh.coreProxy.PortStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.deviceID, voltha.Port_ETHERNET_UNI, uniPort.portNo, uniPort.operState)
+ } else {
+ logger.Debugw(ctx, "reconciling - don't notify core about PortStateUpdate", log.Fields{"device-id": dh.deviceID})
+ }
+
}
}
}
@@ -2737,7 +2793,7 @@
func (dh *deviceHandler) deviceReasonUpdate(ctx context.Context, deviceReason uint8, notifyCore bool) error {
- dh.deviceReason = deviceReason
+ dh.setDeviceReason(deviceReason)
if notifyCore {
//TODO with VOL-3045/VOL-3046: return the error and stop further processing at calling position
if err := dh.coreProxy.DeviceReasonUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.deviceID, deviceReasonMap[deviceReason]); err != nil {
@@ -3070,7 +3126,7 @@
go dh.startAlarmManager(ctx)
}
dh.uniEntityMap = make(map[uint32]*onuUniPort)
- dh.startReconciling(ctx)
+ dh.startReconciling(ctx, false)
}
func (dh *deviceHandler) setCollectorIsRunning(flagValue bool) {
@@ -3113,10 +3169,13 @@
}
}
-func (dh *deviceHandler) startReconciling(ctx context.Context) {
- logger.Debugw(ctx, "start reconciling", log.Fields{"timeout": dh.pOpenOnuAc.maxTimeoutReconciling, "device-id": dh.deviceID})
+func (dh *deviceHandler) startReconciling(ctx context.Context, skipOnuConfig bool) {
+ logger.Debugw(ctx, "start reconciling", log.Fields{"withOnuConfig": skipOnuConfig, "device-id": dh.deviceID})
+
if !dh.isReconciling() {
go func() {
+ logger.Debugw(ctx, "wait for channel signal or timeout",
+ log.Fields{"timeout": dh.pOpenOnuAc.maxTimeoutReconciling, "device-id": dh.deviceID})
select {
case <-dh.chReconcilingFinished:
logger.Debugw(ctx, "reconciling has been finished in time",
@@ -3126,15 +3185,17 @@
log.Fields{"device-id": dh.deviceID})
}
dh.mutexReconcilingFlag.Lock()
- dh.reconciling = false
+ dh.reconciling = cNoReconciling
dh.mutexReconcilingFlag.Unlock()
}()
- dh.mutexReconcilingFlag.Lock()
- dh.reconciling = true
- dh.mutexReconcilingFlag.Unlock()
- } else {
- logger.Warnw(ctx, "reconciling is already running", log.Fields{"device-id": dh.deviceID})
}
+ dh.mutexReconcilingFlag.Lock()
+ if skipOnuConfig {
+ dh.reconciling = cSkipOnuConfigReconciling
+ } else {
+ dh.reconciling = cOnuConfigReconciling
+ }
+ dh.mutexReconcilingFlag.Unlock()
}
func (dh *deviceHandler) stopReconciling(ctx context.Context) {
@@ -3148,7 +3209,29 @@
func (dh *deviceHandler) isReconciling() bool {
dh.mutexReconcilingFlag.RLock()
- value := dh.reconciling
- dh.mutexReconcilingFlag.RUnlock()
+ defer dh.mutexReconcilingFlag.RUnlock()
+ return dh.reconciling != cNoReconciling
+}
+
+func (dh *deviceHandler) isSkipOnuConfigReconciling() bool {
+ dh.mutexReconcilingFlag.RLock()
+ defer dh.mutexReconcilingFlag.RUnlock()
+ return dh.reconciling == cSkipOnuConfigReconciling
+}
+
+func (dh *deviceHandler) setDeviceReason(value uint8) {
+ dh.mutexDeviceReason.Lock()
+ dh.deviceReason = value
+ dh.mutexDeviceReason.Unlock()
+}
+
+func (dh *deviceHandler) getDeviceReason() uint8 {
+ dh.mutexDeviceReason.RLock()
+ value := dh.deviceReason
+ dh.mutexDeviceReason.RUnlock()
return value
}
+
+func (dh *deviceHandler) getDeviceReasonString() string {
+ return deviceReasonMap[dh.getDeviceReason()]
+}
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index 0c71848..9880cb5 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -128,71 +128,15 @@
oo.PDevOmciCC.pLastTxMeInstance = meInstance
}
-func (oo *OnuDeviceEntry) enterGettingMibTemplate(ctx context.Context, e *fsm.Event) {
+func (oo *OnuDeviceEntry) enterGettingMibTemplateState(ctx context.Context, e *fsm.Event) {
if oo.onuSwImageIndications.activeEntityEntry.valid {
- oo.activeSwVersion = oo.onuSwImageIndications.activeEntityEntry.version
+ oo.sOnuPersistentData.PersActiveSwVersion = oo.onuSwImageIndications.activeEntityEntry.version
} else {
logger.Errorw(ctx, "get-mib-template: no active SW version found, working with empty SW version, which might be untrustworthy",
log.Fields{"device-id": oo.deviceID})
}
-
- meStoredFromTemplate := false
- oo.mibTemplatePath = fmt.Sprintf(cSuffixMibTemplateKvStore, oo.vendorID, oo.equipmentID, oo.activeSwVersion)
- logger.Debugw(ctx, "MibSync FSM - MibTemplate - etcd search string", log.Fields{"path": fmt.Sprintf("%s/%s", cBasePathMibTemplateKvStore, oo.mibTemplatePath)})
- Value, err := oo.mibTemplateKVStore.Get(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath)
- if err == nil {
- if Value != nil {
- logger.Debugf(ctx, "MibSync FSM - MibTemplate read: Key: %s, Value: %s %s", Value.Key, Value.Value)
-
- // swap out tokens with specific data
- mibTmpString, _ := kvstore.ToString(Value.Value)
- mibTmpString2 := strings.Replace(mibTmpString, "%SERIAL_NUMBER%", oo.serialNumber, -1)
- mibTmpString = strings.Replace(mibTmpString2, "%MAC_ADDRESS%", oo.macAddress, -1)
- mibTmpBytes := []byte(mibTmpString)
- logger.Debugf(ctx, "MibSync FSM - MibTemplate tokens swapped out: %s", mibTmpBytes)
-
- var firstLevelMap map[string]interface{}
- if err = json.Unmarshal(mibTmpBytes, &firstLevelMap); err != nil {
- logger.Errorw(ctx, "MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": oo.deviceID})
- } else {
- for firstLevelKey, firstLevelValue := range firstLevelMap {
- //logger.Debugw(ctx, "MibSync FSM - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
- if uint16ValidNumber, err := strconv.ParseUint(firstLevelKey, 10, 16); err == nil {
- meClassID := me.ClassID(uint16ValidNumber)
- //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
- if isSupportedClassID(meClassID) {
- //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a supported classID", log.Fields{"meClassID": meClassID})
- secondLevelMap := firstLevelValue.(map[string]interface{})
- for secondLevelKey, secondLevelValue := range secondLevelMap {
- //logger.Debugw(ctx, "MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
- if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
- meEntityID := uint16(uint16ValidNumber)
- //logger.Debugw(ctx, "MibSync FSM - secondLevelKey is a number and a valid EntityId", log.Fields{"meEntityID": meEntityID})
- thirdLevelMap := secondLevelValue.(map[string]interface{})
- for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
- if thirdLevelKey == "Attributes" {
- //logger.Debugw(ctx, "MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
- attributesMap := thirdLevelValue.(map[string]interface{})
- //logger.Debugw(ctx, "MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
- oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, attributesMap)
- meStoredFromTemplate = true
- }
- }
- }
- }
- }
- }
- }
- }
- } else {
- logger.Debugw(ctx, "No MIB template found", log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
- }
- } else {
- logger.Errorf(ctx, "Get from kvstore operation failed for path",
- log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
- }
- if meStoredFromTemplate {
+ if oo.getMibFromTemplate(ctx) {
logger.Debug(ctx, "MibSync FSM - valid MEs stored from template")
oo.pOnuDB.logMeDb(ctx)
fsmMsg = LoadMibTemplateOk
@@ -248,14 +192,7 @@
func (oo *OnuDeviceEntry) enterExaminingMdsState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start GetMds processing in State": e.FSM.Current(), "device-id": oo.deviceID})
- // TODO: As long as story VOL-3834 "Avoid ONU service distruption on adapter restart" is not finished,
- // we need a full configuration cycle of the ONU to reconcile all local FSM data.
- // Therefore we simulate a failed MDS check here to trigger this config
- //oo.requestMdsValue(ctx)
- logger.Debugw(ctx, "MibSync FSM - MDS examination failed - new provisioning", log.Fields{"device-id": oo.deviceID})
- go func() {
- _ = oo.pMibUploadFsm.pFsm.Event(ulEvMismatch)
- }()
+ oo.requestMdsValue(ctx)
}
func (oo *OnuDeviceEntry) enterResynchronizingState(ctx context.Context, e *fsm.Event) {
@@ -268,6 +205,43 @@
// VOL-3793 - ONU-reconcile handling after adapter restart based on mib resync
}
+func (oo *OnuDeviceEntry) enterExaminingMdsSuccessState(ctx context.Context, e *fsm.Event) {
+ logger.Debugw(ctx, "MibSync FSM",
+ log.Fields{"Start processing on examining MDS success in State": e.FSM.Current(), "device-id": oo.deviceID})
+
+ if oo.getMibFromTemplate(ctx) {
+ oo.baseDeviceHandler.startReconciling(ctx, true)
+ oo.baseDeviceHandler.addAllUniPorts(ctx)
+ oo.baseDeviceHandler.setDeviceReason(drInitialMibDownloaded)
+ oo.baseDeviceHandler.ReadyForSpecificOmciConfig = true
+ // no need to reconcile additional data for MibDownloadFsm, LockStateFsm, or UnlockStateFsm
+
+ oo.baseDeviceHandler.reconcileDeviceTechProf(ctx)
+ if oo.baseDeviceHandler.isReconciling() {
+ oo.baseDeviceHandler.reconcileDeviceFlowConfig(ctx)
+ }
+ // set admin state independent of reconciling state after tp/flow reconcilement
+ if oo.sOnuPersistentData.PersUniDisableDone {
+ oo.baseDeviceHandler.disableUniPortStateUpdate(ctx)
+ oo.baseDeviceHandler.setDeviceReason(drOmciAdminLock)
+ } else {
+ oo.baseDeviceHandler.enableUniPortStateUpdate(ctx)
+ }
+ oo.baseDeviceHandler.stopReconciling(ctx)
+ go func() {
+ _ = oo.pMibUploadFsm.pFsm.Event(ulEvSuccess)
+ }()
+
+ } else {
+ logger.Debugw(ctx, "MibSync FSM",
+ log.Fields{"Getting MIB from template not successful": e.FSM.Current(), "device-id": oo.deviceID})
+ go func() {
+ //switch to reconciling with OMCI config
+ _ = oo.pMibUploadFsm.pFsm.Event(ulEvMismatch)
+ }()
+ }
+}
+
func (oo *OnuDeviceEntry) enterAuditingState(ctx context.Context, e *fsm.Event) {
logger.Debugw(ctx, "MibSync FSM", log.Fields{"Start MibAudit processing in State": e.FSM.Current(), "device-id": oo.deviceID})
if oo.baseDeviceHandler.checkAuditStartCondition(ctx, cUploadFsm) {
@@ -455,25 +429,25 @@
logger.Debugf(ctx, "MibSync FSM - GetResponse Data for %s", log.Fields{"device-id": oo.deviceID, "data-fields": msgObj}, meInstance)
switch meInstance {
case "OnuG":
- oo.vendorID = trimStringFromInterface(meAttributes["VendorId"])
+ oo.sOnuPersistentData.PersVendorID = trimStringFromInterface(meAttributes["VendorId"])
snBytes, _ := me.InterfaceToOctets(meAttributes["SerialNumber"])
if onugSerialNumberLen == len(snBytes) {
snVendorPart := fmt.Sprintf("%s", snBytes[:4])
snNumberPart := hex.EncodeToString(snBytes[4:])
- oo.serialNumber = snVendorPart + snNumberPart
+ oo.sOnuPersistentData.PersSerialNumber = snVendorPart + snNumberPart
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-G - VendorId/SerialNumber", log.Fields{"device-id": oo.deviceID,
- "onuDeviceEntry.vendorID": oo.vendorID, "onuDeviceEntry.serialNumber": oo.serialNumber})
+ "onuDeviceEntry.vendorID": oo.sOnuPersistentData.PersVendorID, "onuDeviceEntry.serialNumber": oo.sOnuPersistentData.PersSerialNumber})
} else {
logger.Infow(ctx, "MibSync FSM - SerialNumber has wrong length - fill serialNumber with zeros", log.Fields{"device-id": oo.deviceID, "length": len(snBytes)})
- oo.serialNumber = cEmptySerialNumberString
+ oo.sOnuPersistentData.PersSerialNumber = cEmptySerialNumberString
}
// trigger retrieval of EquipmentId
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetEquipmentID)
return nil
case "Onu2G":
- oo.equipmentID = trimStringFromInterface(meAttributes["EquipmentId"])
+ oo.sOnuPersistentData.PersEquipmentID = trimStringFromInterface(meAttributes["EquipmentId"])
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu2-G - EquipmentId", log.Fields{"device-id": oo.deviceID,
- "onuDeviceEntry.equipmentID": oo.equipmentID})
+ "onuDeviceEntry.equipmentID": oo.sOnuPersistentData.PersEquipmentID})
// trigger retrieval of 1st SW-image info
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetFirstSwVersion)
return nil
@@ -490,12 +464,12 @@
case "IpHostConfigData":
macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
if omciMacAddressLen == len(macBytes) {
- oo.macAddress = hex.EncodeToString(macBytes[:])
+ oo.sOnuPersistentData.PersMacAddress = hex.EncodeToString(macBytes[:])
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for IpHostConfigData - MacAddress", log.Fields{"device-id": oo.deviceID,
- "onuDeviceEntry.macAddress": oo.macAddress})
+ "macAddress": oo.sOnuPersistentData.PersMacAddress})
} else {
logger.Infow(ctx, "MibSync FSM - MacAddress wrong length - fill macAddress with zeros", log.Fields{"device-id": oo.deviceID, "length": len(macBytes)})
- oo.macAddress = cEmptyMacAddrString
+ oo.sOnuPersistentData.PersMacAddress = cEmptyMacAddrString
}
// trigger retrieval of mib template
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMibTemplate)
@@ -523,7 +497,7 @@
imageVersion := trimStringFromInterface(meAttributes["Version"])
logger.Infow(ctx, "MibSync FSM - GetResponse Data for SoftwareImage",
log.Fields{"device-id": oo.deviceID, "entityID": entityID,
- "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted, "SNR": oo.serialNumber})
+ "version": imageVersion, "isActive": imageIsActive, "isCommitted": imageIsCommitted, "SNR": oo.sOnuPersistentData.PersSerialNumber})
if firstSwImageMeID == entityID {
//always accept the state of the first image (2nd image info should not yet be available)
if imageIsActive == swIsActive {
@@ -614,7 +588,7 @@
case "IpHostConfigData":
logger.Debugw(ctx, "MibSync FSM - erroneous result for IpHostConfigData received - ONU doesn't support ME - fill macAddress with zeros",
log.Fields{"device-id": oo.deviceID, "data-fields": msgObj})
- oo.macAddress = cEmptyMacAddrString
+ oo.sOnuPersistentData.PersMacAddress = cEmptyMacAddrString
// trigger retrieval of mib template
_ = oo.pMibUploadFsm.pFsm.Event(ulEvGetMibTemplate)
return nil
@@ -743,9 +717,9 @@
logger.Debugw(ctx, "MibSync FSM - GetResponse Data for Onu-Data - MibDataSync", log.Fields{"device-id": oo.deviceID,
"mibDataSyncOnu": mibDataSyncOnu, "PersMibDataSyncAdpt": oo.sOnuPersistentData.PersMibDataSyncAdpt})
- mdsCheckOk := oo.sOnuPersistentData.PersMibDataSyncAdpt == mibDataSyncOnu
+ mdsValuesAreEqual := oo.sOnuPersistentData.PersMibDataSyncAdpt == mibDataSyncOnu
if oo.pMibUploadFsm.pFsm.Is(ulStAuditing) {
- if mdsCheckOk {
+ if mdsValuesAreEqual {
logger.Debugw(ctx, "MibSync FSM - mib audit - MDS check ok", log.Fields{"device-id": oo.deviceID})
_ = oo.pMibUploadFsm.pFsm.Event(ulEvSuccess)
} else {
@@ -753,7 +727,7 @@
_ = oo.pMibUploadFsm.pFsm.Event(ulEvMismatch)
}
} else if oo.pMibUploadFsm.pFsm.Is(ulStReAuditing) {
- if mdsCheckOk {
+ if mdsValuesAreEqual {
logger.Debugw(ctx, "MibSync FSM - mib reaudit - MDS check ok", log.Fields{"device-id": oo.deviceID})
_ = oo.pMibUploadFsm.pFsm.Event(ulEvSuccess)
} else {
@@ -762,7 +736,7 @@
_ = oo.pMibUploadFsm.pFsm.Event(ulEvMismatch)
}
} else if oo.pMibUploadFsm.pFsm.Is(ulStExaminingMds) {
- if mdsCheckOk {
+ if mdsValuesAreEqual && mibDataSyncOnu != 0 {
logger.Debugw(ctx, "MibSync FSM - MDS examination ok", log.Fields{"device-id": oo.deviceID})
_ = oo.pMibUploadFsm.pFsm.Event(ulEvSuccess)
} else {
@@ -801,3 +775,63 @@
}
return false //all other case are treated as 'nothing to commit
}
+func (oo *OnuDeviceEntry) getMibFromTemplate(ctx context.Context) bool {
+
+ oo.mibTemplatePath = oo.buildMibTemplatePath()
+ logger.Debugw(ctx, "MibSync FSM - get Mib from template", log.Fields{"path": fmt.Sprintf("%s/%s", cBasePathMibTemplateKvStore, oo.mibTemplatePath)})
+
+ restoredFromMibTemplate := false
+ Value, err := oo.mibTemplateKVStore.Get(log.WithSpanFromContext(context.TODO(), ctx), oo.mibTemplatePath)
+ if err == nil {
+ if Value != nil {
+ logger.Debugf(ctx, "MibSync FSM - Mib template read: Key: %s, Value: %s %s", Value.Key, Value.Value)
+
+ // swap out tokens with specific data
+ mibTmpString, _ := kvstore.ToString(Value.Value)
+ mibTmpString2 := strings.Replace(mibTmpString, "%SERIAL_NUMBER%", oo.sOnuPersistentData.PersSerialNumber, -1)
+ mibTmpString = strings.Replace(mibTmpString2, "%MAC_ADDRESS%", oo.sOnuPersistentData.PersMacAddress, -1)
+ mibTmpBytes := []byte(mibTmpString)
+ logger.Debugf(ctx, "MibSync FSM - Mib template tokens swapped out: %s", mibTmpBytes)
+
+ var firstLevelMap map[string]interface{}
+ if err = json.Unmarshal(mibTmpBytes, &firstLevelMap); err != nil {
+ logger.Errorw(ctx, "MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": oo.deviceID})
+ } else {
+ for firstLevelKey, firstLevelValue := range firstLevelMap {
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey", log.Fields{"firstLevelKey": firstLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(firstLevelKey, 10, 16); err == nil {
+ meClassID := me.ClassID(uint16ValidNumber)
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
+ if isSupportedClassID(meClassID) {
+ //logger.Debugw(ctx, "MibSync FSM - firstLevelKey is a supported classID", log.Fields{"meClassID": meClassID})
+ secondLevelMap := firstLevelValue.(map[string]interface{})
+ for secondLevelKey, secondLevelValue := range secondLevelMap {
+ //logger.Debugw(ctx, "MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
+ meEntityID := uint16(uint16ValidNumber)
+ //logger.Debugw(ctx, "MibSync FSM - secondLevelKey is a number and a valid EntityId", log.Fields{"meEntityID": meEntityID})
+ thirdLevelMap := secondLevelValue.(map[string]interface{})
+ for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
+ if thirdLevelKey == "Attributes" {
+ //logger.Debugw(ctx, "MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
+ attributesMap := thirdLevelValue.(map[string]interface{})
+ //logger.Debugw(ctx, "MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
+ oo.pOnuDB.PutMe(ctx, meClassID, meEntityID, attributesMap)
+ restoredFromMibTemplate = true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ logger.Debugw(ctx, "No MIB template found", log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ }
+ } else {
+ logger.Errorf(ctx, "Get from kvstore operation failed for path",
+ log.Fields{"path": oo.mibTemplatePath, "device-id": oo.deviceID})
+ }
+ return restoredFromMibTemplate
+}
diff --git a/internal/pkg/onuadaptercore/omci_ani_config.go b/internal/pkg/onuadaptercore/omci_ani_config.go
index 756b3f5..742a0ab 100644
--- a/internal/pkg/onuadaptercore/omci_ani_config.go
+++ b/internal/pkg/onuadaptercore/omci_ani_config.go
@@ -423,7 +423,7 @@
//ensure internal slices are empty (which might be set from previous run) - release memory
oFsm.gemPortAttribsSlice = nil
- // start go routine for processing of LockState messages
+ // start go routine for processing of ANI config messages
go oFsm.processOmciAniMessages(ctx)
//let the state machine run forward from here directly
diff --git a/internal/pkg/onuadaptercore/omci_vlan_config.go b/internal/pkg/onuadaptercore/omci_vlan_config.go
index 3a33a0f..d541ffd 100644
--- a/internal/pkg/onuadaptercore/omci_vlan_config.go
+++ b/internal/pkg/onuadaptercore/omci_vlan_config.go
@@ -102,8 +102,10 @@
vlanEvFlowDataRemoved = "vlanEvFlowDataRemoved"
//vlanEvTimeoutSimple = "vlanEvTimeoutSimple"
//vlanEvTimeoutMids = "vlanEvTimeoutMids"
- vlanEvReset = "vlanEvReset"
- vlanEvRestart = "vlanEvRestart"
+ vlanEvReset = "vlanEvReset"
+ vlanEvRestart = "vlanEvRestart"
+ vlanEvSkipOmciConfig = "vlanEvSkipOmciConfig"
+ vlanEvSkipIncFlowConfig = "vlanEvSkipIncFlowConfig"
)
const (
@@ -231,6 +233,10 @@
Dst: vlanStResetting},
// the only way to get to resource-cleared disabled state again is via "resseting"
{Name: vlanEvRestart, Src: []string{vlanStResetting}, Dst: vlanStDisabled},
+ // transitions for reconcile handling according to VOL-3834
+ {Name: vlanEvSkipOmciConfig, Src: []string{vlanStStarting}, Dst: vlanStConfigDone},
+ {Name: vlanEvSkipOmciConfig, Src: []string{vlanStConfigDone}, Dst: vlanStConfigIncrFlow},
+ {Name: vlanEvSkipIncFlowConfig, Src: []string{vlanStConfigIncrFlow}, Dst: vlanStConfigDone},
},
fsm.Callbacks{
"enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(ctx, e) },
@@ -449,12 +455,24 @@
"device-id": oFsm.deviceID})
oFsm.numUniFlows++
+ pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
+
+ if oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
+ logger.Debugw(ctx, "reconciling - skip omci-config of additional vlan rule",
+ log.Fields{"fsmState": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
+ oFsm.mutexFlowParams.Unlock()
+ if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvSkipOmciConfig)
+ }(pConfigVlanStateBaseFsm)
+ }
+ return nil
+ }
// note: theoretical it would be possible to clear the same rule from the remove slice
// (for entries that have not yet been started with removal)
// but that is getting quite complicated - maybe a future optimization in case it should prove reasonable
// anyway the precondition here is that the FSM checks for rules to delete first and adds new rules afterwards
- pConfigVlanStateBaseFsm := oFsm.pAdaptFsm.pFsm
if pConfigVlanStateBaseFsm.Is(vlanStConfigDone) {
//have to re-trigger the FSM to proceed with outstanding incremental flow configuration
if oFsm.configuredUniFlow == 0 {
@@ -801,8 +819,16 @@
//let the state machine run forward from here directly
pConfigVlanStateAFsm := oFsm.pAdaptFsm
if pConfigVlanStateAFsm != nil {
- oFsm.mutexFlowParams.Lock()
+ if oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
+ logger.Debugw(ctx, "reconciling - skip omci-config of vlan rule",
+ log.Fields{"fsmState": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
+ go func(a_pAFsm *AdapterFsm) {
+ _ = a_pAFsm.pFsm.Event(vlanEvSkipOmciConfig)
+ }(pConfigVlanStateAFsm)
+ return
+ }
+ oFsm.mutexFlowParams.Lock()
//possibly the entry is not valid anymore based on intermediate delete requests
//just a basic protection ...
if len(oFsm.uniVlanFlowParamsSlice) == 0 {
@@ -815,7 +841,6 @@
}(pConfigVlanStateAFsm)
return
}
-
//access to uniVlanFlowParamsSlice is done on first element only here per definition
//store the actual rule that shall be worked upon in the following transient states
oFsm.actualUniVlanConfigRule = oFsm.uniVlanFlowParamsSlice[0].VlanRuleParams
@@ -926,6 +951,7 @@
}
func (oFsm *UniVlanConfigFsm) enterVlanConfigDone(ctx context.Context, e *fsm.Event) {
+
oFsm.mutexFlowParams.RLock()
defer oFsm.mutexFlowParams.RUnlock()
@@ -953,6 +979,12 @@
return
}
if oFsm.numUniFlows > oFsm.configuredUniFlow {
+ if oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
+ oFsm.configuredUniFlow = oFsm.numUniFlows
+ logger.Debugw(ctx, "reconciling - skip enterVlanConfigDone processing",
+ log.Fields{"numUniFlows": oFsm.numUniFlows, "configuredUniFlow": oFsm.configuredUniFlow, "device-id": oFsm.deviceID})
+ return
+ }
if oFsm.configuredUniFlow == 0 {
// 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)
@@ -997,6 +1029,15 @@
}
func (oFsm *UniVlanConfigFsm) enterConfigIncrFlow(ctx context.Context, e *fsm.Event) {
+
+ if oFsm.pDeviceHandler.isSkipOnuConfigReconciling() {
+ logger.Debugw(ctx, "reconciling - skip further processing for incremental flow",
+ log.Fields{"fsmState": oFsm.pAdaptFsm.pFsm.Current(), "device-id": oFsm.deviceID})
+ go func(a_pBaseFsm *fsm.FSM) {
+ _ = a_pBaseFsm.Event(vlanEvSkipIncFlowConfig)
+ }(oFsm.pAdaptFsm.pFsm)
+ return
+ }
oFsm.mutexFlowParams.Lock()
logger.Debugw(ctx, "UniVlanConfigFsm - start config further incremental flow", log.Fields{
"in state": e.FSM.Current(), "recent flow-number": oFsm.configuredUniFlow,
@@ -1159,7 +1200,7 @@
oFsm.pLastTxMeInstance = meInstance
} else {
logger.Debugw(ctx, "UniVlanConfigFsm delete VTFD OMCI handling skipped based on device state", log.Fields{
- "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
+ "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.getDeviceReasonString()})
}
} else {
//many VTFD already should exists - find and remove the one concerned by the actual remove rule
@@ -1197,7 +1238,7 @@
oFsm.pLastTxMeInstance = meInstance
} else {
logger.Debugw(ctx, "UniVlanConfigFsm set VTFD OMCI handling skipped based on device state", log.Fields{
- "device-id": oFsm.deviceID, "device-state": deviceReasonMap[oFsm.pDeviceHandler.deviceReason]})
+ "device-id": oFsm.deviceID, "device-state": oFsm.pDeviceHandler.getDeviceReasonString()})
}
} else {
logger.Warnw(ctx, "UniVlanConfigFsm: requested VLAN for removal not found in list - ignore and continue (no VTFD set)",
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 25ffaa3..fa21e68 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -79,6 +79,7 @@
ulStInSync = "ulStInSync"
ulStExaminingMds = "ulStExaminingMds"
ulStResynchronizing = "ulStResynchronizing"
+ ulStExaminingMdsSuccess = "ulStExaminingMdsSuccess"
ulStAuditing = "ulStAuditing"
ulStReAuditing = "ulStReAuditing"
ulStOutOfSync = "ulStOutOfSync"
@@ -237,7 +238,11 @@
type onuPersistentData struct {
PersOnuID uint32 `json:"onu_id"`
PersIntfID uint32 `json:"intf_id"`
- PersSnr string `json:"serial_number"`
+ 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"`
@@ -266,12 +271,7 @@
onuKVStorePath string
onuKVStoreprocResult error //error indication of processing
chOnuKvProcessingStep chan uint8
- vendorID string
- serialNumber string
- equipmentID string
onuSwImageIndications sSwImageIndications
- activeSwVersion string
- macAddress string
//lockDeviceEntries sync.RWMutex
mibDbClass func(context.Context) error
supportedFsms OmciDeviceFsms
@@ -373,12 +373,16 @@
{Name: ulEvSuccess, Src: []string{ulStUploading}, Dst: ulStUploadDone},
{Name: ulEvSuccess, Src: []string{ulStUploadDone}, Dst: ulStInSync},
- {Name: ulEvSuccess, Src: []string{ulStExaminingMds}, Dst: ulStInSync},
+ //{Name: ulEvSuccess, Src: []string{ulStExaminingMds}, Dst: ulStInSync},
+ {Name: ulEvSuccess, Src: []string{ulStExaminingMds}, Dst: ulStExaminingMdsSuccess},
// TODO: As long as mib-resynchronizing is not implemented, failed MDS-examination triggers
// mib-reset and new provisioning at this point
//{Name: ulEvMismatch, Src: []string{ulStExaminingMds}, Dst: ulStResynchronizing},
{Name: ulEvMismatch, Src: []string{ulStExaminingMds}, Dst: ulStResettingMib},
+ {Name: ulEvSuccess, Src: []string{ulStExaminingMdsSuccess}, Dst: ulStInSync},
+ {Name: ulEvMismatch, Src: []string{ulStExaminingMdsSuccess}, Dst: ulStResettingMib},
+
{Name: ulEvAuditMib, Src: []string{ulStInSync}, Dst: ulStAuditing},
{Name: ulEvSuccess, Src: []string{ulStOutOfSync}, Dst: ulStInSync},
@@ -412,11 +416,12 @@
"enter_" + ulStGettingFirstSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingFirstSwVersionState(ctx, e) },
"enter_" + ulStGettingSecondSwVersion: func(e *fsm.Event) { onuDeviceEntry.enterGettingSecondSwVersionState(ctx, e) },
"enter_" + ulStGettingMacAddress: func(e *fsm.Event) { onuDeviceEntry.enterGettingMacAddressState(ctx, e) },
- "enter_" + ulStGettingMibTemplate: func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplate(ctx, e) },
+ "enter_" + ulStGettingMibTemplate: func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplateState(ctx, e) },
"enter_" + ulStUploading: func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(ctx, e) },
"enter_" + ulStUploadDone: func(e *fsm.Event) { onuDeviceEntry.enterUploadDoneState(ctx, e) },
"enter_" + ulStExaminingMds: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(ctx, e) },
"enter_" + ulStResynchronizing: func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(ctx, e) },
+ "enter_" + ulStExaminingMdsSuccess: func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsSuccessState(ctx, e) },
"enter_" + ulStAuditing: func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(ctx, e) },
"enter_" + ulStReAuditing: func(e *fsm.Event) { onuDeviceEntry.enterReAuditingState(ctx, e) },
"enter_" + ulStOutOfSync: func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(ctx, e) },
@@ -586,7 +591,8 @@
}
oo.persUniConfigMutex.Lock()
defer oo.persUniConfigMutex.Unlock()
- oo.sOnuPersistentData = onuPersistentData{0, 0, "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0)}
+ oo.sOnuPersistentData =
+ onuPersistentData{0, 0, "", "", "", "", "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0)}
oo.onuKVStoreMutex.RLock()
Value, err := oo.onuKVStore.Get(ctx, oo.onuKVStorePath)
oo.onuKVStoreMutex.RUnlock()
@@ -638,9 +644,9 @@
oo.persUniConfigMutex.Lock()
defer oo.persUniConfigMutex.Unlock()
- oo.sOnuPersistentData.PersUniConfig = nil //releasing all UniConfig entries to garbage collector
- oo.sOnuPersistentData = onuPersistentData{0, 0, "", "", "", false, false, oo.mibAuditInterval, 0, 0, make([]uniPersConfig, 0)} //default entry
-
+ 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)}
logger.Debugw(ctx, "delete ONU-data from KVStore", log.Fields{"device-id": oo.deviceID})
oo.onuKVStoreMutex.Lock()
err := oo.onuKVStore.Delete(ctx, oo.onuKVStorePath)
@@ -676,7 +682,6 @@
//assign values which are not already present when newOnuDeviceEntry() is called
oo.sOnuPersistentData.PersOnuID = oo.baseDeviceHandler.pOnuIndication.OnuId
oo.sOnuPersistentData.PersIntfID = oo.baseDeviceHandler.pOnuIndication.IntfId
- oo.sOnuPersistentData.PersSnr = oo.baseDeviceHandler.pOnuOmciDevice.serialNumber
//TODO: verify usage of these values during restart UC
oo.sOnuPersistentData.PersAdminState = oo.baseDeviceHandler.pOnuIndication.AdminState
oo.sOnuPersistentData.PersOperState = oo.baseDeviceHandler.pOnuIndication.OperState
@@ -828,3 +833,7 @@
}
logger.Debugf(ctx, "mibDataSync updated - mds: %d - device-id: %s", oo.sOnuPersistentData.PersMibDataSyncAdpt, oo.deviceID)
}
+
+func (oo *OnuDeviceEntry) buildMibTemplatePath() string {
+ return fmt.Sprintf(cSuffixMibTemplateKvStore, oo.sOnuPersistentData.PersVendorID, oo.sOnuPersistentData.PersEquipmentID, oo.sOnuPersistentData.PersActiveSwVersion)
+}
diff --git a/internal/pkg/onuadaptercore/onu_uni_tp.go b/internal/pkg/onuadaptercore/onu_uni_tp.go
index 0ab368e..3fdbe19 100644
--- a/internal/pkg/onuadaptercore/onu_uni_tp.go
+++ b/internal/pkg/onuadaptercore/onu_uni_tp.go
@@ -227,6 +227,14 @@
return
}
+ if onuTP.baseDeviceHandler.isSkipOnuConfigReconciling() {
+ logger.Debugw(ctx, "reconciling - skip omci-config of ANI side ", log.Fields{"uni-id": aUniID, "device-id": onuTP.deviceID})
+ if _, existTP := onuTP.mapUniTpIndication[uniTpKey]; existTP {
+ onuTP.mapUniTpIndication[uniTpKey].techProfileConfigDone = true
+ }
+ return
+ }
+
processingStep++
valuePA, existPA := onuTP.mapPonAniConfig[uniTpKey]
@@ -633,7 +641,7 @@
}
} else {
logger.Debugw(ctx, "uniPonAniConfigFsm delete Gem on OMCI skipped based on device state", log.Fields{
- "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.deviceReason})
+ "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.getDeviceReasonString()})
}
// remove GemPort from config DB
delete(onuTP.mapPonAniConfig[uniTPKey].mapGemPortParams, onuTP.mapRemoveGemEntry[uniTPKey].removeGemID)
@@ -713,7 +721,7 @@
}
} else {
logger.Debugw(ctx, "uniPonAniConfigFsm TCont cleanup on OMCI skipped based on device state", log.Fields{
- "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.deviceReason})
+ "device-id": onuTP.deviceID, "device-state": onuTP.baseDeviceHandler.getDeviceReasonString()})
}
//clear the internal store profile data
onuTP.clearAniSideConfig(ctx, aUniID, aTpID)
@@ -744,7 +752,7 @@
}
}
-// createUniLockFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
+// createAniConfigFsm initializes and runs the AniConfig FSM to transfer the OMCI related commands for ANI side configuration
func (onuTP *onuUniTechProf) createAniConfigFsm(ctx context.Context, aUniID uint8, aTpID uint8,
apCurrentUniPort *onuUniPort, devEvent OnuDeviceEvent, aProcessingStep uint8) error {
logger.Debugw(ctx, "createAniConfigFsm", log.Fields{"device-id": onuTP.deviceID})
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index eb1aaba..3f98031 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -322,7 +322,7 @@
handler := newDeviceHandler(ctx, oo.coreProxy, oo.adapterProxy, oo.eventProxy, device, oo)
oo.addDeviceHandlerToMap(ctx, handler)
handler.device = device
- handler.startReconciling(ctx)
+ handler.startReconciling(ctx, false)
go handler.adoptOrReconcileDevice(ctx, handler.device)
// reconcilement will be continued after onu-device entry is added
} else {