dev: Fix buffer length when unserializing an eth pkt
authorMichael LeBeane <michael.lebeane@amd.com>
Tue, 29 Nov 2016 18:04:45 +0000 (13:04 -0500)
committerMichael LeBeane <michael.lebeane@amd.com>
Tue, 29 Nov 2016 18:04:45 +0000 (13:04 -0500)
Changeset 11701 only serialized the useful portion of of an ethernet packets'
payload. However, the device models expect each ethernet packet to contain
a 16KB buffer, even if there is no data in it. This patch adds a 'bufLength'
field to EthPacketData so the original size of the packet buffer can always
be unserialized.

Reported-by: Gabor Dozsa <Gabor.Dozsa@arm.com>
src/dev/net/etherpkt.cc
src/dev/net/etherpkt.hh
src/dev/net/i8254xGBe.cc
src/dev/net/ns_gige.cc
src/dev/net/sinic.cc

index 446e44e468efb3dbeb6124e13c003eeba6429900..22c0156d04be5cfdc1bed0353502408dc4fec047 100644 (file)
@@ -42,6 +42,7 @@ void
 EthPacketData::serialize(const string &base, CheckpointOut &cp) const
 {
     paramOut(cp, base + ".simLength", simLength);
+    paramOut(cp, base + ".bufLength", bufLength);
     paramOut(cp, base + ".length", length);
     arrayParamOut(cp, base + ".data", data, length);
 }
@@ -50,11 +51,23 @@ void
 EthPacketData::unserialize(const string &base, CheckpointIn &cp)
 {
     paramIn(cp, base + ".length", length);
-    if (length) {
-        assert(data == nullptr);
-        data = new uint8_t[length];
-        arrayParamIn(cp, base + ".data", data, length);
+    unsigned chkpt_buf_length;
+    if (optParamIn(cp, base + ".bufLength", chkpt_buf_length)) {
+        // If bufLength is in the checkpoint, make sure that the current buffer
+        // is unallocated or that the checkpoint requested size is smaller than
+        // the current buffer.
+        assert(!data || chkpt_buf_length <= bufLength);
+        bufLength = chkpt_buf_length;
+    } else {
+        // If bufLength is not in the checkpoint, try to use the existing
+        // buffer or use length to size the buffer
+        if (!data)
+            bufLength = length;
     }
+    assert(length <= bufLength);
+    if (!data)
+        data = new uint8_t[bufLength];
+    arrayParamIn(cp, base + ".data", data, length);
     if (!optParamIn(cp, base + ".simLength", simLength))
         simLength = length;
 }
index f84c03a4c28c02d32c16c0737777a61136700734..a9cc79b80d8297b4f4de90a042810c4ba183bb89 100644 (file)
@@ -54,6 +54,11 @@ class EthPacketData
      */
     uint8_t *data;
 
+    /**
+     * Total size of the allocated data buffer.
+     */
+    unsigned bufLength;
+
     /**
      * Amount of space occupied by the payload in the data buffer
      */
@@ -69,11 +74,11 @@ class EthPacketData
     unsigned simLength;
 
     EthPacketData()
-        : data(nullptr), length(0), simLength(0)
+        : data(nullptr), bufLength(0), length(0), simLength(0)
     { }
 
     explicit EthPacketData(unsigned size)
-        : data(new uint8_t[size]), length(0), simLength(0)
+        : data(new uint8_t[size]), bufLength(size), length(0), simLength(0)
     { }
 
     ~EthPacketData() { if (data) delete [] data; }
index 11f017a21b2cbcab61c88752f7c906dd47a1703e..baca0138fb5612b5385c8f83c2aa1d38966e9aa7 100644 (file)
@@ -2522,7 +2522,7 @@ IGbE::unserialize(CheckpointIn &cp)
     bool txPktExists;
     UNSERIALIZE_SCALAR(txPktExists);
     if (txPktExists) {
-        txPacket = std::make_shared<EthPacketData>();
+        txPacket = std::make_shared<EthPacketData>(16384);
         txPacket->unserialize("txpacket", cp);
     }
 
index 91a0da7a9fdb37abb129890b09ec2aa506bc36a4..50bb6ed17ea99eb3e4ded5fa2af47c1b891504de 100644 (file)
@@ -2352,7 +2352,7 @@ NSGigE::unserialize(CheckpointIn &cp)
     bool txPacketExists;
     UNSERIALIZE_SCALAR(txPacketExists);
     if (txPacketExists) {
-        txPacket = make_shared<EthPacketData>();
+        txPacket = make_shared<EthPacketData>(16384);
         txPacket->unserialize("txPacket", cp);
         uint32_t txPktBufPtr;
         UNSERIALIZE_SCALAR(txPktBufPtr);
index de8d4e98ae2a2da67a6abd6d775c94f3b3b2215e..e86e1abe26d3b4e7ddd9e132743efde687342f3a 100644 (file)
@@ -1496,7 +1496,7 @@ Device::unserialize(CheckpointIn &cp)
     UNSERIALIZE_SCALAR(txPacketExists);
     txPacket = 0;
     if (txPacketExists) {
-        txPacket = make_shared<EthPacketData>();
+        txPacket = make_shared<EthPacketData>(16384);
         txPacket->unserialize("txPacket", cp);
         UNSERIALIZE_SCALAR(txPacketOffset);
         UNSERIALIZE_SCALAR(txPacketBytes);