[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 {
diff --git a/internal/pkg/onuadaptercore/messageTypes.go b/internal/pkg/onuadaptercore/messageTypes.go
index b3e9191..a5d5aff 100644
--- a/internal/pkg/onuadaptercore/messageTypes.go
+++ b/internal/pkg/onuadaptercore/messageTypes.go
@@ -22,11 +22,11 @@
"github.com/opencord/omci-lib-go"
)
-type MessageType int
+type MessageType uint8
const (
- TestMsg MessageType = 0
- OMCI MessageType = 1
+ TestMsg MessageType = iota
+ OMCI
)
func (m MessageType) String() string {
@@ -42,14 +42,19 @@
Data interface{}
}
+type TestMessageType uint8
+
const (
- AnyTriggerForMibSyncUploadMib = 0
- AbortMessageProcessing = 1
+ noOperation TestMessageType = iota
+ LoadMibTemplateOk
+ LoadMibTemplateFailed
+ TimeOutOccurred
+ AbortMessageProcessing
)
//TODO: place holder to have a second interface variant - to be replaced by real variant later on
type TestMessage struct {
- TestMessageVal uint32
+ TestMessageVal TestMessageType
}
type OmciMessage struct {
diff --git a/internal/pkg/onuadaptercore/mib_download.go b/internal/pkg/onuadaptercore/mib_download.go
index 03c328d..8d00188 100644
--- a/internal/pkg/onuadaptercore/mib_download.go
+++ b/internal/pkg/onuadaptercore/mib_download.go
@@ -41,7 +41,6 @@
}
// start go routine for processing of MibDownload messages
go onuDeviceEntry.ProcessMibDownloadMessages()
- //possibly include a further MibReset here in order to enforce reset of incomplete set data ...(TODO?)
}
func (onuDeviceEntry *OnuDeviceEntry) enterCreatingGalState(e *fsm.Event) {
@@ -61,7 +60,7 @@
}
func (onuDeviceEntry *OnuDeviceEntry) enterBridgeInitState(e *fsm.Event) {
- logger.Debugw("MibDownload FSM - starting bridge config loop", log.Fields{
+ logger.Infow("MibDownload FSM - starting bridge config port loop", log.Fields{
"in state": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
go onuDeviceEntry.performInitialBridgeSetup()
}
@@ -86,13 +85,13 @@
pMibDlFsm := onuDeviceEntry.pMibDownloadFsm
if pMibDlFsm != nil {
// abort running message processing
- mibSyncMsg := Message{
+ fsmAbortMsg := Message{
Type: TestMsg,
Data: TestMessage{
TestMessageVal: AbortMessageProcessing,
},
}
- pMibDlFsm.commChan <- mibSyncMsg
+ pMibDlFsm.commChan <- fsmAbortMsg
//try to restart the FSM to 'disabled'
// see DownloadedState: decouple event transfer
@@ -206,12 +205,6 @@
logger.Error("Omci Msg layer could not be assigned for SetResponse")
return
}
- logger.Debugw("SetResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
- if msgObj.Result != me.Success {
- logger.Errorw("Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
- // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
- return
- }
logger.Debugw("SetResponse Data", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
if msgObj.Result != me.Success {
logger.Errorw("Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
@@ -233,9 +226,6 @@
//so far that was the only MibDownlad Set Element ...
}
}
-
- // TODO!!!: further needed processing here ....
-
} //SetResponseType
default:
{
@@ -247,7 +237,7 @@
func (onuDeviceEntry *OnuDeviceEntry) performInitialBridgeSetup() {
for uniNo, uniPort := range onuDeviceEntry.baseDeviceHandler.uniEntityMap {
- logger.Infow("Starting IntialBridgeSetup", log.Fields{
+ logger.Debugw("Starting IntialBridgeSetup", log.Fields{
"deviceId": onuDeviceEntry.deviceID, "for PortNo": uniNo})
//create MBSP
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index d15ae03..d5f2696 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -19,7 +19,10 @@
import (
"context"
+ "encoding/json"
"errors"
+ "fmt"
+ "strconv"
"github.com/looplab/fsm"
@@ -29,12 +32,37 @@
//"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
"github.com/opencord/omci-lib-go"
me "github.com/opencord/omci-lib-go/generated"
+ "github.com/opencord/voltha-lib-go/v3/pkg/db"
+ "github.com/opencord/voltha-lib-go/v3/pkg/db/kvstore"
"github.com/opencord/voltha-lib-go/v3/pkg/log"
//ic "github.com/opencord/voltha-protos/v3/go/inter_container"
//"github.com/opencord/voltha-protos/v3/go/openflow_13"
//"github.com/opencord/voltha-protos/v3/go/voltha"
)
+var supportedClassIds = []me.ClassID{
+ me.CardholderClassID, // 5
+ me.CircuitPackClassID, // 6
+ me.SoftwareImageClassID, // 7
+ me.PhysicalPathTerminationPointEthernetUniClassID, // 11
+ me.OltGClassID, // 131
+ me.OnuPowerSheddingClassID, // 133
+ me.IpHostConfigDataClassID, // 134
+ me.OnuGClassID, // 256
+ me.Onu2GClassID, // 257
+ me.TContClassID, // 262
+ me.AniGClassID, // 263
+ me.UniGClassID, // 264
+ me.PriorityQueueClassID, // 277
+ me.TrafficSchedulerClassID, // 278
+ me.VirtualEthernetInterfacePointClassID, // 329
+ me.EnhancedSecurityControlClassID, // 332
+ me.OnuDynamicPowerManagementControlClassID, // 336
+ // 347 // definitions for ME "IPv6 host config data" are currently missing in omci-lib-go!
+}
+
+var fsmMsg TestMessageType
+
func (onuDeviceEntry *OnuDeviceEntry) enterStartingState(e *fsm.Event) {
logger.Debugw("MibSync FSM", log.Fields{"Start processing MibSync-msgs in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
@@ -45,7 +73,85 @@
func (onuDeviceEntry *OnuDeviceEntry) enterLoadingMibTemplateState(e *fsm.Event) {
logger.Debugw("MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
- logger.Debug("function not implemented yet")
+
+ meStoredFromTemplate := false
+
+ //TODO: perform MIB-reset
+ //TODO: needs to handle timeouts
+
+ //TODO: etrieve these values via OMCI GetRequests
+ //OltGClassID
+ onuDeviceEntry.vendorID = "BBSM"
+ onuDeviceEntry.serialNumber = "BBSM00000001"
+ //Onu2GClassID
+ onuDeviceEntry.equipmentID = "12345123451234512345"
+ //SoftwareImageClassID
+ onuDeviceEntry.activeSwVersion = "00000000000001"
+ //IpHostConfigDataClassID
+ onuDeviceEntry.macAddress = "00:00:00:00:00:00"
+
+ Path := fmt.Sprintf(SuffixMibTemplateKvStore, onuDeviceEntry.vendorID, onuDeviceEntry.equipmentID, onuDeviceEntry.activeSwVersion)
+ Value, err := onuDeviceEntry.mibTemplateKVStore.Get(context.TODO(), Path)
+ if err == nil {
+ if Value != nil {
+ logger.Debugf("MibSync FSM - MibTemplate read: Key: %s, Value: %s %s", Value.Key, Value.Value)
+ mibTmpBytes, _ := kvstore.ToByte(Value.Value)
+
+ var fistLevelMap map[string]interface{}
+ if err = json.Unmarshal(mibTmpBytes, &fistLevelMap); err != nil {
+ logger.Error("MibSync FSM - Failed to unmarshal template", log.Fields{"error": err, "device-id": onuDeviceEntry.deviceID})
+ } else {
+ for fistLevelKey, firstLevelValue := range fistLevelMap {
+ logger.Debugw("MibSync FSM - fistLevelKey", log.Fields{"fistLevelKey": fistLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(fistLevelKey, 10, 16); err == nil {
+ meClassId := me.ClassID(uint16ValidNumber)
+ logger.Debugw("MibSync FSM - fistLevelKey is a number in uint16-range", log.Fields{"uint16ValidNumber": uint16ValidNumber})
+ if IsSupportedClassId(meClassId) {
+ logger.Debugw("MibSync FSM - fistLevelKey is a supported classId", log.Fields{"meClassId": meClassId})
+ secondLevelMap := firstLevelValue.(map[string]interface{})
+ for secondLevelKey, secondLevelValue := range secondLevelMap {
+ logger.Debugw("MibSync FSM - secondLevelKey", log.Fields{"secondLevelKey": secondLevelKey})
+ if uint16ValidNumber, err := strconv.ParseUint(secondLevelKey, 10, 16); err == nil {
+ meEntityId := uint16(uint16ValidNumber)
+ logger.Debugw("MibSync FSM - secondLevelKey is a numberand a valid EntityId", log.Fields{"meEntityId": meEntityId})
+ thirdLevelMap := secondLevelValue.(map[string]interface{})
+ for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
+ if thirdLevelKey == "attributes" {
+ logger.Debugw("MibSync FSM - thirdLevelKey refers to attributes", log.Fields{"thirdLevelKey": thirdLevelKey})
+ attributesMap := thirdLevelValue.(map[string]interface{})
+ logger.Debugw("MibSync FSM - attributesMap", log.Fields{"attributesMap": attributesMap})
+ onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, attributesMap)
+ meStoredFromTemplate = true
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {
+ logger.Debugw("No MIB template found", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ }
+ } else {
+ logger.Errorf("Get from kvstore operation failed for path %s", Path)
+ }
+ if meStoredFromTemplate {
+ logger.Debug("MibSync FSM - valid MEs stored from template")
+ onuDeviceEntry.pOnuDB.LogMeDb()
+ fsmMsg = LoadMibTemplateOk
+ } else {
+ logger.Debug("MibSync FSM - no valid MEs stored from template - perform MIB-upload!")
+ fsmMsg = LoadMibTemplateFailed
+ }
+
+ mibSyncMsg := Message{
+ Type: TestMsg,
+ Data: TestMessage{
+ TestMessageVal: fsmMsg,
+ },
+ }
+ onuDeviceEntry.pMibUploadFsm.commChan <- mibSyncMsg
}
func (onuDeviceEntry *OnuDeviceEntry) enterUploadingState(e *fsm.Event) {
@@ -115,9 +221,12 @@
logger.Debugw("MibSync Msg", log.Fields{"TestMessage received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
switch msg.TestMessageVal {
- case AnyTriggerForMibSyncUploadMib:
+ case LoadMibTemplateFailed:
onuDeviceEntry.pMibUploadFsm.pFsm.Event("upload_mib")
logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
+ case LoadMibTemplateOk:
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("success")
+ logger.Debugw("MibSync Msg", log.Fields{"state": string(onuDeviceEntry.pMibUploadFsm.pFsm.Current())})
default:
logger.Warn("MibSync Msg", log.Fields{"Unknown message type received for device-id": onuDeviceEntry.deviceID, "msg.TestMessageVal": msg.TestMessageVal})
}
@@ -181,7 +290,11 @@
}
logger.Debugw("MibUploadNextResponse Data for:", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
- onuDeviceEntry.pOnuDB.StoreMe(msgObj)
+ meClassId := msgObj.ReportedME.GetClassID()
+ meEntityId := msgObj.ReportedME.GetEntityID()
+ meAttributes := msgObj.ReportedME.GetAttributeValueMap()
+
+ onuDeviceEntry.pOnuDB.StoreMe(meClassId, meEntityId, meAttributes)
if onuDeviceEntry.PDevOmciCC.uploadSequNo < onuDeviceEntry.PDevOmciCC.uploadNoOfCmds {
onuDeviceEntry.PDevOmciCC.sendMibUploadNext(context.TODO(), ConstDefaultOmciTimeout, true)
@@ -193,6 +306,50 @@
}
}
+func (onuDeviceEntry *OnuDeviceEntry) newKVClient(storeType string, address string, timeout int) (kvstore.Client, error) {
+ logger.Infow("kv-store-type", log.Fields{"store": storeType})
+ switch storeType {
+ case "consul":
+ return kvstore.NewConsulClient(address, timeout)
+ case "etcd":
+ return kvstore.NewEtcdClient(address, timeout, log.FatalLevel)
+ }
+ return nil, errors.New("unsupported-kv-store")
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) SetKVClient(backend string, Host string, Port int, BasePathKvStore string) *db.Backend {
+ logger.Debugw("SetKVClient with params:", log.Fields{"backend": backend, "Host": Host, "Port": Port,
+ "BasePathKvStore": BasePathKvStore, "deviceId": onuDeviceEntry.deviceID})
+
+ addr := Host + ":" + strconv.Itoa(Port)
+ // TODO : Make sure direct call to NewBackend is working fine with backend , currently there is some
+ // issue between kv store and backend , core is not calling NewBackend directly
+ kvClient, err := onuDeviceEntry.newKVClient(backend, addr, KvstoreTimeout)
+ if err != nil {
+ logger.Fatalw("Failed to init KV client\n", log.Fields{"err": err})
+ return nil
+ }
+
+ kvbackend := &db.Backend{
+ Client: kvClient,
+ StoreType: backend,
+ Host: Host,
+ Port: Port,
+ Timeout: KvstoreTimeout,
+ PathPrefix: BasePathKvStore}
+
+ return kvbackend
+}
+
+func IsSupportedClassId(meClassId me.ClassID) bool {
+ for _, v := range supportedClassIds {
+ if v == meClassId {
+ return true
+ }
+ }
+ return false
+}
+
func (onuDeviceEntry *OnuDeviceEntry) MibDbVolatileDict() error {
logger.Debug("MibVolatileDict- running from default Entry code")
return errors.New("not_implemented")
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 972670f..9074fc8 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -57,10 +57,16 @@
// ### OMCI related definitions - end
+//CallbackPairEntry to be used for OMCI send/receive correlation
+type CallbackPairEntry struct {
+ cbRespChannel chan Message
+ cbFunction func(*omci.OMCI, *gp.Packet, chan Message) error
+}
+
//CallbackPair to be used for ReceiveCallback init
type CallbackPair struct {
- cbKey uint16
- cbFunction func(*omci.OMCI, *gp.Packet) error
+ cbKey uint16
+ cbEntry CallbackPairEntry
}
type omciTransferStructure struct {
@@ -96,7 +102,7 @@
mutexTxQueue sync.Mutex
txQueue *list.List
mutexRxSchedMap sync.Mutex
- rxSchedulerMap map[uint16]func(*omci.OMCI, *gp.Packet) error
+ rxSchedulerMap map[uint16]CallbackPairEntry
pLastTxMeInstance *me.ManagedEntity
}
@@ -125,7 +131,7 @@
omciCC.uploadNoOfCmds = 0
omciCC.txQueue = list.New()
- omciCC.rxSchedulerMap = make(map[uint16]func(*omci.OMCI, *gp.Packet) error)
+ omciCC.rxSchedulerMap = make(map[uint16]CallbackPairEntry)
return &omciCC
}
@@ -229,11 +235,11 @@
} else {
logger.Debug("RxMsg is a Omci Response Message: try to schedule it to the requester")
oo.mutexRxSchedMap.Lock()
- rxCallback, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
- if ok && rxCallback != nil {
+ rxCallbackEntry, ok := oo.rxSchedulerMap[omciMsg.TransactionID]
+ if ok && rxCallbackEntry.cbFunction != nil {
//disadvantage of decoupling: error verification made difficult, but anyway the question is
// how to react on erroneous frame reception, maybe can simply be ignored
- go rxCallback(omciMsg, &packet)
+ go rxCallbackEntry.cbFunction(omciMsg, &packet, rxCallbackEntry.cbRespChannel)
// having posted the response the request is regarded as 'done'
delete(oo.rxSchedulerMap, omciMsg.TransactionID)
oo.mutexRxSchedMap.Unlock()
@@ -362,7 +368,7 @@
logger.Debugw("register-response-callback:", log.Fields{"for TansCorrId": receiveCallbackPair.cbKey})
// it could be checked, if the callback keay is already registered - but simply overwrite may be acceptable ...
oo.mutexRxSchedMap.Lock()
- oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbFunction
+ oo.rxSchedulerMap[receiveCallbackPair.cbKey] = receiveCallbackPair.cbEntry
oo.mutexRxSchedMap.Unlock()
//just use a simple list for starting - might need some more effort, especially for multi source write access
@@ -526,20 +532,21 @@
return dst, nil
}
-//supply a response handler for the MibSync omci response messages
-func (oo *OmciCC) receiveMibSyncResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
+//supply a response handler for omci response messages to be transferred to the requested FSM
+func (oo *OmciCC) receiveOmciResponse(omciMsg *omci.OMCI, packet *gp.Packet, respChan chan Message) error {
- logger.Debugw("mib-sync-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
+ logger.Debugw("omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
"transCorrId": omciMsg.TransactionID, "deviceId": oo.deviceID})
if oo.pOnuDeviceEntry == nil {
- logger.Error("Abort Receive MibSync OMCI, DeviceEntryPointer is nil")
+ logger.Errorw("Abort receiving OMCI response, DeviceEntryPointer is nil", log.Fields{
+ "deviceId": oo.deviceID})
return errors.New("DeviceEntryPointer is nil")
}
// no further test on SeqNo is done here, assignment from rxScheduler is trusted
// MibSync responses are simply transferred via deviceEntry to MibSync, no specific analysis here
- mibSyncMsg := Message{
+ omciRespMsg := Message{
Type: OMCI,
Data: OmciMessage{
OmciMsg: omciMsg,
@@ -547,32 +554,7 @@
},
}
//logger.Debugw("Message to be sent into channel:", log.Fields{"mibSyncMsg": mibSyncMsg})
- (*oo.pOnuDeviceEntry).pMibUploadFsm.commChan <- mibSyncMsg
-
- return nil
-}
-
-//supply a response handler for the MibDownload omci response messages
-func (oo *OmciCC) ReceiveMibDownloadResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
-
- logger.Debugw("mib-download-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
- "transCorrId": omciMsg.TransactionID, "deviceId": oo.deviceID})
-
- if oo.pOnuDeviceEntry == nil {
- logger.Error("Abort Receive MibDownload OMCI response, DeviceEntryPointer is nil")
- return errors.New("DeviceEntryPointer is nil")
- }
-
- // no further test on SeqNo is done here, assignment from rxScheduler is trusted
- // MibDownload responses are simply transferred via deviceEntry to MibDownload, no specific analysis here
- mibDlMsg := Message{
- Type: OMCI,
- Data: OmciMessage{
- OmciMsg: omciMsg,
- OmciPacket: packet,
- },
- }
- (*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan <- mibDlMsg
+ respChan <- omciRespMsg
return nil
}
@@ -588,10 +570,14 @@
tid := oo.GetNextTid(highPrio)
pkt, err := serialize(omci.MibResetRequestType, request, tid)
if err != nil {
- logger.Errorw("Cannot serialize MibResetRequest", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize MibResetRequest", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return err
}
- omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+ }
return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
}
@@ -605,13 +591,17 @@
tid := oo.GetNextTid(highPrio)
pkt, err := serialize(omci.MibUploadRequestType, request, tid)
if err != nil {
- logger.Errorw("Cannot serialize MibUploadRequest", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize MibUploadRequest", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return err
}
oo.uploadSequNo = 0
oo.uploadNoOfCmds = 0
- omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+ }
return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
}
@@ -626,12 +616,16 @@
tid := oo.GetNextTid(highPrio)
pkt, err := serialize(omci.MibUploadNextRequestType, request, tid)
if err != nil {
- logger.Errorw("Cannot serialize MibUploadNextRequest", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize MibUploadNextRequest", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return err
}
oo.uploadSequNo++
- omciRxCallbackPair := CallbackPair{tid, oo.receiveMibSyncResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+ }
return oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
}
@@ -648,38 +642,45 @@
//all setByCreate parameters already set, no default option required ...
omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType, omci.TransactionID(tid))
if err != nil {
- logger.Errorw("Cannot encode GalEnetProfileInstance for create", log.Fields{"Err": err})
+ logger.Errorw("Cannot encode GalEnetProfileInstance for create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
pkt, err := serializeOmciLayer(omciLayer, msgLayer)
if err != nil {
- logger.Errorw("Cannot serialize GalEnetProfile create", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize GalEnetProfile create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+ }
err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
- logger.Errorw("Cannot send GalEnetProfile create", log.Fields{"Err": err})
+ logger.Errorw("Cannot send GalEnetProfile create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
} else {
logger.Debug("send GalEnetProfile-Create-msg done")
return meInstance
}
} else {
- logger.Errorw("Cannot generate GalEnetProfileInstance", log.Fields{"Err": omciErr.GetError()})
+ logger.Errorw("Cannot generate GalEnetProfileInstance", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
return nil
}
}
-// might be needed to extend for parameter arguments, here just for setting the VonnectivityMode!!
+// might be needed to extend for parameter arguments, here just for setting the ConnectivityMode!!
func (oo *OmciCC) sendSetOnu2g(ctx context.Context, timeout int, highPrio bool) *me.ManagedEntity {
tid := oo.GetNextTid(highPrio)
logger.Debugw("send ONU2-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
- // here we should better use the MibUpload stored ONU2-G data to re-use the given InstanceNumber
- // and to verify, if the ONU really supports the desired connectivity mode 5 (in ConnCap)
+ // ONU-G ME-ID is defined to be 0, but we could verify, if the ONU really supports the desired
+ // connectivity mode 5 (in ConnCap)
// By now we just use fix values to fire - this is anyway what the python adapter does
// read ONU-2G from DB ???? //TODO!!!
meParams := me.ParamData{
@@ -690,27 +691,34 @@
if omciErr.GetError() == nil {
omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
if err != nil {
- logger.Errorw("Cannot encode ONU2-G instance for set", log.Fields{"Err": err})
+ logger.Errorw("Cannot encode ONU2-G instance for set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
pkt, err := serializeOmciLayer(omciLayer, msgLayer)
if err != nil {
- logger.Errorw("Cannot serialize ONU2-G set", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize ONU2-G set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+ }
err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
- logger.Errorw("Cannot send ONU2-G set", log.Fields{"Err": err})
+ logger.Errorw("Cannot send ONU2-G set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
} else {
logger.Debug("send ONU2-G-Set-msg done")
return meInstance
}
} else {
- logger.Errorw("Cannot generate ONU2-G", log.Fields{"Err": omciErr.GetError()})
+ logger.Errorw("Cannot generate ONU2-G", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
return nil
}
}
@@ -741,27 +749,34 @@
omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType,
omci.TransactionID(tid), omci.AddDefaults(true))
if err != nil {
- logger.Errorw("Cannot encode MBSP for create", log.Fields{"Err": err})
+ logger.Errorw("Cannot encode MBSP for create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
pkt, err := serializeOmciLayer(omciLayer, msgLayer)
if err != nil {
- logger.Errorw("Cannot serialize MBSP create", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize MBSP create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+ }
err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
- logger.Errorw("Cannot send MBSP create", log.Fields{"Err": err})
+ logger.Errorw("Cannot send MBSP create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
} else {
logger.Debug("send MBSP-Create-msg done")
return meInstance
}
} else {
- logger.Errorw("Cannot generate MBSP Instance", log.Fields{"Err": omciErr.GetError()})
+ logger.Errorw("Cannot generate MBSP Instance", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
return nil
}
}
@@ -788,27 +803,34 @@
omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType,
omci.TransactionID(tid), omci.AddDefaults(true))
if err != nil {
- logger.Errorw("Cannot encode MBPCD for create", log.Fields{"Err": err})
+ logger.Errorw("Cannot encode MBPCD for create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
pkt, err := serializeOmciLayer(omciLayer, msgLayer)
if err != nil {
- logger.Errorw("Cannot serialize MBPCD create", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize MBPCD create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+ }
err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
- logger.Errorw("Cannot send MBPCD create", log.Fields{"Err": err})
+ logger.Errorw("Cannot send MBPCD create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
} else {
logger.Debug("send MBPCD-Create-msg done")
return meInstance
}
} else {
- logger.Errorw("Cannot generate MBPCD Instance", log.Fields{"Err": omciErr.GetError()})
+ logger.Errorw("Cannot generate MBPCD Instance", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
return nil
}
}
@@ -840,27 +862,172 @@
//all setByCreate parameters already set, no default option required ...
omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.CreateRequestType, omci.TransactionID(tid))
if err != nil {
- logger.Errorw("Cannot encode EVTOCD for create", log.Fields{"Err": err})
+ logger.Errorw("Cannot encode EVTOCD for create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
pkt, err := serializeOmciLayer(omciLayer, msgLayer)
if err != nil {
- logger.Errorw("Cannot serialize EVTOCD create", log.Fields{"Err": err})
+ logger.Errorw("Cannot serialize EVTOCD create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
}
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveMibDownloadResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibDownloadFsm.commChan, oo.receiveOmciResponse},
+ }
err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
if err != nil {
- logger.Errorw("Cannot send EVTOCD create", log.Fields{"Err": err})
+ logger.Errorw("Cannot send EVTOCD create", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
return nil
} else {
logger.Debug("send EVTOCD-Create-msg done")
return meInstance
}
} else {
- logger.Errorw("Cannot generate EVTOCD Instance", log.Fields{"Err": omciErr.GetError()})
+ logger.Errorw("Cannot generate EVTOCD Instance", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
+ return nil
+ }
+}
+
+func (oo *OmciCC) sendSetOnuGLS(ctx context.Context, timeout int,
+ highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+ tid := oo.GetNextTid(highPrio)
+ logger.Debugw("send ONU-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+ // ONU-G ME-ID is defined to be 0, no need to perform a DB lookup
+ meParams := me.ParamData{
+ EntityID: 0,
+ Attributes: requestedAttributes,
+ }
+ meInstance, omciErr := me.NewOnuG(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode ONU-G instance for set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize ONU-G set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send ONU-G set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ } else {
+ logger.Debug("send ONU-G-Set-msg done")
+ return meInstance
+ }
+ } else {
+ logger.Errorw("Cannot generate ONU-G", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
+ return nil
+ }
+}
+
+func (oo *OmciCC) sendSetUniGLS(ctx context.Context, aInstNo uint16, timeout int,
+ highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+ tid := oo.GetNextTid(highPrio)
+ logger.Debugw("send UNI-G-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+ // UNI-G ME-ID is taken from Mib Upload stored OnuUniPort instance (argument)
+ meParams := me.ParamData{
+ EntityID: aInstNo,
+ Attributes: requestedAttributes,
+ }
+ meInstance, omciErr := me.NewUniG(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode UNI-G instance for set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize UNI-G-Set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send UNIG-G-Set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ } else {
+ logger.Debug("send UNI-G-Set-msg done")
+ return meInstance
+ }
+ } else {
+ logger.Errorw("Cannot generate UNI-G", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
+ return nil
+ }
+}
+
+func (oo *OmciCC) sendSetVeipLS(ctx context.Context, aInstNo uint16, timeout int,
+ highPrio bool, requestedAttributes me.AttributeValueMap, rxChan chan Message) *me.ManagedEntity {
+ tid := oo.GetNextTid(highPrio)
+ logger.Debugw("send VEIP-Set-msg:", log.Fields{"deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+ // ONU-G ME-ID is defined to be 0, no need to perform a DB lookup
+ meParams := me.ParamData{
+ EntityID: aInstNo,
+ Attributes: requestedAttributes,
+ }
+ meInstance, omciErr := me.NewVirtualEthernetInterfacePoint(meParams)
+ if omciErr.GetError() == nil {
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.SetRequestType, omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorw("Cannot encode VEIP instance for set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize VEIP-Set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse},
+ }
+ err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send VEIP-Set", log.Fields{
+ "Err": err, "deviceId": oo.deviceID})
+ return nil
+ } else {
+ logger.Debug("send VEIP-Set-msg done")
+ return meInstance
+ }
+ } else {
+ logger.Errorw("Cannot generate VEIP", log.Fields{
+ "Err": omciErr.GetError(), "deviceId": oo.deviceID})
return nil
}
}
diff --git a/internal/pkg/onuadaptercore/omci_test_request.go b/internal/pkg/onuadaptercore/omci_test_request.go
index a79ad21..cfb3096 100644
--- a/internal/pkg/onuadaptercore/omci_test_request.go
+++ b/internal/pkg/onuadaptercore/omci_test_request.go
@@ -73,7 +73,10 @@
// without yet checking the received response automatically here (might be improved ??)
tid := oo.pDevOmciCC.GetNextTid(false)
onu2gBaseGet, _ := oo.CreateOnu2gBaseGet(tid)
- omciRxCallbackPair := CallbackPair{tid, oo.ReceiveOmciVerifyResponse}
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{nil, oo.ReceiveOmciVerifyResponse},
+ }
logger.Debugw("performOmciTest-start sending frame", log.Fields{"for deviceId": oo.deviceID})
// send with default timeout and normal prio
@@ -109,8 +112,8 @@
return pkt, nil
}
-//supply a response handler
-func (oo *OmciTestRequest) ReceiveOmciVerifyResponse(omciMsg *omci.OMCI, packet *gp.Packet) error {
+//supply a response handler - in this testobject the message is evaluated directly, no response channel used
+func (oo *OmciTestRequest) ReceiveOmciVerifyResponse(omciMsg *omci.OMCI, packet *gp.Packet, respChan chan Message) error {
logger.Debugw("verify-omci-message-response received:", log.Fields{"omciMsgType": omciMsg.MessageType,
"transCorrId": omciMsg.TransactionID, "DeviceIdent": omciMsg.DeviceIdentifier})
diff --git a/internal/pkg/onuadaptercore/onu_device_db.go b/internal/pkg/onuadaptercore/onu_device_db.go
index 0b985d6..7f779b2 100644
--- a/internal/pkg/onuadaptercore/onu_device_db.go
+++ b/internal/pkg/onuadaptercore/onu_device_db.go
@@ -21,7 +21,6 @@
"context"
"sort"
- "github.com/opencord/omci-lib-go"
me "github.com/opencord/omci-lib-go/generated"
"github.com/opencord/voltha-lib-go/v3/pkg/log"
)
@@ -46,11 +45,7 @@
return &onuDeviceDB
}
-func (onuDeviceDB *OnuDeviceDB) StoreMe(a_pMibUpResp *omci.MibUploadNextResponse) {
-
- meClassId := a_pMibUpResp.ReportedME.GetClassID()
- meEntityId := a_pMibUpResp.ReportedME.GetEntityID()
- meAttributes := a_pMibUpResp.ReportedME.GetAttributeValueMap()
+func (onuDeviceDB *OnuDeviceDB) StoreMe(meClassId me.ClassID, meEntityId uint16, meAttributes me.AttributeValueMap) {
//filter out the OnuData
if me.OnuDataClassID == meClassId {
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index 2d7caa6..2a7c29e 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -19,12 +19,14 @@
import (
"context"
- //"errors"
+ "errors"
+
//"sync"
//"time"
"github.com/looplab/fsm"
"github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
+ "github.com/opencord/voltha-lib-go/v3/pkg/db"
//"github.com/opencord/voltha-lib-go/v3/pkg/kafka"
"github.com/opencord/voltha-lib-go/v3/pkg/log"
@@ -33,6 +35,12 @@
//"github.com/opencord/voltha-protos/v3/go/voltha"
)
+const (
+ KvstoreTimeout = 5 //in seconds
+ BasePathMibTemplateKvStore = "service/voltha/omci_mibs/templates"
+ SuffixMibTemplateKvStore = "%s/%s/%s"
+)
+
type OnuDeviceEvent int
const (
@@ -41,8 +49,11 @@
MibDatabaseSync OnuDeviceEvent = 1 // MIB database sync (upload done)
OmciCapabilitiesDone OnuDeviceEvent = 2 // OMCI ME and message type capabilities known
MibDownloadDone OnuDeviceEvent = 3 // MIB database sync (upload done)
- PortLinkUp OnuDeviceEvent = 4 // Port link state change
- PortLinkDw OnuDeviceEvent = 5 // Port link state change
+ UniLockStateDone OnuDeviceEvent = 4 // Uni ports admin set to lock
+ UniUnlockStateDone OnuDeviceEvent = 5 // Uni ports admin set to unlock
+ UniAdminStateDone OnuDeviceEvent = 6 // Uni ports admin set done - general
+ PortLinkUp OnuDeviceEvent = 7 // Port link state change
+ PortLinkDw OnuDeviceEvent = 8 // Port link state change
// Add other events here as needed (alarms separate???)
)
@@ -78,25 +89,29 @@
//OntDeviceEntry structure holds information about the attached FSM'as and their communication
type OnuDeviceEntry struct {
- deviceID string
- baseDeviceHandler *DeviceHandler
- coreProxy adapterif.CoreProxy
- adapterProxy adapterif.AdapterProxy
- started bool
- PDevOmciCC *OmciCC
- pOnuDB *OnuDeviceDB
+ deviceID string
+ baseDeviceHandler *DeviceHandler
+ coreProxy adapterif.CoreProxy
+ adapterProxy adapterif.AdapterProxy
+ started bool
+ PDevOmciCC *OmciCC
+ pOnuDB *OnuDeviceDB
+ mibTemplateKVStore *db.Backend
+ vendorID string
+ serialNumber string
+ equipmentID string
+ activeSwVersion string
+ macAddress string
//lockDeviceEntries sync.RWMutex
mibDbClass func() error
supportedFsms OmciDeviceFsms
devState OnuDeviceEvent
// for mibUpload
mibAuditDelay uint16
- //MibSyncFsm *fsm.FSM
- //MibSyncChan chan Message
+
+ // for mibUpload
pMibUploadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
// for mibDownload
- //MibDownloadFsm *fsm.FSM
- //MibDownloadChan chan Message
pMibDownloadFsm *AdapterFsm //could be handled dynamically and more general as pAdapterFsm - perhaps later
//remark: general usage of pAdapterFsm would require generalization of commChan usage and internal event setting
// within the FSM event procedures
@@ -105,8 +120,7 @@
//OnuDeviceEntry returns a new instance of a OnuDeviceEntry
//mib_db (as well as not inluded alarm_db not really used in this code? VERIFY!!)
-func NewOnuDeviceEntry(ctx context.Context,
- device_id string, device_Handler *DeviceHandler,
+func NewOnuDeviceEntry(ctx context.Context, device_id string, kVStoreHost string, kVStorePort int, kvStoreType string, device_Handler *DeviceHandler,
core_proxy adapterif.CoreProxy, adapter_proxy adapterif.AdapterProxy,
supported_Fsms_Ptr *OmciDeviceFsms) *OnuDeviceEntry {
logger.Infow("init-onuDeviceEntry", log.Fields{"deviceId": device_id})
@@ -240,6 +254,11 @@
// some specifc error treatment - or waiting for crash ???
}
+ onuDeviceEntry.mibTemplateKVStore = onuDeviceEntry.SetKVClient(kvStoreType, kVStoreHost, kVStorePort, BasePathMibTemplateKvStore)
+ if onuDeviceEntry.mibTemplateKVStore == nil {
+ logger.Error("Failed to setup mibTemplateKVStore")
+ }
+
// Alarm Synchronization Database
//self._alarm_db = None
//self._alarm_database_cls = support_classes['alarm-synchronizer']['database']
@@ -252,11 +271,13 @@
oo.PDevOmciCC = NewOmciCC(ctx, oo, oo.deviceID, oo.baseDeviceHandler,
oo.coreProxy, oo.adapterProxy)
+ if oo.PDevOmciCC == nil {
+ logger.Errorw("Could not create devOmciCc - abort", log.Fields{"for device": oo.deviceID})
+ return errors.New("Could not create devOmciCc")
+ }
- //TODO .....
- //mib_db.start()
oo.started = true
- logger.Info("OnuDeviceEntry-started, but not yet mib_db!!!")
+ logger.Info("OnuDeviceEntry-started")
return nil
}
@@ -277,7 +298,7 @@
if dev_Event == MibDatabaseSync {
if oo.devState < MibDatabaseSync { //devState has not been synced yet
oo.devState = MibDatabaseSync
- go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+ go oo.baseDeviceHandler.DeviceProcStatusUpdate(dev_Event)
//TODO!!! device control: next step: start MIB capability verification from here ?!!!
} else {
logger.Debugw("mibinsync-event in some already synced state - ignored", log.Fields{"state": oo.devState})
@@ -285,7 +306,7 @@
} else if dev_Event == MibDownloadDone {
if oo.devState < MibDownloadDone { //devState has not been synced yet
oo.devState = MibDownloadDone
- go oo.baseDeviceHandler.DeviceStateUpdate(dev_Event)
+ go oo.baseDeviceHandler.DeviceProcStatusUpdate(dev_Event)
} else {
logger.Debugw("mibdownloaddone-event was already seen - ignored", log.Fields{"state": oo.devState})
}
diff --git a/internal/pkg/onuadaptercore/openonu.go b/internal/pkg/onuadaptercore/openonu.go
index 255af1d..253f901 100644
--- a/internal/pkg/onuadaptercore/openonu.go
+++ b/internal/pkg/onuadaptercore/openonu.go
@@ -195,7 +195,8 @@
// and are by now not reported to the calling party (to force what reaction there?)
return nil
}
- logger.Warn("no handler found for received Inter-Proxy-message 'ToDeviceId'")
+ logger.Warnw("no handler found for received Inter-Proxy-message", log.Fields{
+ "msgToDeviceId": targetDevice})
return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", targetDevice))
}
@@ -226,23 +227,23 @@
//Disable_device disables the given device
func (oo *OpenONUAC) Disable_device(device *voltha.Device) error {
- logger.Debug("Disable_device", device.Id)
+ logger.Debugw("Disable_device", log.Fields{"deviceId": device.Id})
if handler := oo.getDeviceHandler(device.Id); handler != nil {
go handler.DisableDevice(device)
return nil
}
- logger.Warn("no handler found for reenable device 'device.Id'")
+ logger.Warnw("no handler found for device-disable", log.Fields{"deviceId": device.Id})
return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
}
-//Reenable_device enables the olt device after disable
+//Reenable_device enables the onu device after disable
func (oo *OpenONUAC) Reenable_device(device *voltha.Device) error {
- logger.Debug("Reenable_device", device.Id)
+ logger.Debugw("Reenable_device", log.Fields{"deviceId": device.Id})
if handler := oo.getDeviceHandler(device.Id); handler != nil {
go handler.ReenableDevice(device)
return nil
}
- logger.Warn("no handler found for reenable device 'device.Id'")
+ logger.Warnw("no handler found for device-reenable", log.Fields{"deviceId": device.Id})
return fmt.Errorf(fmt.Sprintf("handler-not-found-%s", device.Id))
}
@@ -251,7 +252,7 @@
return errors.New("unImplemented")
}
-//Self_test_device unimplented
+//Self_test_device unimplemented
func (oo *OpenONUAC) Self_test_device(device *voltha.Device) error {
return errors.New("unImplemented")
}
@@ -321,21 +322,16 @@
return nil, errors.New("unImplemented")
}
-// Enable_port to Enable PON/NNI interface
+// Enable_port to Enable PON/NNI interface - seems not to be used/required according to python code
func (oo *OpenONUAC) Enable_port(deviceID string, port *voltha.Port) error {
return errors.New("unImplemented")
}
-// Disable_port to Disable pon/nni interface
+// Disable_port to Disable pon/nni interface - seems not to be used/required according to python code
func (oo *OpenONUAC) Disable_port(deviceID string, port *voltha.Port) error {
return errors.New("unImplemented")
}
-// enableDisablePort to Disable pon or Enable PON interface
-func (oo *OpenONUAC) enableDisablePort(deviceID string, port *voltha.Port, enablePort bool) error {
- return errors.New("unImplemented")
-}
-
//needed for if update >= 3.1.x
func (oo *OpenONUAC) Child_device_lost(deviceID string, pPortNo uint32, onuID uint32) error {
return errors.New("unImplemented")
diff --git a/internal/pkg/onuadaptercore/uniportadmin.go b/internal/pkg/onuadaptercore/uniportadmin.go
new file mode 100644
index 0000000..f7b98da
--- /dev/null
+++ b/internal/pkg/onuadaptercore/uniportadmin.go
@@ -0,0 +1,375 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//Package adaptercoreonu provides the utility for onu devices, flows and statistics
+package adaptercoreonu
+
+import (
+ "context"
+ "errors"
+ "time"
+
+ "github.com/looplab/fsm"
+
+ "github.com/opencord/omci-lib-go"
+ me "github.com/opencord/omci-lib-go/generated"
+ "github.com/opencord/voltha-lib-go/v3/pkg/log"
+ //ic "github.com/opencord/voltha-protos/v3/go/inter_container"
+ //"github.com/opencord/voltha-protos/v3/go/openflow_13"
+ //"github.com/opencord/voltha-protos/v3/go/voltha"
+)
+
+//LockStateFsm defines the structure for the state machine to lock/unlock the ONU UNI ports via OMCI
+type LockStateFsm struct {
+ pOmciCC *OmciCC
+ adminState bool
+ requestEvent OnuDeviceEvent
+ omciLockResponseReceived chan bool //seperate channel needed for checking UNI port OMCi message responses
+ pAdaptFsm *AdapterFsm
+}
+
+//NewLockStateFsm is the 'constructor' for the state machine to lock/unlock the ONU UNI ports via OMCI
+func NewLockStateFsm(apDevOmciCC *OmciCC, aAdminState bool, aRequestEvent OnuDeviceEvent,
+ aName string, aDeviceID string, aCommChannel chan Message) *LockStateFsm {
+ instFsm := &LockStateFsm{
+ pOmciCC: apDevOmciCC,
+ adminState: aAdminState,
+ requestEvent: aRequestEvent,
+ }
+ instFsm.pAdaptFsm = NewAdapterFsm(aName, aDeviceID, aCommChannel)
+ if instFsm.pAdaptFsm == nil {
+ logger.Errorw("LockStateFsm's AdapterFsm could not be instantiated!!", log.Fields{
+ "device-id": aDeviceID})
+ return nil
+ }
+ if aAdminState == true { //port locking requested
+ instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
+ "disabled",
+ fsm.Events{
+
+ {Name: "start", Src: []string{"disabled"}, Dst: "starting"},
+
+ {Name: "start_admin", Src: []string{"starting"}, Dst: "settingUnis"},
+ // the settingUnis state is used for multi ME config for alle UNI related ports
+ // maybe such could be reflected in the state machine as well (port number parametrized)
+ // but that looks not straightforward here - so we keep it simple here for the beginning(?)
+ {Name: "rx_unis_resp", Src: []string{"settingUnis"}, Dst: "settingOnuG"},
+ {Name: "rx_onug_resp", Src: []string{"settingOnuG"}, Dst: "adminDone"},
+
+ {Name: "timeout_simple", Src: []string{"settingOnuG"}, Dst: "starting"},
+ {Name: "timeout_unis", Src: []string{"settingUnis"}, Dst: "starting"},
+
+ {Name: "reset", Src: []string{"starting", "settingOnuG", "settingUnis",
+ "adminDone"}, Dst: "resetting"},
+ // exceptional treatment for all states except "resetting"
+ {Name: "restart", Src: []string{"starting", "settingOnuG", "settingUnis",
+ "adminDone", "resetting"}, Dst: "disabled"},
+ },
+
+ fsm.Callbacks{
+ "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
+ "enter_starting": func(e *fsm.Event) { instFsm.enterAdminStartingState(e) },
+ "enter_settingOnuG": func(e *fsm.Event) { instFsm.enterSettingOnuGState(e) },
+ "enter_settingUnis": func(e *fsm.Event) { instFsm.enterSettingUnisState(e) },
+ "enter_adminDone": func(e *fsm.Event) { instFsm.enterAdminDoneState(e) },
+ "enter_resetting": func(e *fsm.Event) { instFsm.enterResettingState(e) },
+ },
+ )
+ } else { //port unlocking requested
+ instFsm.pAdaptFsm.pFsm = fsm.NewFSM(
+ "disabled",
+ fsm.Events{
+
+ {Name: "start", Src: []string{"disabled"}, Dst: "starting"},
+
+ {Name: "start_admin", Src: []string{"starting"}, Dst: "settingOnuG"},
+ {Name: "rx_onug_resp", Src: []string{"settingOnuG"}, Dst: "settingUnis"},
+ // the settingUnis state is used for multi ME config for alle UNI related ports
+ // maybe such could be reflected in the state machine as well (port number parametrized)
+ // but that looks not straightforward here - so we keep it simple here for the beginning(?)
+ {Name: "rx_unis_resp", Src: []string{"settingUnis"}, Dst: "adminDone"},
+
+ {Name: "timeout_simple", Src: []string{"settingOnuG"}, Dst: "starting"},
+ {Name: "timeout_unis", Src: []string{"settingUnis"}, Dst: "starting"},
+
+ {Name: "reset", Src: []string{"starting", "settingOnuG", "settingUnis",
+ "adminDone"}, Dst: "resetting"},
+ // exceptional treatment for all states except "resetting"
+ {Name: "restart", Src: []string{"starting", "settingOnuG", "settingUnis",
+ "adminDone", "resetting"}, Dst: "disabled"},
+ },
+
+ fsm.Callbacks{
+ "enter_state": func(e *fsm.Event) { instFsm.pAdaptFsm.logFsmStateChange(e) },
+ "enter_starting": func(e *fsm.Event) { instFsm.enterAdminStartingState(e) },
+ "enter_settingOnuG": func(e *fsm.Event) { instFsm.enterSettingOnuGState(e) },
+ "enter_settingUnis": func(e *fsm.Event) { instFsm.enterSettingUnisState(e) },
+ "enter_adminDone": func(e *fsm.Event) { instFsm.enterAdminDoneState(e) },
+ "enter_resetting": func(e *fsm.Event) { instFsm.enterResettingState(e) },
+ },
+ )
+ }
+ if instFsm.pAdaptFsm.pFsm == nil {
+ logger.Errorw("LockStateFsm's Base FSM could not be instantiated!!", log.Fields{
+ "device-id": aDeviceID})
+ return nil
+ }
+
+ logger.Infow("LockStateFsm created", log.Fields{"device-id": aDeviceID})
+ return instFsm
+}
+
+//SetSuccessEvent modifies the requested event notified on success
+//assumption is that this is only called in the disabled (idle) state of the FSM, hence no sem protection required
+func (oFsm *LockStateFsm) SetSuccessEvent(aEvent OnuDeviceEvent) {
+ oFsm.requestEvent = aEvent
+}
+
+func (oFsm *LockStateFsm) enterAdminStartingState(e *fsm.Event) {
+ logger.Debugw("LockStateFSM start", log.Fields{"in state": e.FSM.Current(),
+ "device-id": oFsm.pAdaptFsm.deviceID})
+ // in case the used channel is not yet defined (can be re-used after restarts)
+ if oFsm.omciLockResponseReceived == nil {
+ oFsm.omciLockResponseReceived = make(chan bool)
+ logger.Debug("LockStateFSM - OMCI UniLock RxChannel defined")
+ } else {
+ // as we may 're-use' this instance of FSM and the connected channel
+ // make sure there is no 'lingering' request in the already existing channel:
+ // (simple loop sufficient as we are the only receiver)
+ for len(oFsm.omciLockResponseReceived) > 0 {
+ <-oFsm.omciLockResponseReceived
+ }
+ }
+ // start go routine for processing of LockState messages
+ go oFsm.ProcessOmciLockMessages()
+
+ //let the state machine run forward from here directly
+ pLockStateAFsm := oFsm.pAdaptFsm
+ if pLockStateAFsm != nil {
+ // obviously calling some FSM event here directly does not work - so trying to decouple it ...
+ go func(a_pAFsm *AdapterFsm) {
+ if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+ a_pAFsm.pFsm.Event("start_admin")
+ }
+ }(pLockStateAFsm)
+ }
+}
+
+func (oFsm *LockStateFsm) enterSettingOnuGState(e *fsm.Event) {
+ var omciAdminState uint8 = 1 //default locked
+ if oFsm.adminState == false {
+ omciAdminState = 0
+ }
+ logger.Debugw("LockStateFSM Tx Set::ONU-G:admin", log.Fields{
+ "omciAdmin": omciAdminState, "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
+ requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
+ meInstance := oFsm.pOmciCC.sendSetOnuGLS(context.TODO(), ConstDefaultOmciTimeout, true,
+ requestedAttributes, oFsm.pAdaptFsm.commChan)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ // we might already abort the processing with nil here, but maybe some auto-recovery may be tried
+ // - may be improved later, for now we just handle it with the Rx timeout or missing next event (stick in state)
+ oFsm.pOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (oFsm *LockStateFsm) enterSettingUnisState(e *fsm.Event) {
+ logger.Infow("LockStateFSM - starting PPTP config loop", log.Fields{
+ "in state": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID, "LockState": oFsm.adminState})
+ go oFsm.performUniPortAdminSet()
+}
+
+func (oFsm *LockStateFsm) enterAdminDoneState(e *fsm.Event) {
+ logger.Debugw("LockStateFSM", log.Fields{"send notification to core in State": e.FSM.Current(), "device-id": oFsm.pAdaptFsm.deviceID})
+ //use DeviceHandler event notification directly, no need/support to update DeviceEntryState for lock/unlock
+ oFsm.pOmciCC.pBaseDeviceHandler.DeviceProcStatusUpdate(oFsm.requestEvent)
+ //let's reset the state machine in order to release all resources now
+ pLockStateAFsm := oFsm.pAdaptFsm
+ if pLockStateAFsm != nil {
+ // obviously calling some FSM event here directly does not work - so trying to decouple it ...
+ go func(a_pAFsm *AdapterFsm) {
+ if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+ a_pAFsm.pFsm.Event("reset")
+ }
+ }(pLockStateAFsm)
+ }
+}
+
+func (oFsm *LockStateFsm) enterResettingState(e *fsm.Event) {
+ logger.Debugw("LockStateFSM resetting", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+ pLockStateAFsm := oFsm.pAdaptFsm
+ if pLockStateAFsm != nil {
+ // abort running message processing
+ fsmAbortMsg := Message{
+ Type: TestMsg,
+ Data: TestMessage{
+ TestMessageVal: AbortMessageProcessing,
+ },
+ }
+ pLockStateAFsm.commChan <- fsmAbortMsg
+
+ //try to restart the FSM to 'disabled'
+ // see DownloadedState: decouple event transfer
+ go func(a_pAFsm *AdapterFsm) {
+ if a_pAFsm != nil && a_pAFsm.pFsm != nil {
+ a_pAFsm.pFsm.Event("restart")
+ }
+ }(pLockStateAFsm)
+ }
+}
+
+func (oFsm *LockStateFsm) ProcessOmciLockMessages( /*ctx context.Context*/ ) {
+ logger.Debugw("Start LockStateFsm Msg processing", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+loop:
+ for {
+ select {
+ // case <-ctx.Done():
+ // logger.Info("MibSync Msg", log.Fields{"Message handling canceled via context for device-id": oFsm.pAdaptFsm.deviceID})
+ // break loop
+ case message, ok := <-oFsm.pAdaptFsm.commChan:
+ if !ok {
+ logger.Info("LockStateFsm Rx Msg - could not read from channel", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+ // but then we have to ensure a restart of the FSM as well - as exceptional procedure
+ oFsm.pAdaptFsm.pFsm.Event("restart")
+ break loop
+ }
+ logger.Debugw("LockStateFsm Rx Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+
+ switch message.Type {
+ case TestMsg:
+ msg, _ := message.Data.(TestMessage)
+ if msg.TestMessageVal == AbortMessageProcessing {
+ logger.Infow("LockStateFsm abort ProcessMsg", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+ break loop
+ }
+ logger.Warnw("LockStateFsm unknown TestMessage", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID, "MessageVal": msg.TestMessageVal})
+ case OMCI:
+ msg, _ := message.Data.(OmciMessage)
+ oFsm.handleOmciLockStateMessage(msg)
+ default:
+ logger.Warn("LockStateFsm Rx unknown message", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
+ "message.Type": message.Type})
+ }
+ }
+ }
+ logger.Infow("End LockStateFsm Msg processing", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID})
+}
+
+func (oFsm *LockStateFsm) handleOmciLockStateMessage(msg OmciMessage) {
+ logger.Debugw("Rx OMCI LockStateFsm Msg", log.Fields{"device-id": oFsm.pAdaptFsm.deviceID,
+ "msgType": msg.OmciMsg.MessageType})
+
+ if msg.OmciMsg.MessageType == omci.SetResponseType {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
+ if msgLayer == nil {
+ logger.Error("LockStateFsm - Omci Msg layer could not be detected for SetResponse")
+ return
+ }
+ msgObj, msgOk := msgLayer.(*omci.SetResponse)
+ if !msgOk {
+ logger.Error("LockStateFsm - Omci Msg layer could not be assigned for SetResponse")
+ return
+ }
+ logger.Debugw("LockStateFsm SetResponse Data", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "data-fields": msgObj})
+ if msgObj.Result != me.Success {
+ logger.Errorw("LockStateFsm - Omci SetResponse Error - later: drive FSM to abort state ?", log.Fields{"Error": msgObj.Result})
+ // possibly force FSM into abort or ignore some errors for some messages? store error for mgmt display?
+ return
+ }
+ // compare comments above for CreateResponse (apply also here ...)
+ if msgObj.EntityClass == oFsm.pOmciCC.pLastTxMeInstance.GetClassID() &&
+ msgObj.EntityInstance == oFsm.pOmciCC.pLastTxMeInstance.GetEntityID() {
+ //store the created ME into DB //TODO??? obviously the Python code does not store the config ...
+ // if, then something like:
+ //oFsm.pOnuDB.StoreMe(msgObj)
+
+ switch oFsm.pOmciCC.pLastTxMeInstance.GetName() {
+ case "OnuG":
+ { // let the FSM proceed ...
+ oFsm.pAdaptFsm.pFsm.Event("rx_onug_resp")
+ }
+ case "UniG", "VEIP":
+ { // let the PPTP init proceed by stopping the wait function
+ oFsm.omciLockResponseReceived <- true
+ }
+ }
+ }
+ } else {
+ logger.Errorw("LockStateFsm - Rx OMCI unhandled MsgType", log.Fields{"omciMsgType": msg.OmciMsg.MessageType})
+ return
+ }
+}
+
+func (oFsm *LockStateFsm) performUniPortAdminSet() {
+ var omciAdminState uint8 = 1 //default locked
+ if oFsm.adminState == false {
+ omciAdminState = 0
+ }
+ //set UNI-G or VEIP AdminState
+ requestedAttributes := me.AttributeValueMap{"AdministrativeState": omciAdminState}
+
+ for uniNo, uniPort := range oFsm.pOmciCC.pBaseDeviceHandler.uniEntityMap {
+ logger.Debugw("Setting PPTP admin state", log.Fields{
+ "deviceId": oFsm.pAdaptFsm.deviceID, "for PortNo": uniNo})
+
+ var meInstance *me.ManagedEntity
+ if uniPort.portType == UniPPTP {
+ meInstance = oFsm.pOmciCC.sendSetUniGLS(context.TODO(), uniPort.entityId, ConstDefaultOmciTimeout,
+ true, requestedAttributes, oFsm.pAdaptFsm.commChan)
+ oFsm.pOmciCC.pLastTxMeInstance = meInstance
+ } else if uniPort.portType == UniVEIP {
+ meInstance = oFsm.pOmciCC.sendSetVeipLS(context.TODO(), uniPort.entityId, ConstDefaultOmciTimeout,
+ true, requestedAttributes, oFsm.pAdaptFsm.commChan)
+ oFsm.pOmciCC.pLastTxMeInstance = meInstance
+ } else {
+ logger.Warnw("Unsupported PPTP type - skip",
+ log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "Port": uniNo})
+ continue
+ }
+
+ //verify response
+ err := oFsm.WaitforOmciResponse(meInstance)
+ if err != nil {
+ logger.Errorw("PPTP Admin State set failed, aborting LockState set!",
+ log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID, "Port": uniNo})
+ oFsm.pAdaptFsm.pFsm.Event("reset")
+ return
+ }
+ } //for all UNI ports
+ // if Config has been done for all UNI related instances let the FSM proceed
+ // while we did not check here, if there is some port at all - !?
+ logger.Infow("PPTP config loop finished", log.Fields{"deviceId": oFsm.pAdaptFsm.deviceID})
+ oFsm.pAdaptFsm.pFsm.Event("rx_unis_resp")
+ return
+}
+
+func (oFsm *LockStateFsm) WaitforOmciResponse(a_pMeInstance *me.ManagedEntity) error {
+ select {
+ // maybe be also some outside cancel (but no context modelled for the moment ...)
+ // case <-ctx.Done():
+ // logger.Infow("LockState-bridge-init message reception canceled", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+ case <-time.After(3 * time.Second):
+ logger.Warnw("LockStateFSM uni-set timeout", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+ return errors.New("LockStateFsm uni-set timeout")
+ case success := <-oFsm.omciLockResponseReceived:
+ if success == true {
+ logger.Debug("LockStateFSM uni-set response received")
+ return nil
+ }
+ // should not happen so far
+ logger.Warnw("LockStateFSM uni-set response error", log.Fields{"for device-id": oFsm.pAdaptFsm.deviceID})
+ return errors.New("LockStateFsm uni-set responseError")
+ }
+}