dev: Add 'simLength' parameter in EthPacketData
Currently, all the network devices create a 16K buffer for the 'data' field
in EthPacketData, and use 'length' to keep track of the size of the packet
in the buffer.  This patch introduces the 'simLength' parameter to
EthPacketData, which is used to hold the effective length of the packet used
for all timing calulations in the simulator.  Serialization is performed using
only the useful data in the packet ('length') and not necessarily the entire
original buffer.
diff --git a/src/dev/net/dist_etherlink.cc b/src/dev/net/dist_etherlink.cc
index a793739..a1cdc01 100644
--- a/src/dev/net/dist_etherlink.cc
+++ b/src/dev/net/dist_etherlink.cc
@@ -197,7 +197,7 @@
     }
 
     packet = pkt;
-    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+    Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0);
     if (delayVar != 0)
         delay += random_mt.random<Tick>(0, delayVar);
 
@@ -233,7 +233,7 @@
     bool packet_exists;
     UNSERIALIZE_SCALAR(packet_exists);
     if (packet_exists) {
-        packet = make_shared<EthPacketData>(16384);
+        packet = make_shared<EthPacketData>();
         packet->unserialize("packet", cp);
     }
 
diff --git a/src/dev/net/dist_iface.cc b/src/dev/net/dist_iface.cc
index 0e48770..26fe453 100644
--- a/src/dev/net/dist_iface.cc
+++ b/src/dev/net/dist_iface.cc
@@ -407,7 +407,7 @@
         Desc d = descQueue.front();
         descQueue.pop();
         d.sendTick = curTick();
-        d.sendDelay = d.packet->size(); // assume 1 tick/byte max link speed
+        d.sendDelay = d.packet->simLength; // assume 1 tick/byte max link speed
         v.push_back(d);
     }
 
@@ -493,7 +493,7 @@
 {
         UNSERIALIZE_SCALAR(sendTick);
         UNSERIALIZE_SCALAR(sendDelay);
-        packet = std::make_shared<EthPacketData>(16384);
+        packet = std::make_shared<EthPacketData>();
         packet->unserialize("rxPacket", cp);
 }
 
@@ -583,14 +583,15 @@
     header.sendTick  = curTick();
     header.sendDelay = send_delay;
 
-    header.dataPacketLength = pkt->size();
+    header.dataPacketLength = pkt->length;
+    header.simLength = pkt->simLength;
 
     // Send out the packet and the meta info.
     sendPacket(header, pkt);
 
     DPRINTF(DistEthernetPkt,
             "DistIface::sendDataPacket() done size:%d send_delay:%llu\n",
-            pkt->size(), send_delay);
+            pkt->length, send_delay);
 }
 
 void
diff --git a/src/dev/net/dist_packet.hh b/src/dev/net/dist_packet.hh
index 4c079c4..b154ab4 100644
--- a/src/dev/net/dist_packet.hh
+++ b/src/dev/net/dist_packet.hh
@@ -86,6 +86,11 @@
          */
         MsgType msgType;
         Tick sendTick;
+        /**
+         * Length used for modeling timing in the simulator.
+         * (from EthPacketData::simLength).
+         */
+        unsigned simLength;
         union {
             Tick sendDelay;
             Tick syncRepeat;
@@ -93,6 +98,7 @@
         union {
             /**
              * Actual length of the simulated Ethernet packet.
+             * (from EthPacketData::length).
              */
             unsigned dataPacketLength;
             struct {
diff --git a/src/dev/net/etherbus.cc b/src/dev/net/etherbus.cc
index ba5beab..042c4ec 100644
--- a/src/dev/net/etherbus.cc
+++ b/src/dev/net/etherbus.cc
@@ -98,7 +98,7 @@
 
     packet = pkt;
     sender = sndr;
-    int delay = (int)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+    int delay = (int)ceil(((double)pkt->simLength * ticksPerByte) + 1.0);
     DPRINTF(Ethernet, "scheduling packet: delay=%d, (rate=%f)\n",
             delay, ticksPerByte);
     schedule(event, curTick() + delay);
diff --git a/src/dev/net/etherlink.cc b/src/dev/net/etherlink.cc
index c327a01..0975ba4 100644
--- a/src/dev/net/etherlink.cc
+++ b/src/dev/net/etherlink.cc
@@ -192,7 +192,7 @@
     DDUMP(EthernetData, pkt->data, pkt->length);
 
     packet = pkt;
-    Tick delay = (Tick)ceil(((double)pkt->length * ticksPerByte) + 1.0);
+    Tick delay = (Tick)ceil(((double)pkt->simLength * ticksPerByte) + 1.0);
     if (delayVar != 0)
         delay += random_mt.random<Tick>(0, delayVar);
 
@@ -235,7 +235,7 @@
     bool packet_exists;
     paramIn(cp, base + ".packet_exists", packet_exists);
     if (packet_exists) {
-        packet = make_shared<EthPacketData>(16384);
+        packet = make_shared<EthPacketData>();
         packet->unserialize(base + ".packet", cp);
     }
 
@@ -251,7 +251,7 @@
     if (optParamIn(cp, base + ".tx_queue_size", tx_queue_size)) {
         for (size_t idx = 0; idx < tx_queue_size; ++idx) {
             Tick tick;
-            EthPacketPtr delayed_packet = make_shared<EthPacketData>(16384);
+            EthPacketPtr delayed_packet = make_shared<EthPacketData>();
 
             paramIn(cp, csprintf("%s.txQueue[%i].tick", base, idx), tick);
             delayed_packet->unserialize(
diff --git a/src/dev/net/etherpkt.cc b/src/dev/net/etherpkt.cc
index f06af33..446e44e 100644
--- a/src/dev/net/etherpkt.cc
+++ b/src/dev/net/etherpkt.cc
@@ -41,6 +41,7 @@
 void
 EthPacketData::serialize(const string &base, CheckpointOut &cp) const
 {
+    paramOut(cp, base + ".simLength", simLength);
     paramOut(cp, base + ".length", length);
     arrayParamOut(cp, base + ".data", data, length);
 }
@@ -49,7 +50,12 @@
 EthPacketData::unserialize(const string &base, CheckpointIn &cp)
 {
     paramIn(cp, base + ".length", length);
-    if (length)
+    if (length) {
+        assert(data == nullptr);
+        data = new uint8_t[length];
         arrayParamIn(cp, base + ".data", data, length);
+    }
+    if (!optParamIn(cp, base + ".simLength", simLength))
+        simLength = length;
 }
 
diff --git a/src/dev/net/etherpkt.hh b/src/dev/net/etherpkt.hh
index 4575632..f84c03a 100644
--- a/src/dev/net/etherpkt.hh
+++ b/src/dev/net/etherpkt.hh
@@ -49,33 +49,37 @@
 class EthPacketData
 {
   public:
-    /*
+    /**
      * Pointer to packet data will be deleted
      */
     uint8_t *data;
 
-    /*
-     * Length of the current packet
+    /**
+     * Amount of space occupied by the payload in the data buffer
      */
     unsigned length;
 
-  public:
+    /**
+     * Effective length, used for modeling timing in the simulator.
+     * This could be different from length if the packets are assumed
+     * to use a tightly packed or compressed format, but it's not worth
+     * the performance/complexity hit to perform that packing or compression
+     * in the simulation.
+     */
+    unsigned simLength;
+
     EthPacketData()
-        : data(NULL), length(0)
+        : data(nullptr), length(0), simLength(0)
     { }
 
     explicit EthPacketData(unsigned size)
-        : data(new uint8_t[size]), length(0)
+        : data(new uint8_t[size]), length(0), simLength(0)
     { }
 
     ~EthPacketData() { if (data) delete [] data; }
 
-  public:
-
     void serialize(const std::string &base, CheckpointOut &cp) const;
     void unserialize(const std::string &base, CheckpointIn &cp);
-
-    unsigned size() const { return length; }
 };
 
 typedef std::shared_ptr<EthPacketData> EthPacketPtr;
diff --git a/src/dev/net/etherswitch.cc b/src/dev/net/etherswitch.cc
index 52d9b11..c9698cf 100644
--- a/src/dev/net/etherswitch.cc
+++ b/src/dev/net/etherswitch.cc
@@ -200,7 +200,7 @@
 Tick
 EtherSwitch::Interface::switchingDelay()
 {
-    Tick delay = (Tick)ceil(((double)outputFifo.front()->length
+    Tick delay = (Tick)ceil(((double)outputFifo.front()->simLength
                                      * ticksPerByte) + 1.0);
     if (delayVar != 0)
                 delay += random_mt.random<Tick>(0, delayVar);
diff --git a/src/dev/net/ethertap.cc b/src/dev/net/ethertap.cc
index e8ece15..e09b7a3 100644
--- a/src/dev/net/ethertap.cc
+++ b/src/dev/net/ethertap.cc
@@ -239,6 +239,7 @@
         EthPacketPtr packet;
         packet = make_shared<EthPacketData>(data_len);
         packet->length = data_len;
+        packet->simLength = data_len;
         memcpy(packet->data, data, data_len);
 
         assert(buffer_offset >= data_len + sizeof(uint32_t));
diff --git a/src/dev/net/i8254xGBe.cc b/src/dev/net/i8254xGBe.cc
index d299dad..11f017a 100644
--- a/src/dev/net/i8254xGBe.cc
+++ b/src/dev/net/i8254xGBe.cc
@@ -1771,12 +1771,15 @@
         DPRINTF(EthernetDesc, "TSO: use: %d hdrlen: %d mss: %d total: %d "
             "used: %d loaded hdr: %d\n", useTso, tsoHeaderLen, tsoMss,
             tsoTotalLen, tsoUsedLen, tsoLoadedHeader);
+        pktPtr->simLength += tsoCopyBytes;
         pktPtr->length += tsoCopyBytes;
         tsoUsedLen += tsoCopyBytes;
         DPRINTF(EthernetDesc, "TSO: descBytesUsed: %d copyBytes: %d\n",
             tsoDescBytesUsed, tsoCopyBytes);
-    } else
+    } else {
+        pktPtr->simLength += TxdOp::getLen(desc);
         pktPtr->length += TxdOp::getLen(desc);
+    }
 
 
 
@@ -2519,7 +2522,7 @@
     bool txPktExists;
     UNSERIALIZE_SCALAR(txPktExists);
     if (txPktExists) {
-        txPacket = std::make_shared<EthPacketData>(16384);
+        txPacket = std::make_shared<EthPacketData>();
         txPacket->unserialize("txpacket", cp);
     }
 
diff --git a/src/dev/net/ns_gige.cc b/src/dev/net/ns_gige.cc
index 3bf0489..91a0da7 100644
--- a/src/dev/net/ns_gige.cc
+++ b/src/dev/net/ns_gige.cc
@@ -1738,6 +1738,7 @@
                     }
                 }
 
+                txPacket->simLength = txPacketBufPtr - txPacket->data;
                 txPacket->length = txPacketBufPtr - txPacket->data;
                 // this is just because the receive can't handle a
                 // packet bigger want to make sure
@@ -2186,6 +2187,7 @@
     bool txPacketExists = txPacket != nullptr;
     SERIALIZE_SCALAR(txPacketExists);
     if (txPacketExists) {
+        txPacket->simLength = txPacketBufPtr - txPacket->data;
         txPacket->length = txPacketBufPtr - txPacket->data;
         txPacket->serialize("txPacket", cp);
         uint32_t txPktBufPtr = (uint32_t) (txPacketBufPtr - txPacket->data);
@@ -2350,7 +2352,7 @@
     bool txPacketExists;
     UNSERIALIZE_SCALAR(txPacketExists);
     if (txPacketExists) {
-        txPacket = make_shared<EthPacketData>(16384);
+        txPacket = make_shared<EthPacketData>();
         txPacket->unserialize("txPacket", cp);
         uint32_t txPktBufPtr;
         UNSERIALIZE_SCALAR(txPktBufPtr);
@@ -2362,7 +2364,7 @@
     UNSERIALIZE_SCALAR(rxPacketExists);
     rxPacket = 0;
     if (rxPacketExists) {
-        rxPacket = make_shared<EthPacketData>(16384);
+        rxPacket = make_shared<EthPacketData>();
         rxPacket->unserialize("rxPacket", cp);
         uint32_t rxPktBufPtr;
         UNSERIALIZE_SCALAR(rxPktBufPtr);
diff --git a/src/dev/net/pktfifo.cc b/src/dev/net/pktfifo.cc
index af4dbf4..17aa54a 100644
--- a/src/dev/net/pktfifo.cc
+++ b/src/dev/net/pktfifo.cc
@@ -77,7 +77,7 @@
 void
 PacketFifoEntry::unserialize(const string &base, CheckpointIn &cp)
 {
-    packet = make_shared<EthPacketData>(16384);
+    packet = make_shared<EthPacketData>();
     packet->unserialize(base + ".packet", cp);
     paramIn(cp, base + ".slack", slack);
     paramIn(cp, base + ".number", number);
diff --git a/src/dev/net/sinic.cc b/src/dev/net/sinic.cc
index fc75c9e..de8d4e9 100644
--- a/src/dev/net/sinic.cc
+++ b/src/dev/net/sinic.cc
@@ -1085,6 +1085,7 @@
 
       case txCopyDone:
         vnic->TxDone = txDmaLen | Regs::TxDone_Complete;
+        txPacket->simLength += txDmaLen;
         txPacket->length += txDmaLen;
         if ((vnic->TxData & Regs::TxData_More)) {
             txPacketOffset += txDmaLen;
@@ -1495,7 +1496,7 @@
     UNSERIALIZE_SCALAR(txPacketExists);
     txPacket = 0;
     if (txPacketExists) {
-        txPacket = make_shared<EthPacketData>(16384);
+        txPacket = make_shared<EthPacketData>();
         txPacket->unserialize("txPacket", cp);
         UNSERIALIZE_SCALAR(txPacketOffset);
         UNSERIALIZE_SCALAR(txPacketBytes);
diff --git a/src/dev/net/tcp_iface.cc b/src/dev/net/tcp_iface.cc
index c9ca577..fba0696 100644
--- a/src/dev/net/tcp_iface.cc
+++ b/src/dev/net/tcp_iface.cc
@@ -329,6 +329,7 @@
     packet = make_shared<EthPacketData>(header.dataPacketLength);
     bool ret = recvTCP(sock, packet->data, header.dataPacketLength);
     panic_if(!ret, "Error while reading socket");
+    packet->simLength = header.simLength;
     packet->length = header.dataPacketLength;
 }