[VOL-5483] Add support at openonu adapter to fetch the current PM data from the supported ONT devices.
Change-Id: I205b4a59b2a4eacff71e2114de8ceb07d7d131e5
Signed-off-by: pnalmas <praneeth.nalmas@radisys.com>
diff --git a/VERSION b/VERSION
index 9359b93..b6ddb73 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.12.33
+2.12.34
diff --git a/go.mod b/go.mod
index 4593cd9..31054fd 100644
--- a/go.mod
+++ b/go.mod
@@ -16,7 +16,7 @@
github.com/google/gopacket v1.1.17
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/looplab/fsm v0.2.0
- github.com/opencord/omci-lib-go/v2 v2.2.3
+ github.com/opencord/omci-lib-go/v2 v2.2.4
github.com/opencord/voltha-lib-go/v7 v7.6.6
github.com/opencord/voltha-protos/v5 v5.6.5
github.com/stretchr/testify v1.8.1
diff --git a/go.sum b/go.sum
index bd8d79f..3d367de 100644
--- a/go.sum
+++ b/go.sum
@@ -928,8 +928,8 @@
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI=
github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
-github.com/opencord/omci-lib-go/v2 v2.2.3 h1:cE9+67m8HmZmlET57eyQmqOOAJlfvvKrLgiJMiwhSMg=
-github.com/opencord/omci-lib-go/v2 v2.2.3/go.mod h1:o1S/jhDLHNikFU7uG2TR5UOM5KmKlqwLlVncXi0FBYQ=
+github.com/opencord/omci-lib-go/v2 v2.2.4 h1:IwRO6AHkhwETNxyiZmqT+7NzDTco3BmUvbsXrtKCoew=
+github.com/opencord/omci-lib-go/v2 v2.2.4/go.mod h1:o1S/jhDLHNikFU7uG2TR5UOM5KmKlqwLlVncXi0FBYQ=
github.com/opencord/voltha-lib-go/v7 v7.6.6 h1:TrLo0nykH2MXPngKzTtmL9/u2gjxs98m1/F0m3FWY2U=
github.com/opencord/voltha-lib-go/v7 v7.6.6/go.mod h1:uGmArLg+nSZd49YXv7ZaD48FA5c+siEFxnyRuldwv6Y=
github.com/opencord/voltha-protos/v5 v5.6.2/go.mod h1:E/Jn3DNu8VGRBCgIWSSg4sWtTBiNuQGSFvHyNH1XlyM=
diff --git a/internal/pkg/common/omci_cc.go b/internal/pkg/common/omci_cc.go
index 89d1afb..5fbe0e7 100755
--- a/internal/pkg/common/omci_cc.go
+++ b/internal/pkg/common/omci_cc.go
@@ -1647,6 +1647,51 @@
return nil
}
+// SendGetCurrentDataME gets current performance monitoring data from ME instance
+func (oo *OmciCC) SendGetCurrentDataME(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
+ timeout int, highPrio bool, rxChan chan Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
+
+ tid := oo.GetNextTid(highPrio)
+ logger.Debugw(ctx, "send get-current-data-request-msg", log.Fields{"classID": classID, "device-id": oo.deviceID,
+ "SequNo": strconv.FormatInt(int64(tid), 16)})
+
+ meParams := me.ParamData{
+ EntityID: entityID,
+ Attributes: requestedAttributes,
+ }
+ var messageSet = omci.BaselineIdent
+ if isExtendedOmci {
+ messageSet = omci.ExtendedIdent
+ }
+ meInstance, omciErr := me.LoadManagedEntityDefinition(classID, meParams)
+ if omciErr.GetError() == nil {
+ meClassIDName := meInstance.GetName()
+ omciLayer, msgLayer, err := oframe.EncodeFrame(meInstance, omci.GetCurrentDataRequestType, oframe.TransactionID(tid), oframe.FrameFormat(messageSet))
+ if err != nil {
+ logger.Errorf(ctx, "Cannot encode instance for get-current-data-request", log.Fields{"meClassIDName": meClassIDName, "Err": err, "device-id": oo.deviceID})
+ return nil, err
+ }
+ pkt, err := SerializeOmciLayer(ctx, omciLayer, msgLayer)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot serialize get-current-data-request", log.Fields{"meClassIDName": meClassIDName, "Err": err, "device-id": oo.deviceID})
+ return nil, err
+ }
+ omciRxCallbackPair := CallbackPair{
+ CbKey: tid,
+ CbEntry: CallbackPairEntry{rxChan, oo.receiveOmciResponse, true},
+ }
+ err = oo.Send(ctx, pkt, timeout, CDefaultRetries, highPrio, omciRxCallbackPair)
+ if err != nil {
+ logger.Errorw(ctx, "Cannot send get-current-data-request-msg", log.Fields{"meClassIDName": meClassIDName, "Err": err, "device-id": oo.deviceID})
+ return nil, err
+ }
+ logger.Debugw(ctx, "send get-current-data-request-msg done", log.Fields{"meClassIDName": meClassIDName, "device-id": oo.deviceID})
+ return meInstance, nil
+ }
+ logger.Errorw(ctx, "Cannot generate meDefinition", log.Fields{"classID": classID, "Err": omciErr.GetError(), "device-id": oo.deviceID})
+ return nil, omciErr.GetError()
+}
+
// SendCreateDot1PMapper creates Ieee8021PMapperServiceProfile ME instance
func (oo *OmciCC) SendCreateDot1PMapper(ctx context.Context, timeout int, highPrio bool,
aInstID uint16, rxChan chan Message) (*me.ManagedEntity, error) {
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 337a97b..1bdeab0 100755
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -5197,7 +5197,14 @@
// getONUGEMStatsInfo - Get the GEM PM history data of the request ONT device
func (dh *deviceHandler) getONUGEMStatsInfo(ctx context.Context) *extension.SingleGetValueResponse {
resp := dh.pOnuMetricsMgr.GetONUGEMCounters(ctx)
- logger.Debugw(ctx, "Received response from AlarmManager for Active Alarms for DeviceEntry", log.Fields{"device-id": dh.DeviceID})
+ logger.Debugw(ctx, "Received response from ONU Metrics Manager for GEM Stats", log.Fields{"device-id": dh.DeviceID})
+ return resp
+}
+
+// getOnuFECStats - Get the GEM PM history data of the request ONT device
+func (dh *deviceHandler) getOnuFECStats(ctx context.Context) *extension.SingleGetValueResponse {
+ resp := dh.pOnuMetricsMgr.GetONUFECCounters(ctx)
+ logger.Debugw(ctx, "Received response from ONU Metrics Manager for FEC Stats", log.Fields{"device-id": dh.DeviceID})
return resp
}
diff --git a/internal/pkg/core/openonu.go b/internal/pkg/core/openonu.go
index 0f6a887..e5e31fc 100755
--- a/internal/pkg/core/openonu.go
+++ b/internal/pkg/core/openonu.go
@@ -527,8 +527,11 @@
return resp, nil
case *extension.GetValueRequest_OnuAllocGemStats:
resp := handler.getONUGEMStatsInfo(ctx)
- logger.Infow(ctx, "Received response for on demand active alarms request ", log.Fields{"response": resp})
+ logger.Infow(ctx, "Received response for on demand GEM counters ", log.Fields{"response": resp})
return resp, nil
+ case *extension.GetValueRequest_FecHistory:
+ return handler.getOnuFECStats(ctx), nil
+
default:
return uniprt.PostUniStatusErrResponse(extension.GetValueResponse_UNSUPPORTED), nil
}
diff --git a/internal/pkg/devdb/onu_device_db.go b/internal/pkg/devdb/onu_device_db.go
index d299789..96b8eb9 100755
--- a/internal/pkg/devdb/onu_device_db.go
+++ b/internal/pkg/devdb/onu_device_db.go
@@ -191,12 +191,12 @@
}
}
-// GetSortedInstKeys returns a sorted list of all instances of an ME
+// // GetSortedInstKeys returns a sorted list of all instances of an ME from both CommonMeDb and OnuSpecificMeDb
func (OnuDeviceDB *OnuDeviceDB) GetSortedInstKeys(ctx context.Context, meClassID me.ClassID) []uint16 {
var meInstKeys []uint16
+ // Check CommonMeDb
OnuDeviceDB.CommonMeDb.MeDbLock.RLock()
- defer OnuDeviceDB.CommonMeDb.MeDbLock.RUnlock()
meDb := OnuDeviceDB.CommonMeDb.MeDb
// Check if the class ID exists in the MeDb map
@@ -206,6 +206,18 @@
}
logger.Debugw(ctx, "meInstKeys - input order :", log.Fields{"meInstKeys": meInstKeys}) //TODO: delete the line after test phase!
}
+ OnuDeviceDB.CommonMeDb.MeDbLock.RUnlock()
+
+ // Check OnuSpecificMeDb
+ OnuDeviceDB.OnuSpecificMeDbLock.RLock()
+ if onuSpecificMap, found := OnuDeviceDB.OnuSpecificMeDb[meClassID]; found {
+ for k := range onuSpecificMap {
+ meInstKeys = append(meInstKeys, k)
+ }
+ }
+ OnuDeviceDB.OnuSpecificMeDbLock.RUnlock()
+
+ // Sort all instance keys
sort.Slice(meInstKeys, func(i, j int) bool { return meInstKeys[i] < meInstKeys[j] })
logger.Debugw(ctx, "meInstKeys - output order :", log.Fields{"meInstKeys": meInstKeys}) //TODO: delete the line after test phase!
diff --git a/internal/pkg/pmmgr/onu_metrics_manager.go b/internal/pkg/pmmgr/onu_metrics_manager.go
index e6eda1c..c333ba4 100755
--- a/internal/pkg/pmmgr/onu_metrics_manager.go
+++ b/internal/pkg/pmmgr/onu_metrics_manager.go
@@ -259,7 +259,7 @@
)
// Defines the type for generic metric population function
-type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
+type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int, bool) error
// *** Classical L2 PM Counters end ***
@@ -1233,6 +1233,12 @@
me.EthernetFrameExtendedPm64BitClassID:
mm.extendedPmMeChan <- meAttributes
return nil
+ case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
+ mm.l2PmChan <- meAttributes
+ return nil
+ case me.FecPerformanceMonitoringHistoryDataClassID:
+ mm.opticalMetricsChan <- meAttributes
+ return nil
default:
logger.Errorw(ctx, "unhandled omci get current data response message",
log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
@@ -1246,6 +1252,15 @@
// AttributeFailure error code, while correctly populating other counters it supports
mm.extendedPmMeChan <- meAttributes
return nil
+ case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
+ // Handle attribute failure for GemPort data similar to Extended PM
+ mm.l2PmChan <- meAttributes
+ return nil
+ case me.FecPerformanceMonitoringHistoryDataClassID:
+ // Handle attribute failure for FEC data similar to Extended PM
+ mm.opticalMetricsChan <- meAttributes
+ return nil
+
default:
logger.Errorw(ctx, "unhandled omci get current data response message",
log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
@@ -1541,13 +1556,13 @@
case FecHistoryName:
for _, entityID := range copyOfEntityIDs {
- if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
+ if metricInfo := mm.collectFecHistoryData(ctx, entityID, false); metricInfo != nil { // upstream
metricInfoSlice = append(metricInfoSlice, metricInfo)
}
}
case GemPortHistoryName:
for _, entityID := range copyOfEntityIDs {
- if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
+ if metricInfo := mm.collectGemHistoryData(ctx, entityID, false); metricInfo != nil { // upstream
metricInfoSlice = append(metricInfoSlice, metricInfo)
}
}
@@ -2037,7 +2052,7 @@
intervalEndTime := -1
ethPMHistData := make(map[string]float32)
- if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
+ if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime, false); err != nil {
return nil
}
@@ -2074,7 +2089,7 @@
intervalEndTime := -1
ethUniHistData := make(map[string]float32)
- if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
+ if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime, false); err != nil {
return nil
}
@@ -2089,7 +2104,7 @@
return &metricInfo
}
-func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
+func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16, isCurrent bool) *voltha.MetricInformation {
var mEnt *me.ManagedEntity
var omciErr me.OmciErrors
var classID me.ClassID
@@ -2104,7 +2119,7 @@
intervalEndTime := -1
fecHistData := make(map[string]float32)
- if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
+ if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime, isCurrent); err != nil {
return nil
}
@@ -2119,7 +2134,7 @@
return &metricInfo
}
-func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
+func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16, isCurrent bool) *voltha.MetricInformation {
var mEnt *me.ManagedEntity
var omciErr me.OmciErrors
var classID me.ClassID
@@ -2134,7 +2149,7 @@
intervalEndTime := -1
gemHistData := make(map[string]float32)
- if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
+ if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime, isCurrent); err != nil {
return nil
}
@@ -2151,16 +2166,22 @@
// nolint: gocyclo
func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
- meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
- //nolint:staticcheck
- upstream := false
- if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
- upstream = true
- }
+ meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
+ upstream := classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
// Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
- meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
- mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ var meInstance *me.ManagedEntity
+ var err error
+
+ // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
+ if isCurrent {
+ meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ } else {
+ meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ }
+
if err != nil {
if CheckMeInstanceStatusCode(err) {
return err // Device is being deleted, so we stop processing
@@ -2269,13 +2290,23 @@
// nolint: gocyclo
func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
- meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
+ meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
// Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
requestedAttributes["IntervalEndTime"] = 0
}
- meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
- mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ var meInstance *me.ManagedEntity
+ var err error
+
+ // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
+ if isCurrent {
+ meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ } else {
+ meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ }
+
if err != nil {
if CheckMeInstanceStatusCode(err) {
return err // Device is being deleted, so we stop processing
@@ -2378,13 +2409,23 @@
// nolint: gocyclo
func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
- meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
+ meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
// Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
}
- meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
- mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ var meInstance *me.ManagedEntity
+ var err error
+
+ // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
+ if isCurrent {
+ meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ } else {
+ meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ }
+
if err != nil {
if CheckMeInstanceStatusCode(err) {
return err // Device is being deleted, so we stop processing
@@ -2400,9 +2441,14 @@
logger.Warnw(ctx, "Deleting the device, stopping FEC history metrics collection for the device ", log.Fields{"device-id": mm.deviceID})
return fmt.Errorf("deleting the device, stopping FEC history metrics collection for the device %v", mm.deviceID)
}
- case meAttributes = <-mm.l2PmChan:
+ case meAttributes = <-func() chan me.AttributeValueMap {
+ if isCurrent {
+ return mm.opticalMetricsChan
+ }
+ return mm.l2PmChan
+ }():
logger.Debugw(ctx, "received fec history data metrics",
- log.Fields{"device-id": mm.deviceID, "entityID": entityID})
+ log.Fields{"device-id": mm.deviceID, "entityID": entityID, "isCurrent": isCurrent})
case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
log.Fields{"device-id": mm.deviceID, "entityID": entityID})
@@ -2469,6 +2515,25 @@
return nil, nil
}
+// GetCurrentDataMEInstance gets current performance monitoring data from ME instance
+func (mm *OnuMetricsManager) GetCurrentDataMEInstance(ctx context.Context, classID me.ClassID, entityID uint16, requestedAttributes me.AttributeValueMap,
+ timeout int, highPrio bool, rxChan chan cmn.Message, isExtendedOmci bool) (*me.ManagedEntity, error) {
+
+ select {
+ case <-mm.pDeviceHandler.GetDeviceDeleteCommChan(ctx):
+ errMsg := "deleting the device, stopping GetCurrentDataMEInstance for the device " + mm.deviceID
+ logger.Warn(ctx, errMsg)
+ return nil, status.Error(codes.NotFound, errMsg)
+ default:
+ if mm.pOnuDeviceEntry.GetDevOmciCC() != nil {
+ meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetCurrentDataME(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ return meInstance, err
+ }
+ }
+ return nil, nil
+}
+
// CheckMeInstanceStatusCode checked status code if not found returns true
func CheckMeInstanceStatusCode(err error) bool {
if err != nil {
@@ -2482,13 +2547,23 @@
// nolint: gocyclo
func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
- meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
+ meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int, isCurrent bool) error {
// Insert "IntervalEndTime" is part of the requested attributes as we need this to compare the get responses when get request is multipart
if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
}
- meInstance, err := mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
- mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ var meInstance *me.ManagedEntity
+ var err error
+
+ // Use GetCurrentDataMEInstance if isCurrent is true, otherwise use GetMeInstance
+ if isCurrent {
+ meInstance, err = mm.GetCurrentDataMEInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ } else {
+ meInstance, err = mm.GetMeInstance(ctx, classID, entityID, requestedAttributes,
+ mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan, mm.isExtendedOmci)
+ }
+
if err != nil {
if CheckMeInstanceStatusCode(err) {
return err // Device is being deleted, so we stop processing
@@ -2661,7 +2736,7 @@
// nolint: unparam
func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
- meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
+ meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int, isCurrent bool) error {
var grpFunc groupMetricPopulateFunc
switch classID {
case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
@@ -2690,7 +2765,7 @@
size = v.Size + size
} else { // We exceeded the allow omci get size
// Let's collect the attributes via get now and collect remaining in the next iteration
- if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
+ if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime, isCurrent); err != nil {
logger.Errorw(ctx, "error during metric collection",
log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
return err
@@ -2701,7 +2776,7 @@
}
}
// Collect the omci get attributes for the last bunch of attributes.
- if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
+ if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime, isCurrent); err != nil {
logger.Errorw(ctx, "error during metric collection",
log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
return err
@@ -4130,6 +4205,29 @@
mm.deviceDeletionInProgress = true
}
+// safeGetMetricValue safely extracts a metric value from the metrics map
+// Returns 0 if the map is nil, key doesn't exist, or value is 0
+// Logs warnings for missing keys to aid in debugging
+func (mm *OnuMetricsManager) safeGetMetricValue(ctx context.Context, metrics map[string]float32, key string, deviceID string) uint32 {
+ if metrics == nil {
+ logger.Warnw(ctx, "Metrics map is nil", log.Fields{"device-id": deviceID, "key": key})
+ return 0
+ }
+
+ value, exists := metrics[key]
+ if !exists {
+ logger.Warnw(ctx, "Metric key not found in metrics map", log.Fields{"device-id": deviceID, "key": key})
+ return 0
+ }
+
+ if value < 0 {
+ logger.Warnw(ctx, "Negative metric value, setting to 0", log.Fields{"device-id": deviceID, "key": key, "value": value})
+ return 0
+ }
+
+ return uint32(value)
+}
+
// Obtain the ONU GEM counters for the ONU device
func (mm *OnuMetricsManager) GetONUGEMCounters(ctx context.Context) *extension.SingleGetValueResponse {
@@ -4167,15 +4265,16 @@
// Loop through each element in the slice
for _, gem := range gemSlice {
logger.Debugw(ctx, "Collecting stats for Gem: ", log.Fields{"GEMID": gem})
- if metricInfo := mm.collectGemHistoryData(ctx, gem); metricInfo != nil {
+ if metricInfo := mm.collectGemHistoryData(ctx, gem, true); metricInfo != nil {
logger.Infow(ctx, "Metricinfo for GEM", log.Fields{"GEMID": gem, "metricInfo": metricInfo})
gemHistoryData := extension.OnuGemPortHistoryData{}
gemHistoryData.GemId = uint32(gem)
- gemHistoryData.TransmittedGEMFrames = uint32(metricInfo.GetMetrics()["transmitted_gem_frames"])
- gemHistoryData.ReceivedGEMFrames = uint32(metricInfo.GetMetrics()["received_gem_frames"])
- gemHistoryData.ReceivedPayloadBytes = uint32(metricInfo.GetMetrics()["received_payload_bytes"])
- gemHistoryData.TransmittedPayloadBytes = uint32(metricInfo.GetMetrics()["transmitted_payload_bytes"])
- gemHistoryData.EncryptionKeyErrors = uint32(metricInfo.GetMetrics()["encryption_key_errors"])
+ metrics := metricInfo.GetMetrics()
+ gemHistoryData.TransmittedGEMFrames = mm.safeGetMetricValue(ctx, metrics, "transmitted_gem_frames", mm.deviceID)
+ gemHistoryData.ReceivedGEMFrames = mm.safeGetMetricValue(ctx, metrics, "received_gem_frames", mm.deviceID)
+ gemHistoryData.ReceivedPayloadBytes = mm.safeGetMetricValue(ctx, metrics, "received_payload_bytes", mm.deviceID)
+ gemHistoryData.TransmittedPayloadBytes = mm.safeGetMetricValue(ctx, metrics, "transmitted_payload_bytes", mm.deviceID)
+ gemHistoryData.EncryptionKeyErrors = mm.safeGetMetricValue(ctx, metrics, "encryption_key_errors", mm.deviceID)
allocIdGemData.GemPortInfo = append(allocIdGemData.GemPortInfo, &gemHistoryData)
logger.Debugw(ctx, " allocIdGemData value ", log.Fields{"AllocIDGemData": allocIdGemData})
@@ -4188,3 +4287,54 @@
return &resp
}
+
+// Obtain the ONU FEC counters for the ONU device
+func (mm *OnuMetricsManager) GetONUFECCounters(ctx context.Context) *extension.SingleGetValueResponse {
+
+ resp := extension.SingleGetValueResponse{
+ Response: &extension.GetValueResponse{
+ Status: extension.GetValueResponse_OK,
+ Response: &extension.GetValueResponse_FecHistory{
+ FecHistory: &extension.GetOnuFecHistoryResponse{},
+ },
+ },
+ }
+
+ if mm.GetdeviceDeletionInProgress() {
+ logger.Infow(ctx, "device already deleted, return", log.Fields{"curr-state": mm.PAdaptFsm.PFsm.Current, "deviceID": mm.deviceID})
+ return nil
+ }
+
+ mm.OnuMetricsManagerLock.RLock()
+ defer mm.OnuMetricsManagerLock.RUnlock()
+
+ FecHistoryInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
+ if len(FecHistoryInstKeys) > 0 {
+ firstInstanceKey := FecHistoryInstKeys[0]
+ logger.Debugw(ctx, "First FEC History Instance Key and Length", log.Fields{"InstanceKey": firstInstanceKey, "FecHistoryInstKeys": FecHistoryInstKeys, "Length": len(FecHistoryInstKeys)})
+
+ logger.Debugw(ctx, "Collecting FEC stats for ONU", log.Fields{"EntityID": firstInstanceKey})
+ if metricInfo := mm.collectFecHistoryData(ctx, firstInstanceKey, true); metricInfo != nil {
+ // Process FEC metrics data here
+ logger.Debugw(ctx, "FEC metrics collected successfully", log.Fields{"metricInfo": metricInfo})
+
+ // Populate the response with the collected FEC metrics directly
+ fecResponse := resp.Response.GetFecHistory()
+ metrics := metricInfo.GetMetrics()
+ fecResponse.CorrectedBytes = mm.safeGetMetricValue(ctx, metrics, "corrected_bytes", mm.deviceID)
+ fecResponse.CorrectedCodeWords = mm.safeGetMetricValue(ctx, metrics, "corrected_code_words", mm.deviceID)
+ fecResponse.UncorrectableCodeWords = mm.safeGetMetricValue(ctx, metrics, "uncorrectable_code_words", mm.deviceID)
+ fecResponse.TotalCodeWords = mm.safeGetMetricValue(ctx, metrics, "total_code_words", mm.deviceID)
+ fecResponse.FecSeconds = mm.safeGetMetricValue(ctx, metrics, "fec_seconds", mm.deviceID)
+
+ logger.Debugw(ctx, "FEC response populated successfully",
+ log.Fields{"device-id": mm.deviceID, "correctedBytes": fecResponse.CorrectedBytes,
+ "correctedCodeWords": fecResponse.CorrectedCodeWords, "fecSeconds": fecResponse.FecSeconds})
+ } else {
+ logger.Warnw(ctx, "Failed to collect FEC metrics", log.Fields{"device-id": mm.deviceID, "EntityID": firstInstanceKey})
+ }
+ }
+
+ logger.Debugw(ctx, "FEC History collection completed", log.Fields{"device-id": mm.deviceID})
+ return &resp
+}
diff --git a/vendor/github.com/opencord/omci-lib-go/v2/VERSION b/vendor/github.com/opencord/omci-lib-go/v2/VERSION
index 5859406..530cdd9 100644
--- a/vendor/github.com/opencord/omci-lib-go/v2/VERSION
+++ b/vendor/github.com/opencord/omci-lib-go/v2/VERSION
@@ -1 +1 @@
-2.2.3
+2.2.4
diff --git a/vendor/github.com/opencord/omci-lib-go/v2/meframe/me_getcurrent.go b/vendor/github.com/opencord/omci-lib-go/v2/meframe/me_getcurrent.go
index 2589bbb..de9343d 100644
--- a/vendor/github.com/opencord/omci-lib-go/v2/meframe/me_getcurrent.go
+++ b/vendor/github.com/opencord/omci-lib-go/v2/meframe/me_getcurrent.go
@@ -20,6 +20,7 @@
import (
"errors"
"fmt"
+
"github.com/google/gopacket"
. "github.com/opencord/omci-lib-go/v2"
me "github.com/opencord/omci-lib-go/v2/generated"
@@ -29,10 +30,24 @@
if opt.frameFormat == ExtendedIdent {
return nil, errors.New("extended message set for this message type is not supported")
}
- mask, err := checkAttributeMask(m, opt.attributeMask)
+ // Given mask sent in (could be default of 0xFFFF) get what is allowable.
+ // This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
+ // number of items.
+ maxMask, err := checkAttributeMask(m, opt.attributeMask)
if err != nil {
return nil, err
}
+ // Now scan attributes and reduce mask to only those requested
+ var mask uint16
+ mask, err = calculateAttributeMask(m, maxMask)
+ if err != nil {
+ return nil, err
+ }
+ if mask == 0 {
+ // TODO: Is a GetCurrentData request with no attributes valid?
+ return nil, errors.New("no attributes requested for GetCurrentDataRequest")
+ }
+
// Common for all MEs
meLayer := &GetCurrentDataRequest{
MeBasePacket: MeBasePacket{
@@ -40,14 +55,10 @@
EntityInstance: m.GetEntityID(),
Extended: opt.frameFormat == ExtendedIdent,
},
+ AttributeMask: mask,
}
- // Get payload space available
- maxPayload := maxPacketAvailable(m, opt)
- // TODO: Lots of work to do
-
- fmt.Println(mask, maxPayload)
- return meLayer, errors.New("todo: Not implemented")
+ return meLayer, nil
}
func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
@@ -58,6 +69,11 @@
if err != nil {
return nil, err
}
+ mask, err = calculateAttributeMask(m, mask)
+ if err != nil {
+ return nil, err
+ }
+
// Common for all MEs
meLayer := &GetCurrentDataResponse{
MeBasePacket: MeBasePacket{
@@ -65,12 +81,66 @@
EntityInstance: m.GetEntityID(),
Extended: opt.frameFormat == ExtendedIdent,
},
+ Result: opt.result,
+ AttributeMask: 0,
+ Attributes: make(me.AttributeValueMap),
}
- // Get payload space available
- maxPayload := maxPacketAvailable(m, opt)
- // TODO: Lots of work to do
+ if meLayer.Result == me.AttributeFailure {
+ meLayer.UnsupportedAttributeMask = opt.unsupportedMask
+ meLayer.FailedAttributeMask = opt.attrExecutionMask
+ }
- fmt.Println(mask, maxPayload)
- return meLayer, errors.New("todo: Not implemented")
+ // Encode whatever we can
+ if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
+ // Get payload space available
+ maxPayload := maxPacketAvailable(m, opt)
+ payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
+ meDefinition := m.GetManagedEntityDefinition()
+ attrDefs := meDefinition.GetAttributeDefinitions()
+ attrMap := m.GetAttributeValueMap()
+
+ if mask != 0 {
+ // Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
+ var attrIndex uint
+ for attrIndex = 1; attrIndex <= 16; attrIndex++ {
+ // Is this attribute requested
+ if mask&(1<<(16-attrIndex)) != 0 {
+ // Get definitions since we need the name
+ attrDef, ok := attrDefs[attrIndex]
+ if !ok {
+ msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
+ attrIndex, meDefinition.GetName())
+ return nil, errors.New(msg)
+ }
+ var attrValue interface{}
+ attrValue, ok = attrMap[attrDef.Name]
+ if !ok {
+ msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
+ attrDef.GetName(), meDefinition.GetName(), m)
+ return nil, errors.New(msg)
+ }
+ // Is space available?
+ if attrDef.Size <= payloadAvailable {
+ // Mark bit handled
+ mask &= ^attrDef.Mask
+ meLayer.AttributeMask |= attrDef.Mask
+ meLayer.Attributes[attrDef.Name] = attrValue
+ payloadAvailable -= attrDef.Size
+
+ } else if opt.failIfTruncated {
+ msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetCurrentDataResponse message",
+ attrDef.GetName())
+ return nil, me.NewMessageTruncatedError(msg)
+ } else {
+ // Add to existing 'failed' mask and update result
+ meLayer.FailedAttributeMask |= attrDef.Mask
+ meLayer.Result = me.AttributeFailure
+ }
+ }
+ }
+ }
+ }
+
+ return meLayer, nil
}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 7aa67c6..b6dc866 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -176,7 +176,7 @@
# github.com/looplab/fsm v0.2.0
## explicit; go 1.13
github.com/looplab/fsm
-# github.com/opencord/omci-lib-go/v2 v2.2.3
+# github.com/opencord/omci-lib-go/v2 v2.2.4
## explicit; go 1.16
github.com/opencord/omci-lib-go/v2
github.com/opencord/omci-lib-go/v2/generated