[VOL-4302] Marking the software-image as downloaded only if the download completes successfully
Change-Id: I1595ace9a18c728a1d3f58495d9b84c9b32ec655
diff --git a/VERSION b/VERSION
index f8e233b..a5543c6 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.9.0
+1.9.1-dev
diff --git a/internal/bbsim/devices/onu.go b/internal/bbsim/devices/onu.go
index 11ace9f..e40c854 100644
--- a/internal/bbsim/devices/onu.go
+++ b/internal/bbsim/devices/onu.go
@@ -126,6 +126,7 @@
CommittedImageEntityId uint16
StandbyImageVersion string
ActiveImageVersion string
+ InDownloadImageVersion string
CommittedImageVersion string
OmciResponseRate uint8
OmciMsgCounter uint8
@@ -1016,7 +1017,7 @@
}).Trace("received-download-section-request")
//Extracting the first 14 bytes to use as a version for this image.
if o.ImageSoftwareReceivedSections == 0 {
- o.StandbyImageVersion = string(msgObj.SectionData[0:14])
+ o.InDownloadImageVersion = string(msgObj.SectionData[0:14])
}
o.ImageSectionData = append(o.ImageSectionData, msgObj.SectionData...)
o.ImageSoftwareReceivedSections++
@@ -1057,58 +1058,8 @@
o.ImageSoftwareReceivedSections++
}
case omci.EndSoftwareDownloadRequestType:
+ success := o.handleEndSoftwareDownloadRequest(msg)
- // In the startSoftwareDownload we get the image size and the window size.
- // We calculate how many DownloadSection we should receive and validate
- // that we got the correct amount when we receive this message
- success := true
- if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
- onuLogger.WithFields(log.Fields{
- "OnuId": o.ID,
- "IntfId": o.PonPortID,
- "OnuSn": o.Sn(),
- "ExpectedSections": o.ImageSoftwareExpectedSections,
- "ReceivedSections": o.ImageSoftwareReceivedSections,
- }).Errorf("onu-did-not-receive-all-image-sections")
- success = false
- }
- if success {
- // Validate Image Crc.
- msgObj, err := omcilib.ParseEndSoftwareDownloadRequest(msg.OmciPkt)
- if err != nil {
- onuLogger.WithFields(log.Fields{
- "OmciMsgType": msg.OmciMsg.MessageType,
- "TransCorrId": msg.OmciMsg.TransactionID,
- "Err": errResp.Error(),
- "IntfId": o.PonPortID,
- "SerialNumber": o.Sn(),
- }).Error("error-while-processing-end-software-download-request")
- }
- computedCRC := crc32a.Checksum(o.ImageSectionData[:int(msgObj.ImageSize)])
- //Convert the crc to network byte order
- var byteSlice []byte = make([]byte, 4)
- binary.LittleEndian.PutUint32(byteSlice, uint32(computedCRC))
- computedCRC = binary.BigEndian.Uint32(byteSlice)
-
- onuLogger.WithFields(log.Fields{
- "OnuId": o.ID,
- "IntfId": o.PonPortID,
- "OnuSn": o.Sn(),
- "ReceivedCRC": msgObj.CRC32,
- "CalculatedCRC": computedCRC,
- }).Debug("onu-image-crc-validation-params")
-
- if msgObj.CRC32 != computedCRC {
- onuLogger.WithFields(log.Fields{
- "OnuId": o.ID,
- "IntfId": o.PonPortID,
- "OnuSn": o.Sn(),
- "ReceivedCRC": msgObj.CRC32,
- "CalculatedCRC": computedCRC,
- }).Errorf("onu-image-crc-validation-falied")
- success = false
- }
- }
if success {
if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.Success); errResp == nil {
o.MibDataSync++
@@ -1127,7 +1078,7 @@
"Err": errResp.Error(),
"IntfId": o.PonPortID,
"SerialNumber": o.Sn(),
- }).Error("error-while-processing-end-software-download-request")
+ }).Error("error-while-responding-to-end-software-download-request")
}
} else {
if responsePkt, errResp = omcilib.CreateEndSoftwareDownloadResponse(msg.OmciPkt, msg.OmciMsg, me.ProcessingError); errResp == nil {
@@ -1424,6 +1375,81 @@
return nil
}
+// returns true if the request is successful, false otherwise
+func (o *Onu) handleEndSoftwareDownloadRequest(msg bbsim.OmciMessage) bool {
+ msgObj, err := omcilib.ParseEndSoftwareDownloadRequest(msg.OmciPkt)
+ if err != nil {
+ onuLogger.WithFields(log.Fields{
+ "OmciMsgType": msg.OmciMsg.MessageType,
+ "TransCorrId": msg.OmciMsg.TransactionID,
+ "Err": err.Error(),
+ "IntfId": o.PonPortID,
+ "SerialNumber": o.Sn(),
+ }).Error("error-while-processing-end-software-download-request")
+ return false
+ }
+
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ "msgObj": msgObj,
+ }).Trace("EndSoftwareDownloadRequest received message")
+
+ // if the image download is ongoing and we receive a message with
+ // ImageSize = 0 and Crc = 4294967295 (0xFFFFFFFF) respond with success
+ if o.ImageSoftwareReceivedSections > 0 &&
+ msgObj.ImageSize == 0 &&
+ msgObj.CRC32 == 4294967295 {
+ o.ImageSoftwareReceivedSections = 0
+ // NOTE potentially we may want to add a ONU state to reflect
+ // the software download abort
+ return true
+ }
+
+ // In the startSoftwareDownload we get the image size and the window size.
+ // We calculate how many DownloadSection we should receive and validate
+ // that we got the correct amount when we receive this message
+ // If the received sections are different from the expected sections
+ // respond with failure
+ if o.ImageSoftwareExpectedSections != o.ImageSoftwareReceivedSections {
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ "ExpectedSections": o.ImageSoftwareExpectedSections,
+ "ReceivedSections": o.ImageSoftwareReceivedSections,
+ }).Errorf("onu-did-not-receive-all-image-sections")
+ return false
+ }
+
+ // check the received CRC vs the computed CRC
+ computedCRC := crc32a.Checksum(o.ImageSectionData[:int(msgObj.ImageSize)])
+ //Convert the crc to network byte order
+ var byteSlice = make([]byte, 4)
+ binary.LittleEndian.PutUint32(byteSlice, computedCRC)
+ computedCRC = binary.BigEndian.Uint32(byteSlice)
+ if msgObj.CRC32 != computedCRC {
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ "ReceivedCRC": msgObj.CRC32,
+ "CalculatedCRC": computedCRC,
+ }).Errorf("onu-image-crc-validation-failed")
+ return false
+ }
+
+ o.StandbyImageVersion = o.InDownloadImageVersion
+ onuLogger.WithFields(log.Fields{
+ "OnuId": o.ID,
+ "IntfId": o.PonPortID,
+ "OnuSn": o.Sn(),
+ "StandbyVersion": o.StandbyImageVersion,
+ }).Debug("onu-image-version-updated")
+ return true
+}
+
// BBR methods
func sendOmciMsg(pktBytes []byte, intfId uint32, onuId uint32, sn *openolt.SerialNumber, msgType string, client openolt.OpenoltClient) {
diff --git a/internal/bbsim/devices/onu_omci_test.go b/internal/bbsim/devices/onu_omci_test.go
index 9f2444f..2c2b489 100644
--- a/internal/bbsim/devices/onu_omci_test.go
+++ b/internal/bbsim/devices/onu_omci_test.go
@@ -24,6 +24,7 @@
me "github.com/opencord/omci-lib-go/v2/generated"
"github.com/opencord/voltha-protos/v5/go/openolt"
"gotest.tools/assert"
+ "strconv"
"testing"
)
@@ -128,13 +129,15 @@
return omciPkt
}
-func makeOmciEndSoftwareDownloadRequest(t *testing.T) []byte {
+func makeOmciEndSoftwareDownloadRequest(t *testing.T, imageSize uint32, imageCrc uint32) []byte {
omciReq := &omci.EndSoftwareDownloadRequest{
MeBasePacket: omci.MeBasePacket{
EntityClass: me.SoftwareImageClassID,
},
NumberOfInstances: 1,
ImageInstances: []uint16{0},
+ ImageSize: imageSize,
+ CRC32: imageCrc,
}
omciPkt, err := omcilib.Serialize(omci.EndSoftwareDownloadRequestType, omciReq, 66)
if err != nil {
@@ -250,9 +253,11 @@
assert.Equal(t, onu.MibDataSync, uint8(4))
// End software download
- onu.ImageSoftwareReceivedSections = 1 // we fake that we have received the one download section we expect
+ onu.ImageSoftwareExpectedSections = 31
+ onu.ImageSoftwareReceivedSections = 31 // we fake that we have received all the download section we expect
+ onu.ImageSectionData = []byte{111, 114, 116, 116, 105, 116, 111, 114, 32, 113, 117, 105, 115, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 110, 101, 99, 32, 108, 105, 98, 101}
onu.InternalState.SetState(OnuStateImageDownloadInProgress)
- err = onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t)), stream)
+ err = onu.handleOmciRequest(makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t, 31, 1523894119)), stream)
assert.NilError(t, err)
assert.Equal(t, onu.MibDataSync, uint8(5))
@@ -361,3 +366,37 @@
assert.Equal(t, stream.CallCount, int(onu.OmciResponseRate))
}
}
+
+func Test_EndSoftwareDownloadRequestHandling(t *testing.T) {
+ onu := createTestOnu()
+
+ // test EndSoftwareDownloadRequest in case of abort
+ onu.ImageSoftwareReceivedSections = 2
+ imageCrc, _ := strconv.ParseInt("FFFFFFFF", 16, 64)
+ msg := makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t, 0, uint32(imageCrc)))
+ res := onu.handleEndSoftwareDownloadRequest(msg)
+ assert.Equal(t, res, true)
+ assert.Equal(t, onu.ImageSoftwareReceivedSections, 0)
+
+ // test EndSoftwareDownloadRequest if we received less sections than expected
+ onu.ImageSoftwareExpectedSections = 2
+ onu.ImageSoftwareReceivedSections = 1
+ msg = makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t, 2, 2))
+ res = onu.handleEndSoftwareDownloadRequest(msg)
+ assert.Equal(t, res, false)
+
+ // test CRC Mismatch
+ onu.ImageSectionData = []byte{111, 114, 116, 116, 105, 116, 111, 114, 32, 113, 117, 105, 115, 46, 32, 86, 105, 118, 97, 109, 117, 115, 32, 110, 101, 99, 32, 108, 105, 98, 101}
+ onu.ImageSoftwareExpectedSections = 2
+ onu.ImageSoftwareReceivedSections = 2
+ msg = makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t, 31, 12))
+ res = onu.handleEndSoftwareDownloadRequest(msg)
+ assert.Equal(t, res, false)
+
+ // if it's a valid case then set the StandbyImageVersion
+ onu.InDownloadImageVersion = "DownloadedImage"
+ msg = makeOmciMessage(t, onu, makeOmciEndSoftwareDownloadRequest(t, 31, 1523894119))
+ res = onu.handleEndSoftwareDownloadRequest(msg)
+ assert.Equal(t, res, true)
+ assert.Equal(t, onu.StandbyImageVersion, "DownloadedImage")
+}