[VOL-3041] - Configuration of port admin state
[VOL-3036] - Read MIB Templates from ETCD
Change-Id: I55b9553104701bf9ecd873a218c9aeffca782cd1
Signed-off-by: Holger Hildebrandt <holger.hildebrandt@adtran.com>
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index e5946f4..b67ceab 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -92,9 +92,9 @@
exitChannel chan int
lockDevice sync.RWMutex
pOnuIndication *oop.OnuIndication
+ pLockStateFsm *LockStateFsm
+ pUnlockStateFsm *LockStateFsm
- //Client oop.OpenoltClient
- //clientCon *grpc.ClientConn
//flowMgr *OpenOltFlowMgr
//eventMgr *OpenOltEventMgr
//resourceMgr *rsrcMgr.OpenOltResourceMgr
@@ -174,12 +174,12 @@
func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
logger.Debugw("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
- logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
+ logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
if dh.pDeviceStateFsm.Is("null") {
if err := dh.pDeviceStateFsm.Event("DeviceInit"); err != nil {
logger.Errorw("Device FSM: Can't go to state DeviceInit", log.Fields{"err": err})
}
- logger.Debug("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
+ logger.Debugw("Device FSM: ", log.Fields{"state": string(dh.pDeviceStateFsm.Current())})
} else {
logger.Debug("AdoptDevice: Agent/device init already done")
}
@@ -287,32 +287,52 @@
return nil
}
+//DisableDevice locks the ONU and its UNI/VEIP ports (admin lock via OMCI)
func (dh *DeviceHandler) DisableDevice(device *voltha.Device) {
- logger.Debug("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
- // and disable port
- // yield self.disable_ports(lock_ports=True, device_disabled=True)
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "OmciAdminLock"); err != nil {
- logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+ logger.Debugw("disable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+
+ // disable UNI ports/ONU
+ // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
+ // here the result of the processing is not checked (trusted in background) *****
+ if dh.pLockStateFsm == nil {
+ dh.createUniLockFsm(true, UniAdminStateDone)
+ } else { //LockStateFSM already init
+ dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
+ dh.runUniLockFsm(true)
}
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "omci-admin-lock"); err != nil {
+ logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+ }
+ // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
voltha.OperStatus_UNKNOWN); err != nil {
logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
}
}
+//ReenableDevice unlocks the ONU and its UNI/VEIP ports (admin unlock via OMCI)
func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) {
- logger.Debug("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+ logger.Debugw("reenable-device", log.Fields{"DeviceId": device.Id, "SerialNumber": device.SerialNumber})
+ // TODO!!! ConnectStatus and OperStatus to be set here could be more accurate, for now just ...
if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID, voltha.ConnectStatus_REACHABLE,
voltha.OperStatus_ACTIVE); err != nil {
logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
}
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "InitialMibDownloaded"); err != nil {
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
logger.Errorw("error-updating-reason-state", log.Fields{"deviceID": dh.deviceID, "error": err})
}
- // and enable port
- // yield self.enable_ports(device)
+
+ // enable ONU/UNI ports
+ // *** should generate UniAdminStateDone event - unrelated to DeviceProcStatusUpdate!!
+ // here the result of the processing is not checked (trusted in background) *****
+ if dh.pUnlockStateFsm == nil {
+ dh.createUniLockFsm(false, UniAdminStateDone)
+ } else { //UnlockStateFSM already init
+ dh.pLockStateFsm.SetSuccessEvent(UniAdminStateDone)
+ dh.runUniLockFsm(false)
+ }
}
func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device,
@@ -627,7 +647,8 @@
we omit that here first (declaration unclear) -> todo at Adapter specialization ...*/
/* also no 'clock' argument - usage open ...*/
/* and no alarm_db yet (oo.alarm_db) */
- deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh, dh.coreProxy, dh.AdapterProxy,
+ deviceEntry = NewOnuDeviceEntry(ctx, dh.deviceID, dh.pOpenOnuAc.KVStoreHost, dh.pOpenOnuAc.KVStorePort, dh.pOpenOnuAc.KVStoreType,
+ dh, dh.coreProxy, dh.AdapterProxy,
dh.pOpenOnuAc.pSupportedFsms) //nil as FSM pointer would yield deviceEntry internal defaults ...
//error treatment possible //TODO!!!
dh.SetOnuDeviceEntry(deviceEntry)
@@ -767,36 +788,17 @@
logger.Errorw("MibSyncFsm: Can't go to state starting", log.Fields{"err": err})
return errors.New("Can't go to state starting")
} else {
- logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
+ logger.Debugw("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
//Determine ONU status and start/re-start MIB Synchronization tasks
//Determine if this ONU has ever synchronized
if true { //TODO: insert valid check
if err := pMibUlFsm.Event("load_mib_template"); err != nil {
logger.Errorw("MibSyncFsm: Can't go to state loading_mib_template", log.Fields{"err": err})
return errors.New("Can't go to state loading_mib_template")
- } else {
- logger.Debug("MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
- //Find and load a mib template. If not found proceed with mib_upload
- // callbacks to be handled:
- // Event("success")
- // Event("timeout")
- //no mib template found
- if true { //TODO: insert valid check
- if err := pMibUlFsm.Event("upload_mib"); err != nil {
- logger.Errorw("MibSyncFsm: Can't go to state uploading", log.Fields{"err": err})
- return errors.New("Can't go to state uploading")
- } else {
- logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
- //Begin full MIB data upload, starting with a MIB RESET
- // callbacks to be handled:
- // success: e.Event("success")
- // failure: e.Event("timeout")
- }
- }
}
} else {
pMibUlFsm.Event("examine_mds")
- logger.Debug("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
+ logger.Debugw("state of MibSyncFsm", log.Fields{"state": string(pMibUlFsm.Current())})
//Examine the MIB Data Sync
// callbacks to be handled:
// Event("success")
@@ -819,75 +821,122 @@
return nil
}
-func (dh *DeviceHandler) DeviceStateUpdate(dev_Event OnuDeviceEvent) {
- if dev_Event == MibDatabaseSync {
- logger.Debugw("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
- //initiate DevStateUpdate
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
- logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{"deviceID": dh.deviceID, "error": err})
- }
-
- unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
- unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
- if ok {
- i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
- for _, mgmtEntityId := range unigInstKeys {
- logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID, "UnigMe EntityID": mgmtEntityId})
- dh.addUniPort(mgmtEntityId, i, UniPPTP)
- i++
+func (dh *DeviceHandler) DeviceProcStatusUpdate(dev_Event OnuDeviceEvent) {
+ switch dev_Event {
+ case MibDatabaseSync:
+ {
+ logger.Infow("MibInSync event: update dev state to 'MibSync complete'", log.Fields{"deviceID": dh.deviceID})
+ //initiate DevStateUpdate
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "discovery-mibsync-complete"); err != nil {
+ logger.Errorw("error-DeviceReasonUpdate to 'mibsync-complete'", log.Fields{
+ "deviceID": dh.deviceID, "error": err})
}
- } else {
- logger.Warnw("No UniG instances found!", log.Fields{"deviceId": dh.GetOnuDeviceEntry().deviceID})
- }
- /* real Mib download procedure could look somthing like this:
- ***** but for the moment the FSM is still limited (sending no OMCI) *****
- ***** thus never reaches 'downloaded' state *****
- */
- pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
- if pMibDlFsm != nil {
- if pMibDlFsm.Is("disabled") {
- if err := pMibDlFsm.Event("start"); err != nil {
- logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
- // maybe try a FSM reset and then again ... - TODO!!!
- } else {
- logger.Debug("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
- // maybe use more specific states here for the specific download steps ...
- if err := pMibDlFsm.Event("create_gal"); err != nil {
- logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
- } else {
- logger.Debug("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
- //Begin MIB data download (running autonomously)
- }
+ unigMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.UniGClassID]
+ unigInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(unigMap)
+ i := uint8(0) //UNI Port limit: see MaxUnisPerOnu (by now 16) (OMCI supports max 255 p.b.)
+ if ok {
+ for _, mgmtEntityId := range unigInstKeys {
+ logger.Debugw("Add UNI port for stored UniG instance:", log.Fields{
+ "deviceId": dh.deviceID, "UnigMe EntityID": mgmtEntityId})
+ dh.addUniPort(mgmtEntityId, i, UniPPTP)
+ i++
}
} else {
- logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
- // maybe try a FSM reset and then again ... - TODO!!!
+ logger.Debugw("No UniG instances found", log.Fields{"deviceId": dh.deviceID})
}
- /***** Mib download started */
- } else {
- logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
- }
- } else if dev_Event == MibDownloadDone {
- logger.Debugw("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
- //initiate DevStateUpdate
- if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
- voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
- logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
- }
- logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
- if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
- logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
- log.Fields{"deviceID": dh.deviceID, "error": err})
- }
+ veipMap, ok := dh.GetOnuDeviceEntry().pOnuDB.meDb[me.VirtualEthernetInterfacePointClassID]
+ veipInstKeys := dh.GetOnuDeviceEntry().pOnuDB.GetSortedInstKeys(veipMap)
+ if ok {
+ for _, mgmtEntityId := range veipInstKeys {
+ logger.Debugw("Add VEIP acc. to stored VEIP instance:", log.Fields{
+ "deviceId": dh.deviceID, "VEIP EntityID": mgmtEntityId})
+ dh.addUniPort(mgmtEntityId, i, UniVEIP)
+ i++
+ }
+ } else {
+ logger.Debugw("No VEIP instances found", log.Fields{"deviceId": dh.deviceID})
+ }
+ if i == 0 {
+ logger.Warnw("No PPTP instances found", log.Fields{"deviceId": dh.deviceID})
+ }
- go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
+ // Init Uni Ports to Admin locked state
+ // maybe not really needed here as UNI ports should be locked by default, but still left as available in python code
+ // *** should generate UniLockStateDone event *****
+ if dh.pLockStateFsm == nil {
+ dh.createUniLockFsm(true, UniLockStateDone)
+ } else { //LockStateFSM already init
+ dh.pLockStateFsm.SetSuccessEvent(UniLockStateDone)
+ dh.runUniLockFsm(true)
+ }
+ }
+ case UniLockStateDone:
+ {
+ logger.Infow("UniLockStateDone event: Starting MIB download", log.Fields{"deviceID": dh.deviceID})
+ /* Mib download procedure -
+ ***** should run over 'downloaded' state and generate MibDownloadDone event *****
+ */
+ pMibDlFsm := dh.GetOnuDeviceEntry().pMibDownloadFsm.pFsm
+ if pMibDlFsm != nil {
+ if pMibDlFsm.Is("disabled") {
+ if err := pMibDlFsm.Event("start"); err != nil {
+ logger.Errorw("MibDownloadFsm: Can't go to state starting", log.Fields{"err": err})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ } else {
+ logger.Debugw("MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+ // maybe use more specific states here for the specific download steps ...
+ if err := pMibDlFsm.Event("create_gal"); err != nil {
+ logger.Errorw("MibDownloadFsm: Can't start CreateGal", log.Fields{"err": err})
+ } else {
+ logger.Debugw("state of MibDownloadFsm", log.Fields{"state": string(pMibDlFsm.Current())})
+ //Begin MIB data download (running autonomously)
+ }
+ }
+ } else {
+ logger.Errorw("wrong state of MibDownloadFsm - want: disabled", log.Fields{"have": string(pMibDlFsm.Current())})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ }
+ /***** Mib download started */
+ } else {
+ logger.Errorw("MibDownloadFsm invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
+ }
+ }
+ case MibDownloadDone:
+ {
+ logger.Infow("MibDownloadDone event: update dev state to 'Oper.Active'", log.Fields{"deviceID": dh.deviceID})
+ //initiate DevStateUpdate
+ if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.deviceID,
+ voltha.ConnectStatus_REACHABLE, voltha.OperStatus_ACTIVE); err != nil {
+ logger.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.deviceID, "error": err})
+ }
+ logger.Debug("MibDownloadDone Event: update dev reason to 'initial-mib-downloaded'")
+ if err := dh.coreProxy.DeviceReasonUpdate(context.TODO(), dh.deviceID, "initial-mib-downloaded"); err != nil {
+ logger.Errorw("error-DeviceReasonUpdate to 'initial-mib-downloaded'",
+ log.Fields{"deviceID": dh.deviceID, "error": err})
+ }
- raisedTs := time.Now().UnixNano()
- go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
- } else {
- logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
- }
+ // *** should generate UniUnlockStateDone event *****
+ if dh.pUnlockStateFsm == nil {
+ dh.createUniLockFsm(false, UniUnlockStateDone)
+ } else { //UnlockStateFSM already init
+ dh.pUnlockStateFsm.SetSuccessEvent(UniUnlockStateDone)
+ dh.runUniLockFsm(false)
+ }
+ }
+ case UniUnlockStateDone:
+ {
+ go dh.enableUniPortStateUpdate(dh.deviceID) //cmp python yield self.enable_ports()
+
+ logger.Infow("UniUnlockStateDone event: Sending OnuUp event", log.Fields{"deviceID": dh.deviceID})
+ raisedTs := time.Now().UnixNano()
+ go dh.sendOnuOperStateEvent(voltha.OperStatus_ACTIVE, dh.deviceID, raisedTs) //cmp python onu_active_event
+ }
+ default:
+ {
+ logger.Warnw("unhandled-device-event", log.Fields{"deviceID": dh.deviceID, "event": dev_Event})
+ }
+ } //switch
}
func (dh *DeviceHandler) addUniPort(a_uniInstNo uint16, a_uniId uint8, a_portType UniPortType) {
@@ -920,7 +969,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
- // dh.lock_ports(false) ONU port activation via OMCI //TODO!!! not yet supported
+ // lock_ports(false) as done in py code here is shifted to separate call from devicevent processing
for uniNo, uniPort := range dh.uniEntityMap {
// only if this port is validated for operState transfer}
@@ -977,6 +1026,73 @@
log.Fields{"DeviceId": a_deviceID, "with-EventName": de.DeviceEventName})
}
+// createUniLockFsm initialises and runs the UniLock FSM to transfer teh OMCi related commands for port lock/unlock
+func (dh *DeviceHandler) createUniLockFsm(aAdminState bool, devEvent OnuDeviceEvent) {
+ chLSFsm := make(chan Message, 2048)
+ var sFsmName string
+ if aAdminState == true {
+ logger.Infow("createLockStateFSM", log.Fields{"deviceID": dh.deviceID})
+ sFsmName = "LockStateFSM"
+ } else {
+ logger.Infow("createUnlockStateFSM", log.Fields{"deviceID": dh.deviceID})
+ sFsmName = "UnLockStateFSM"
+ }
+ pLSFsm := NewLockStateFsm(dh.GetOnuDeviceEntry().PDevOmciCC, aAdminState, devEvent,
+ sFsmName, dh.deviceID, chLSFsm)
+ if pLSFsm != nil {
+ if aAdminState == true {
+ dh.pLockStateFsm = pLSFsm
+ } else {
+ dh.pUnlockStateFsm = pLSFsm
+ }
+ dh.runUniLockFsm(aAdminState)
+ } else {
+ logger.Errorw("LockStateFSM could not be created - abort!!", log.Fields{"deviceID": dh.deviceID})
+ }
+}
+
+// runUniLockFsm starts the UniLock FSM to transfer the OMCI related commands for port lock/unlock
+func (dh *DeviceHandler) runUniLockFsm(aAdminState bool) {
+ /* Uni Port lock/unlock procedure -
+ ***** should run via 'adminDone' state and generate the argument requested event *****
+ */
+ var pLSStatemachine *fsm.FSM
+ if aAdminState == true {
+ pLSStatemachine = dh.pLockStateFsm.pAdaptFsm.pFsm
+ //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
+ if (dh.pUnlockStateFsm != nil) &&
+ (dh.pUnlockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
+ dh.pUnlockStateFsm.pAdaptFsm.pFsm.Event("reset")
+ }
+ } else {
+ pLSStatemachine = dh.pUnlockStateFsm.pAdaptFsm.pFsm
+ //make sure the opposite FSM is not running and if so, terminate it as not relevant anymore
+ if (dh.pLockStateFsm != nil) &&
+ (dh.pLockStateFsm.pAdaptFsm.pFsm.Current() != "disabled") {
+ dh.pLockStateFsm.pAdaptFsm.pFsm.Event("reset")
+ }
+ }
+ if pLSStatemachine != nil {
+ if pLSStatemachine.Is("disabled") {
+ if err := pLSStatemachine.Event("start"); err != nil {
+ logger.Warnw("LockStateFSM: can't start", log.Fields{"err": err})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ } else {
+ /***** LockStateFSM started */
+ logger.Debugw("LockStateFSM started", log.Fields{
+ "state": pLSStatemachine.Current(), "deviceID": dh.deviceID})
+ }
+ } else {
+ logger.Warnw("wrong state of LockStateFSM - want: disabled", log.Fields{
+ "have": pLSStatemachine.Current(), "deviceID": dh.deviceID})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ }
+ } else {
+ logger.Errorw("LockStateFSM StateMachine invalid - cannot be executed!!", log.Fields{"deviceID": dh.deviceID})
+ // maybe try a FSM reset and then again ... - TODO!!!
+ }
+}
+
/* *********************************************************** */
func genMacFromOctets(a_octets [6]uint8) string {