[VOL-3036] Read MIB Templates from ETCD
Change-Id: I59143cd1b51fa64b70b7a1f63eebfd3463f24017
Signed-off-by: Holger Hildebrandt <holger.hildebrandt@adtran.com>
diff --git a/VERSION b/VERSION
index 588933b..efde802 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.11-dev118
+0.1.11-dev121
diff --git a/internal/pkg/onuadaptercore/device_handler.go b/internal/pkg/onuadaptercore/device_handler.go
index 44a5b6a..1aca121 100644
--- a/internal/pkg/onuadaptercore/device_handler.go
+++ b/internal/pkg/onuadaptercore/device_handler.go
@@ -70,6 +70,27 @@
cOnuActivatedEvent = "ONU_ACTIVATED"
)
+type resourceEntry int
+
+const (
+ cResourceGemPort resourceEntry = 1
+ cResourceTcont resourceEntry = 2
+)
+
+type OnuSerialNumber struct {
+ VendorId []byte
+ VendorSpecific []byte
+}
+
+type onuPersistentData struct {
+ persOnuID uint32
+ persIntfID uint32
+ persSnr OnuSerialNumber
+ persAdminState string
+ persOperState string
+ persUniTpPath map[uint32]string
+}
+
//DeviceHandler will interact with the ONU ? device.
type DeviceHandler struct {
deviceID string
@@ -82,9 +103,13 @@
parentId string
ponPortNumber uint32
- coreProxy adapterif.CoreProxy
- AdapterProxy adapterif.AdapterProxy
- EventProxy adapterif.EventProxy
+ coreProxy adapterif.CoreProxy
+ AdapterProxy adapterif.AdapterProxy
+ EventProxy adapterif.EventProxy
+
+ tpProcMutex sync.RWMutex
+ sOnuPersistentData onuPersistentData
+
pOpenOnuAc *OpenONUAC
pDeviceStateFsm *fsm.FSM
pPonPort *voltha.Port
@@ -122,6 +147,8 @@
dh.DeviceType = cloned.Type
dh.adminState = "up"
dh.device = cloned
+ dh.tpProcMutex = sync.RWMutex{}
+ dh.sOnuPersistentData.persUniTpPath = make(map[uint32]string)
dh.pOpenOnuAc = adapter
dh.exitChannel = make(chan int, 1)
dh.lockDevice = sync.RWMutex{}
@@ -217,14 +244,15 @@
msgBody := msg.GetBody()
omciMsg := &ic.InterAdapterOmciMessage{}
if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
- logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{"error": err})
+ logger.Warnw("cannot-unmarshal-omci-msg-body", log.Fields{
+ "deviceID": dh.deviceID, "error": err})
return err
}
//assuming omci message content is hex coded!
// with restricted output of 16(?) bytes would be ...omciMsg.Message[:16]
- logger.Debugw("inter-adapter-recv-omci",
- log.Fields{"RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
+ logger.Debugw("inter-adapter-recv-omci", log.Fields{
+ "deviceID": dh.deviceID, "RxOmciMessage": hex.EncodeToString(omciMsg.Message)})
//receive_message(omci_msg.message)
pDevEntry := dh.GetOnuDeviceEntry(true)
if pDevEntry != nil {
@@ -239,7 +267,8 @@
msgBody := msg.GetBody()
onu_indication := &oop.OnuIndication{}
if err := ptypes.UnmarshalAny(msgBody, onu_indication); err != nil {
- logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{"error": err})
+ logger.Warnw("cannot-unmarshal-onu-indication-msg-body", log.Fields{
+ "deviceID": dh.deviceID, "error": err})
return err
}
@@ -258,9 +287,89 @@
return errors.New("InvalidOperState")
}
}
+ // TODO: temporarily commented out - see https://gerrit.opencord.org/#/c/19330/
+ // case ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST:
+ // {
+ // msgBody := msg.GetBody()
+ // techProfMsg := &ic.InterAdapterTechProfileDownloadMessage{}
+ // if err := ptypes.UnmarshalAny(msgBody, techProfMsg); err != nil {
+ // logger.Warnw("cannot-unmarshal-techprof-msg-body", log.Fields{
+ // "deviceID": dh.deviceID, "error": err})
+ // return err
+ // }
+ // // we have to lock access to TechProfile processing based on different messageType calls or
+ // // even to fast subsequent calls of the same messageType
+ // dh.tpProcMutex.Lock()
+ // // lock hangs as long as below decoupled or other related TechProfile processing is active
+ // if bTpModify := dh.updateOnuUniTpPath(techProfMsg.UniId, techProfMsg.Path); bTpModify == true {
+ // // if there has been some change for some uni TechProfilePath
+ // //in order to allow concurrent calls to other dh instances we do not wait for execution here
+ // //but doing so we can not indicate problems to the caller (who does what with that then?)
+ // //by now we just assume straightforward successful execution
+ // //TODO!!! Generally: In this scheme it would be good to have some means to indicate
+ // // possible problems to the caller later autonomously
+
+ // // some code to coordinate TP 'run to completion'
+ // // attention: completion and wg.Add is assumed to be doen in both routines,
+ // // no timeout control so far (needed)
+ // var wg sync.WaitGroup
+ // wg.Add(2) // for the 2 go routines to finish
+ // go dh.configureUniTp(techProfMsg.UniId, techProfMsg.Path, &wg)
+ // go dh.updateOnuTpPathKvStore(&wg)
+ // //the wait.. function is responsible for tpProcMutex.Unlock()
+ // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
+ // } else {
+ // dh.tpProcMutex.Unlock()
+ // }
+ // }
+ // case ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST:
+ // {
+ // msgBody := msg.GetBody()
+ // delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{}
+ // if err := ptypes.UnmarshalAny(msgBody, delGemPortMsg); err != nil {
+ // logger.Warnw("cannot-unmarshal-delete-gem-msg-body", log.Fields{
+ // "deviceID": dh.deviceID, "error": err})
+ // return err
+ // }
+
+ // //compare TECH_PROFILE_DOWNLOAD_REQUEST
+ // dh.tpProcMutex.Lock()
+ // var wg sync.WaitGroup
+ // wg.Add(1) // for the 1 go routine to finish
+ // go dh.deleteTpRessource(delGemPortMsg.UniId, delGemPortMsg.TpPath,
+ // cResourceGemPort, delGemPortMsg.GemPortId, &wg)
+ // //the wait.. function is responsible for tpProcMutex.Unlock()
+ // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
+ // }
+ // case ic.InterAdapterMessageType_DELETE_TCONT_REQUEST:
+ // {
+ // msgBody := msg.GetBody()
+ // delTcontMsg := &ic.InterAdapterDeleteTcontMessage{}
+ // if err := ptypes.UnmarshalAny(msgBody, delTcontMsg); err != nil {
+ // logger.Warnw("cannot-unmarshal-delete-tcont-msg-body", log.Fields{
+ // "deviceID": dh.deviceID, "error": err})
+ // return err
+ // }
+
+ // //compare TECH_PROFILE_DOWNLOAD_REQUEST
+ // dh.tpProcMutex.Lock()
+ // if bTpModify := dh.updateOnuUniTpPath(delTcontMsg.UniId, ""); bTpModify == true {
+ // var wg sync.WaitGroup
+ // wg.Add(2) // for the 1 go routine to finish
+ // go dh.deleteTpRessource(delTcontMsg.UniId, delTcontMsg.TpPath,
+ // cResourceTcont, delTcontMsg.AllocId, &wg)
+ // // Removal of the tcont/alloc id mapping represents the removal of the tech profile
+ // go dh.updateOnuTpPathKvStore(&wg)
+ // //the wait.. function is responsible for tpProcMutex.Unlock()
+ // go dh.waitForTpCompletion(&wg) //let that also run off-line to let the IA messaging return!
+ // } else {
+ // dh.tpProcMutex.Unlock()
+ // }
+ // }
default:
{
- logger.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
+ logger.Errorw("inter-adapter-unhandled-type", log.Fields{
+ "deviceID": dh.deviceID, "msgType": msg.Header.Type})
return errors.New("unimplemented")
}
}
@@ -834,9 +943,9 @@
//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")
+ if err := pMibUlFsm.Event("reset_mib"); err != nil {
+ logger.Errorw("MibSyncFsm: Can't go to state resetting_mib", log.Fields{"err": err})
+ return errors.New("Can't go to state resetting_mib")
}
} else {
pMibUlFsm.Event("examine_mds")
@@ -1239,12 +1348,88 @@
}
}
+/* **** Traffic Profile related processing **********/
+// updateOnuUniTpPath verifies and updates changes in the dh.onuUniTpPath
+func (dh *DeviceHandler) updateOnuUniTpPath(aUniID uint32, aPathString string) bool {
+ /* within some specific InterAdapter processing request write/read access to data is ensured to be sequentially,
+ as also the complete sequence is ensured to 'run to completion' before some new request is accepted
+ no specific concurrency protection to sOnuPersistentData is required here
+ */
+ if existingPath, present := dh.sOnuPersistentData.persUniTpPath[aUniID]; present {
+ // uni entry already exists
+ //logger.Debugw(" already exists", log.Fields{"for InstanceId": a_uniInstNo})
+ if existingPath != aPathString {
+ if aPathString == "" {
+ //existing entry to be deleted
+ logger.Debugw("UniTp path delete", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
+ delete(dh.sOnuPersistentData.persUniTpPath, aUniID)
+ } else {
+ //existing entry to be modified
+ logger.Debugw("UniTp path modify", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
+ dh.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
+ }
+ return true
+ }
+ //entry already exists
+ logger.Debugw("UniTp path already exists", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
+ return false
+ } else {
+ //uni entry does not exist
+ if aPathString == "" {
+ //delete request in non-existing state , accept as no change
+ logger.Debugw("UniTp path already removed", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID})
+ return false
+ }
+ //new entry to be set
+ logger.Debugw("New UniTp path set", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
+ dh.sOnuPersistentData.persUniTpPath[aUniID] = aPathString
+ return true
+ }
+}
+
+func (dh *DeviceHandler) configureUniTp(aUniID uint32, aPathString string, wg *sync.WaitGroup) {
+ defer wg.Done()
+ logger.Debugw("this would configure the Uni according to TpPath", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString})
+ //TODO!!!
+ //this processing requires reading of the TechProfile config data from KV-Store,
+ // to evaluate the configuration and to start the corresponding OMCI configuation of the UNI port
+}
+
+func (dh *DeviceHandler) updateOnuTpPathKvStore(wg *sync.WaitGroup) {
+ defer wg.Done()
+ logger.Debugw("this would update the ONU's TpPath in KVStore", log.Fields{
+ "deviceID": dh.deviceID})
+ //TODO!!!
+ //make use of dh.sOnuPersistentData to store the TpPath to KVStore
+}
+
+// deleteTpRessource removes ressources from the ONU's specified Uni
+func (dh *DeviceHandler) deleteTpRessource(aUniID uint32, aPathString string,
+ aRessource resourceEntry, aEntryID uint32, wg *sync.WaitGroup) {
+ defer wg.Done()
+ logger.Debugw("this would remove TP resources from ONU's UNI", log.Fields{
+ "deviceID": dh.deviceID, "uniID": aUniID, "path": aPathString, "ressource": aRessource})
+ //TODO!!!
+}
+
+func (dh *DeviceHandler) waitForTpCompletion(wg *sync.WaitGroup) {
+ wg.Wait()
+ logger.Debug("some TechProfile Processing completed")
+ dh.tpProcMutex.Unlock() //allow further TP related processing
+}
+
/* *********************************************************** */
-func genMacFromOctets(a_octets [6]uint8) string {
+func genMacFromOctets(aOctets [6]uint8) string {
return fmt.Sprintf("%02x:%02x:%02x:%02x:%02x:%02x",
- a_octets[5], a_octets[4], a_octets[3],
- a_octets[2], a_octets[1], a_octets[0])
+ aOctets[5], aOctets[4], aOctets[3],
+ aOctets[2], aOctets[1], aOctets[0])
}
//copied from OLT Adapter: unify centrally ?
diff --git a/internal/pkg/onuadaptercore/mib_sync.go b/internal/pkg/onuadaptercore/mib_sync.go
index 807412d..80470ed 100644
--- a/internal/pkg/onuadaptercore/mib_sync.go
+++ b/internal/pkg/onuadaptercore/mib_sync.go
@@ -19,6 +19,7 @@
import (
"context"
+ "encoding/hex"
"encoding/json"
"errors"
"fmt"
@@ -66,33 +67,76 @@
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})
-
onuDeviceEntry.pOnuDB = NewOnuDeviceDB(context.TODO(), onuDeviceEntry)
-
go onuDeviceEntry.ProcessMibSyncMessages()
}
-func (onuDeviceEntry *OnuDeviceEntry) enterLoadingMibTemplateState(e *fsm.Event) {
+func (onuDeviceEntry *OnuDeviceEntry) enterResettingMibState(e *fsm.Event) {
logger.Debugw("MibSync FSM", log.Fields{"Start MibTemplate processing in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
- meStoredFromTemplate := false
+ logger.Debugw("MibSync FSM", log.Fields{"send mibReset in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.sendMibReset(context.TODO(), ConstDefaultOmciTimeout, true)
- //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"
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingVendorAndSerialState(e *fsm.Event) {
+ logger.Debugw("MibSync FSM", log.Fields{"Start getting VendorId and SerialNumber in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ requestedAttributes := me.AttributeValueMap{"VendorId": "", "SerialNumber": 0}
+ meInstance := onuDeviceEntry.PDevOmciCC.sendGetMe(context.TODO(), me.OnuGClassID, OnugMeId, requestedAttributes, ConstDefaultOmciTimeout, true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+}
- Path := fmt.Sprintf(SuffixMibTemplateKvStore, onuDeviceEntry.vendorID, onuDeviceEntry.equipmentID, onuDeviceEntry.activeSwVersion)
- Value, err := onuDeviceEntry.mibTemplateKVStore.Get(context.TODO(), Path)
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingEquipmentIdState(e *fsm.Event) {
+ logger.Debugw("MibSync FSM", log.Fields{"Start getting EquipmentId in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ requestedAttributes := me.AttributeValueMap{"EquipmentId": ""}
+ meInstance := onuDeviceEntry.PDevOmciCC.sendGetMe(context.TODO(), me.Onu2GClassID, Onu2gMeId, requestedAttributes, ConstDefaultOmciTimeout, true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingFirstSwVersionState(e *fsm.Event) {
+ logger.Debugw("MibSync FSM", log.Fields{"Start getting IsActive and Version of first SW-image in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ requestedAttributes := me.AttributeValueMap{"IsActive": 0, "Version": ""}
+ meInstance := onuDeviceEntry.PDevOmciCC.sendGetMe(context.TODO(), me.SoftwareImageClassID, FirstSwImageMeId, requestedAttributes, ConstDefaultOmciTimeout, true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingSecondSwVersionState(e *fsm.Event) {
+ logger.Debugw("MibSync FSM", log.Fields{"Start getting IsActive and Version of second SW-image in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ requestedAttributes := me.AttributeValueMap{"IsActive": 0, "Version": ""}
+ meInstance := onuDeviceEntry.PDevOmciCC.sendGetMe(context.TODO(), me.SoftwareImageClassID, SecondSwImageMeId, requestedAttributes, ConstDefaultOmciTimeout, true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingMacAddressState(e *fsm.Event) {
+ logger.Debugw("MibSync FSM", log.Fields{"Start getting MacAddress in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ requestedAttributes := me.AttributeValueMap{"MacAddress": ""}
+ meInstance := onuDeviceEntry.PDevOmciCC.sendGetMe(context.TODO(), me.IpHostConfigDataClassID, IpHostConfigDataMeId, requestedAttributes, ConstDefaultOmciTimeout, true)
+ //accept also nil as (error) return value for writing to LastTx
+ // - this avoids misinterpretation of new received OMCI messages
+ onuDeviceEntry.PDevOmciCC.pLastTxMeInstance = meInstance
+}
+
+func (onuDeviceEntry *OnuDeviceEntry) enterGettingMibTemplate(e *fsm.Event) {
+
+ for i := FirstSwImageMeId; i <= SecondSwImageMeId; i++ {
+ if onuDeviceEntry.swImages[i].isActive > 0 {
+ onuDeviceEntry.activeSwVersion = onuDeviceEntry.swImages[i].version
+ }
+ }
+
+ meStoredFromTemplate := false
+ path := fmt.Sprintf(SuffixMibTemplateKvStore, onuDeviceEntry.vendorID, onuDeviceEntry.equipmentID, onuDeviceEntry.activeSwVersion)
+ logger.Debugw("MibSync FSM - MibTemplate - etcd search string", log.Fields{"path": path})
+ 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)
@@ -120,7 +164,7 @@
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})
+ logger.Debugw("MibSync FSM - secondLevelKey is a number and a valid EntityId", log.Fields{"meEntityId": meEntityId})
thirdLevelMap := secondLevelValue.(map[string]interface{})
for thirdLevelKey, thirdLevelValue := range thirdLevelMap {
if thirdLevelKey == "attributes" {
@@ -138,10 +182,10 @@
}
}
} else {
- logger.Debugw("No MIB template found", log.Fields{"device-id": onuDeviceEntry.deviceID})
+ logger.Debugw("No MIB template found", log.Fields{"path": path, "device-id": onuDeviceEntry.deviceID})
}
} else {
- logger.Errorf("Get from kvstore operation failed for path %s", Path)
+ logger.Errorf("Get from kvstore operation failed for path %s", path)
}
if meStoredFromTemplate {
logger.Debug("MibSync FSM - valid MEs stored from template")
@@ -162,8 +206,8 @@
}
func (onuDeviceEntry *OnuDeviceEntry) enterUploadingState(e *fsm.Event) {
- logger.Debugw("MibSync FSM", log.Fields{"send mibReset in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
- onuDeviceEntry.PDevOmciCC.sendMibReset(context.TODO(), ConstDefaultOmciTimeout, true)
+ logger.Debugw("MibSync FSM", log.Fields{"send MibUpload in State": e.FSM.Current(), "device-id": onuDeviceEntry.deviceID})
+ onuDeviceEntry.PDevOmciCC.sendMibUpload(context.TODO(), ConstDefaultOmciTimeout, true)
}
func (onuDeviceEntry *OnuDeviceEntry) enterInSyncState(e *fsm.Event) {
@@ -247,22 +291,30 @@
//further analysis could be done here based on msg.OmciMsg.Payload, e.g. verification of error code ...
switch msg.OmciMsg.MessageType {
case omci.MibResetResponseType:
- msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibResetResponse)
- if msgLayer == nil {
- logger.Error("Omci Msg layer could not be detected")
- return
+ if onuDeviceEntry.pMibUploadFsm.pFsm.Is("resetting_mib") {
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibResetResponse)
+ if msgLayer != nil {
+ msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
+ if msgOk {
+ logger.Debugw("MibResetResponse Data", log.Fields{"data-fields": msgObj})
+ if msgObj.Result == me.Success {
+ // trigger retrieval of VendorId and SerialNumber
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_vendor_and_serial")
+ return
+ } else {
+ logger.Errorw("Omci MibResetResponse Error", log.Fields{"Error": msgObj.Result})
+ }
+ } else {
+ logger.Error("Omci Msg layer could not be assigned")
+ }
+ } else {
+ logger.Error("Omci Msg layer could not be detected")
+ }
+ } else {
+ logger.Errorw("Omci MibResetResponse received", log.Fields{"in state ": onuDeviceEntry.pMibUploadFsm.pFsm.Current})
}
- msgObj, msgOk := msgLayer.(*omci.MibResetResponse)
- if !msgOk {
- logger.Error("Omci Msg layer could not be assigned")
- return
- }
- logger.Debugw("MibResetResponse Data", log.Fields{"data-fields": msgObj})
- if msgObj.Result != me.Success {
- logger.Errorw("Omci MibResetResponse Error - strange - what to do?", log.Fields{"Error": msgObj.Result})
- return
- }
- onuDeviceEntry.PDevOmciCC.sendMibUpload(context.TODO(), ConstDefaultOmciTimeout, true)
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("stop")
+
case omci.MibUploadResponseType:
msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeMibUploadResponse)
if msgLayer == nil {
@@ -310,6 +362,85 @@
onuDeviceEntry.pOnuDB.LogMeDb()
onuDeviceEntry.pMibUploadFsm.pFsm.Event("success")
}
+ case omci.GetResponseType:
+ msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
+ if msgLayer != nil {
+ msgObj, msgOk := msgLayer.(*omci.GetResponse)
+ if msgOk {
+ logger.Debugw("MibSync FSM - GetResponse Data", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if msgObj.Result == me.Success {
+ entityId := onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetEntityID()
+ if msgObj.EntityClass == onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetClassID() && msgObj.EntityInstance == entityId {
+ meAttributes := msgObj.Attributes
+ switch onuDeviceEntry.PDevOmciCC.pLastTxMeInstance.GetName() {
+ case "OnuG":
+ logger.Debugw("MibSync FSM - GetResponse Data for Onu-G", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ onuDeviceEntry.vendorID = fmt.Sprintf("%s", meAttributes["VendorId"])
+ snBytes, _ := me.InterfaceToOctets(meAttributes["SerialNumber"])
+ if OnugSerialNumberLen == len(snBytes) {
+ snVendorPart := fmt.Sprintf("%s", snBytes[:4])
+ snNumberPart := hex.EncodeToString(snBytes[4:])
+ onuDeviceEntry.serialNumber = snVendorPart + snNumberPart
+ logger.Debugw("MibSync FSM - GetResponse Data for Onu-G - VendorId/SerialNumber", log.Fields{"deviceId": onuDeviceEntry.deviceID,
+ "onuDeviceEntry.vendorID": onuDeviceEntry.vendorID, "onuDeviceEntry.serialNumber": onuDeviceEntry.serialNumber})
+ } else {
+ logger.Errorw("MibSync FSM - SerialNumber has wrong length", log.Fields{"deviceId": onuDeviceEntry.deviceID, "length": len(snBytes)})
+ }
+ // trigger retrieval of EquipmentId
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_equipment_id")
+ return
+ case "Onu2G":
+ logger.Debugw("MibSync FSM - GetResponse Data for Onu2-G", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ onuDeviceEntry.equipmentID = fmt.Sprintf("%s", meAttributes["EquipmentId"])
+ logger.Debugw("MibSync FSM - GetResponse Data for Onu2-G - EquipmentId", log.Fields{"deviceId": onuDeviceEntry.deviceID,
+ "onuDeviceEntry.equipmentID": onuDeviceEntry.equipmentID})
+ // trigger retrieval of 1st SW-image info
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_first_sw_version")
+ return
+ case "SoftwareImage":
+ logger.Debugw("MibSync FSM - GetResponse Data for SoftwareImage", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ if entityId <= SecondSwImageMeId {
+ onuDeviceEntry.swImages[entityId].version = fmt.Sprintf("%s", meAttributes["Version"])
+ onuDeviceEntry.swImages[entityId].isActive = meAttributes["IsActive"].(uint8)
+ logger.Debugw("MibSync FSM - GetResponse Data for SoftwareImage - Version/IsActive",
+ log.Fields{"deviceId": onuDeviceEntry.deviceID, "entityId": entityId,
+ "version": onuDeviceEntry.swImages[entityId].version, "isActive": onuDeviceEntry.swImages[entityId].isActive})
+ } else {
+ //TODO: error handling
+ }
+ if FirstSwImageMeId == entityId {
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_second_sw_version")
+ return
+ } else if SecondSwImageMeId == entityId {
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_mac_address")
+ return
+ }
+ case "IpHostConfigData":
+ ///
+ logger.Debugw("MibSync FSM - GetResponse Data for IpHostConfigData", log.Fields{"deviceId": onuDeviceEntry.deviceID, "data-fields": msgObj})
+ macBytes, _ := me.InterfaceToOctets(meAttributes["MacAddress"])
+ if OmciMacAddressLen == len(macBytes) {
+ onuDeviceEntry.macAddress = hex.EncodeToString(macBytes[:])
+ logger.Debugw("MibSync FSM - GetResponse Data for IpHostConfigData - MacAddress", log.Fields{"deviceId": onuDeviceEntry.deviceID,
+ "onuDeviceEntry.macAddress": onuDeviceEntry.macAddress})
+ } else {
+ logger.Errorw("MibSync FSM - MacAddress wrong length", log.Fields{"deviceId": onuDeviceEntry.deviceID, "length": len(macBytes)})
+ }
+ // trigger retrieval of mib template
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("get_mib_template")
+ }
+ }
+ } else {
+ logger.Errorw("Omci GetResponse Error", log.Fields{"Error": msgObj.Result})
+ }
+ } else {
+ logger.Error("Omci Msg layer could not be assigned for GetResponse")
+ }
+ } else {
+ logger.Error("Omci Msg layer could not be detected for GetResponse")
+ }
+ //
+ onuDeviceEntry.pMibUploadFsm.pFsm.Event("stop")
}
}
diff --git a/internal/pkg/onuadaptercore/omci_cc.go b/internal/pkg/onuadaptercore/omci_cc.go
index 9074fc8..7edd20e 100644
--- a/internal/pkg/onuadaptercore/omci_cc.go
+++ b/internal/pkg/onuadaptercore/omci_cc.go
@@ -1031,3 +1031,44 @@
return nil
}
}
+
+func (oo *OmciCC) sendGetMe(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
+ timeout int, highPrio bool) *me.ManagedEntity {
+
+ tid := oo.GetNextTid(highPrio)
+ logger.Debugw("send get-request-msg", log.Fields{"classID": classID, "deviceId": oo.deviceID, "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+ meParams := me.ParamData{
+ EntityID: entityID,
+ Attributes: requestedAttributes,
+ }
+ meInstance, omciErr := me.LoadManagedEntityDefinition(classID, meParams)
+ if omciErr.GetError() == nil {
+ meClassIdName := meInstance.GetName()
+ omciLayer, msgLayer, err := omci.EncodeFrame(meInstance, omci.GetRequestType, omci.TransactionID(tid))
+ if err != nil {
+ logger.Errorf("Cannot encode instance for get-request", log.Fields{"meClassIdName": meClassIdName, "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+ pkt, err := serializeOmciLayer(omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw("Cannot serialize get-request", log.Fields{"meClassIdName": meClassIdName, "Err": err, "deviceId": oo.deviceID})
+ return nil
+ }
+ omciRxCallbackPair := CallbackPair{
+ cbKey: tid,
+ cbEntry: CallbackPairEntry{(*oo.pOnuDeviceEntry).pMibUploadFsm.commChan, oo.receiveOmciResponse},
+ }
+ err = oo.Send(ctx, pkt, timeout, 0, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw("Cannot send get-request-msg", log.Fields{"meClassIdName": meClassIdName, "Err": err, "deviceId": oo.deviceID})
+ return nil
+ } else {
+ logger.Debugw("send get-request-msg done", log.Fields{"meClassIdName": meClassIdName, "deviceId": oo.deviceID})
+ return meInstance
+ }
+ } else {
+ logger.Errorw("Cannot generate meDefinition", log.Fields{"classID": classID, "Err": omciErr.GetError(), "deviceId": oo.deviceID})
+ return nil
+ }
+}
diff --git a/internal/pkg/onuadaptercore/onu_device_entry.go b/internal/pkg/onuadaptercore/onu_device_entry.go
index dff9545..4d31f77 100644
--- a/internal/pkg/onuadaptercore/onu_device_entry.go
+++ b/internal/pkg/onuadaptercore/onu_device_entry.go
@@ -88,6 +88,22 @@
}
//OntDeviceEntry structure holds information about the attached FSM'as and their communication
+
+const (
+ FirstSwImageMeId = 0
+ SecondSwImageMeId = 1
+)
+const OnugMeId = 0
+const Onu2gMeId = 0
+const IpHostConfigDataMeId = 1
+const OnugSerialNumberLen = 8
+const OmciMacAddressLen = 6
+
+type SwImages struct {
+ version string
+ isActive uint8
+}
+
type OnuDeviceEntry struct {
deviceID string
baseDeviceHandler *DeviceHandler
@@ -100,6 +116,7 @@
vendorID string
serialNumber string
equipmentID string
+ swImages [SecondSwImageMeId + 1]SwImages
activeSwVersion string
macAddress string
//lockDeviceEntries sync.RWMutex
@@ -173,11 +190,18 @@
{Name: "start", Src: []string{"disabled"}, Dst: "starting"},
- {Name: "load_mib_template", Src: []string{"starting"}, Dst: "loading_mib_template"},
- {Name: "upload_mib", Src: []string{"loading_mib_template"}, Dst: "uploading"},
+ {Name: "reset_mib", Src: []string{"starting"}, Dst: "resetting_mib"},
+ {Name: "get_vendor_and_serial", Src: []string{"resetting_mib"}, Dst: "getting_vendor_and_serial"},
+ {Name: "get_equipment_id", Src: []string{"getting_vendor_and_serial"}, Dst: "getting_equipment_id"},
+ {Name: "get_first_sw_version", Src: []string{"getting_equipment_id"}, Dst: "getting_first_sw_version"},
+ {Name: "get_second_sw_version", Src: []string{"getting_first_sw_version"}, Dst: "getting_second_sw_version"},
+ {Name: "get_mac_address", Src: []string{"getting_second_sw_version"}, Dst: "getting_mac_address"},
+ {Name: "get_mib_template", Src: []string{"getting_mac_address"}, Dst: "getting_mib_template"},
+
+ {Name: "upload_mib", Src: []string{"getting_mib_template"}, Dst: "uploading"},
{Name: "examine_mds", Src: []string{"starting"}, Dst: "examining_mds"},
- {Name: "success", Src: []string{"loading_mib_template"}, Dst: "in_sync"},
+ {Name: "success", Src: []string{"getting_mib_template"}, Dst: "in_sync"},
{Name: "success", Src: []string{"uploading"}, Dst: "in_sync"},
{Name: "success", Src: []string{"examining_mds"}, Dst: "in_sync"},
@@ -195,21 +219,29 @@
{Name: "success", Src: []string{"resynchronizing"}, Dst: "in_sync"},
{Name: "diffs_found", Src: []string{"resynchronizing"}, Dst: "out_of_sync"},
- {Name: "timeout", Src: []string{"loading_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "starting"},
+ {Name: "timeout", Src: []string{"reset_mib", "get_vendor_and_serial", "get_equipment_id", "get_first_sw_version", "get_mac_address",
+ "get_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "starting"},
- {Name: "stop", Src: []string{"starting", "loading_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "disabled"},
+ {Name: "stop", Src: []string{"starting", "reset_mib", "get_vendor_and_serial", "get_equipment_id", "get_first_sw_version", "get_mac_address",
+ "get_mib_template", "uploading", "resynchronizing", "examining_mds", "in_sync", "out_of_sync", "auditing"}, Dst: "disabled"},
},
fsm.Callbacks{
- "enter_state": func(e *fsm.Event) { onuDeviceEntry.pMibUploadFsm.logFsmStateChange(e) },
- "enter_starting": func(e *fsm.Event) { onuDeviceEntry.enterStartingState(e) },
- "enter_loading_mib_template": func(e *fsm.Event) { onuDeviceEntry.enterLoadingMibTemplateState(e) },
- "enter_uploading": func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(e) },
- "enter_examining_mds": func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(e) },
- "enter_resynchronizing": func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(e) },
- "enter_auditing": func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(e) },
- "enter_out_of_sync": func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(e) },
- "enter_in_sync": func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(e) },
+ "enter_state": func(e *fsm.Event) { onuDeviceEntry.pMibUploadFsm.logFsmStateChange(e) },
+ "enter_starting": func(e *fsm.Event) { onuDeviceEntry.enterStartingState(e) },
+ "enter_resetting_mib": func(e *fsm.Event) { onuDeviceEntry.enterResettingMibState(e) },
+ "enter_getting_vendor_and_serial": func(e *fsm.Event) { onuDeviceEntry.enterGettingVendorAndSerialState(e) },
+ "enter_getting_equipment_id": func(e *fsm.Event) { onuDeviceEntry.enterGettingEquipmentIdState(e) },
+ "enter_getting_first_sw_version": func(e *fsm.Event) { onuDeviceEntry.enterGettingFirstSwVersionState(e) },
+ "enter_getting_second_sw_version": func(e *fsm.Event) { onuDeviceEntry.enterGettingSecondSwVersionState(e) },
+ "enter_getting_mac_address": func(e *fsm.Event) { onuDeviceEntry.enterGettingMacAddressState(e) },
+ "enter_getting_mib_template": func(e *fsm.Event) { onuDeviceEntry.enterGettingMibTemplate(e) },
+ "enter_uploading": func(e *fsm.Event) { onuDeviceEntry.enterUploadingState(e) },
+ "enter_examining_mds": func(e *fsm.Event) { onuDeviceEntry.enterExaminingMdsState(e) },
+ "enter_resynchronizing": func(e *fsm.Event) { onuDeviceEntry.enterResynchronizingState(e) },
+ "enter_auditing": func(e *fsm.Event) { onuDeviceEntry.enterAuditingState(e) },
+ "enter_out_of_sync": func(e *fsm.Event) { onuDeviceEntry.enterOutOfSyncState(e) },
+ "enter_in_sync": func(e *fsm.Event) { onuDeviceEntry.enterInSyncState(e) },
},
)
// Omci related Mib download state machine