[VOL-4655] Panic in isSuccessfulResponseWithMibDataSync handler if the decoded msgLayer is nil
Change-Id: I6e5e4ef7b7ebde01b7cfa9bb243b72b9e85d7181
diff --git a/VERSION b/VERSION
index 2e369c9..473593f 100755
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.2-dev274
+2.2.2-dev275
diff --git a/internal/pkg/common/omci_cc.go b/internal/pkg/common/omci_cc.go
index 463bc06..6c01694 100755
--- a/internal/pkg/common/omci_cc.go
+++ b/internal/pkg/common/omci_cc.go
@@ -318,8 +318,11 @@
oo.printRxMessage(ctx, rxMsg)
return fmt.Errorf("rxOmciMessage too small for BaseFormat %s", oo.deviceID)
}
-
- packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, gopacket.NoCopy)
+ decodeOptions := gopacket.DecodeOptions{
+ Lazy: true,
+ NoCopy: true,
+ }
+ packet := gopacket.NewPacket(rxMsg, omci.LayerTypeOMCI, decodeOptions)
if packet == nil {
logger.Errorw(ctx, "omci-message could not be decoded", log.Fields{"device-id": oo.deviceID})
oo.printRxMessage(ctx, rxMsg)
@@ -350,14 +353,15 @@
return fmt.Errorf("could not assign omci layer %s", oo.deviceID)
}
logger.Debugw(ctx, "omci-message-decoded:", log.Fields{"omciMsgType": omciMsg.MessageType,
- "transCorrId": strconv.FormatInt(int64(omciMsg.TransactionID), 16), "DeviceIdent": omciMsg.DeviceIdentifier})
+ "transCorrId": strconv.FormatInt(int64(omciMsg.TransactionID), 16),
+ "DeviceIdent": omciMsg.DeviceIdentifier, "device-id": oo.deviceID})
// TestResult is asynchronous indication that carries the same TID as the TestResponse.
// We expect to find the TID in the oo.rxSchedulerMap
if byte(omciMsg.MessageType)&me.AK == 0 && omciMsg.MessageType != omci.TestResultType {
// Not a response
oo.printRxMessage(ctx, rxMsg)
- logger.Debug(ctx, "RxMsg is no Omci Response Message")
+ logger.Debugw(ctx, "RxMsg is no Omci Response Message", log.Fields{"device-id": oo.deviceID})
if omciMsg.TransactionID == 0 {
return oo.receiveOnuMessage(ctx, omciMsg, &packet)
}
@@ -376,8 +380,19 @@
//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 rxCallbackEntry.CbFunction(ctx, omciMsg, &packet, rxCallbackEntry.CbRespChannel)
- if isSuccessfulResponseWithMibDataSync(omciMsg, &packet) {
+ isSuccessfulResponse, err := oo.isSuccessfulResponseWithMibDataSync(ctx, omciMsg, &packet)
+ if err != nil {
+ // qualified error logging already done in function above
+ if !rxCallbackEntry.FramePrint {
+ oo.printRxMessage(ctx, rxMsg)
+ }
+ return fmt.Errorf("could not decode further layers %s", oo.deviceID)
+ }
+ if isSuccessfulResponse {
oo.pOnuDeviceEntry.IncrementMibDataSync(ctx)
+ } else {
+ logger.Debugw(ctx, "mibDataSync counter not to be updated for this message type",
+ log.Fields{"omciMsg.MessageType": omciMsg.MessageType, "device-id": oo.deviceID})
}
// If omciMsg.MessageType is omci.TestResponseType, we still expect the TestResult OMCI message,
@@ -4592,58 +4607,109 @@
}
//nolint: gocyclo
-func isSuccessfulResponseWithMibDataSync(omciMsg *omci.OMCI, packet *gp.Packet) bool {
+func (oo *OmciCC) isSuccessfulResponseWithMibDataSync(ctx context.Context, omciMsg *omci.OMCI, packet *gp.Packet) (bool, error) {
+
+ nextLayer, err := omci.MsgTypeToNextLayer(omciMsg.MessageType, false)
+ if err != nil {
+ logger.Errorw(ctx, "omci-message: could not map msgType to nextLayer", log.Fields{"device-id": oo.deviceID})
+ return false, fmt.Errorf("could not map msgType to nextLayer - %s", oo.deviceID)
+ }
+ msgLayer := (*packet).Layer(nextLayer)
+ if msgLayer != nil {
+ // Note: Due to relaxed decoding, you may now still have a decoding error attached to the layers
+ if failure := (*packet).ErrorLayer(); failure != nil {
+ if nextLayer == omci.LayerTypeMibUploadNextResponse {
+ // In the case of MibUploadNextResponse, we let the packet pass so that later processing
+ // can examine for UnkonwnMEs and UnknownAttributes
+ logger.Infow(ctx, "omci-message: MibUploadNextResponse packet with ErrorLayer - let it pass",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error()})
+ return false, nil
+ } else if nextLayer == omci.LayerTypeGetResponse {
+ if resp := msgLayer.(*omci.GetResponse); resp != nil {
+ if resp.NextLayerType() == omci.LayerTypeUnknownAttributes {
+ unknownAttrLayer := (*packet).Layer(omci.LayerTypeUnknownAttributes)
+ if unknownAttrLayer != nil {
+ logger.Errorw(ctx, "omci-message: GetResponse packet contains unknownAttrLayer - skip it!",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error(), "unknownAttrLayer": unknownAttrLayer})
+ return false, fmt.Errorf("packet contains unknownAttrLayer - %s", oo.deviceID)
+ }
+ }
+ }
+ }
+ // Try to decode any further error information
+ if decodeFailure, ok := failure.(*gopacket.DecodeFailure); ok && decodeFailure != nil {
+ logger.Errorw(ctx, "omci-message: packet contains ErrorLayer with further info - skip it!",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error(), "decodeFailure": decodeFailure.String()})
+ return false, fmt.Errorf("packet contains ErrorLayer with further info - %s", oo.deviceID)
+ }
+ logger.Errorw(ctx, "omci-message: packet contains ErrorLayer - skip it!",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error()})
+ return false, fmt.Errorf("packet contains ErrorLayer - %s", oo.deviceID)
+ }
+ } else if failure := (*packet).ErrorLayer(); failure != nil {
+ // message layer could not be decoded, but at least check if additional failure information is available
+ if decodeFailure, ok := failure.(*gopacket.DecodeFailure); ok && decodeFailure != nil {
+ logger.Errorw(ctx, "omci-message: could not decode msgLayer of packet, further info available - skip it!",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error(), "decodeFailure": decodeFailure.String()})
+ return false, fmt.Errorf("could not decode msgLayer of packet, further info available - %s", oo.deviceID)
+ }
+ logger.Errorw(ctx, "omci-message: could not decode msgLayer of packet, ErrorLayer available",
+ log.Fields{"device-id": oo.deviceID, "error": failure.Error()})
+ return false, fmt.Errorf("could not decode msgLayer of packet, ErrorLayer available - %s", oo.deviceID)
+ } else {
+ logger.Errorw(ctx, "omci-message: could not decode msgLayer of packet", log.Fields{"device-id": oo.deviceID})
+ return false, fmt.Errorf("could not decode msgLayer of packet - %s", oo.deviceID)
+ }
+
for _, v := range responsesWithMibDataSync {
if v == omciMsg.MessageType {
- nextLayer, _ := omci.MsgTypeToNextLayer(v, false)
- msgLayer := (*packet).Layer(nextLayer)
switch nextLayer {
case omci.LayerTypeCreateResponse:
if resp := msgLayer.(*omci.CreateResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeDeleteResponse:
if resp := msgLayer.(*omci.DeleteResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeSetResponse:
if resp := msgLayer.(*omci.SetResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeStartSoftwareDownloadResponse:
if resp := msgLayer.(*omci.StartSoftwareDownloadResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeEndSoftwareDownloadResponse:
if resp := msgLayer.(*omci.EndSoftwareDownloadResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeActivateSoftwareResponse:
if resp := msgLayer.(*omci.ActivateSoftwareResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
case omci.LayerTypeCommitSoftwareResponse:
if resp := msgLayer.(*omci.CommitSoftwareResponse); resp != nil {
if resp.Result == me.Success {
- return true
+ return true, nil
}
}
}
}
}
- return false
+ return false, nil
}
func (oo *OmciCC) processRequestMonitoring(ctx context.Context, aOmciTxRequest OmciTransferStructure) {