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.
This commit is contained in:
mlebeane 2016-10-26 22:48:33 -04:00
parent de72e36619
commit 96905971f2
14 changed files with 53 additions and 28 deletions

View file

@ -197,7 +197,7 @@ DistEtherLink::TxLink::transmit(EthPacketPtr pkt)
}
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 @@ DistEtherLink::Link::unserialize(CheckpointIn &cp)
bool packet_exists;
UNSERIALIZE_SCALAR(packet_exists);
if (packet_exists) {
packet = make_shared<EthPacketData>(16384);
packet = make_shared<EthPacketData>();
packet->unserialize("packet", cp);
}

View file

@ -407,7 +407,7 @@ DistIface::RecvScheduler::resumeRecvTicks()
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 @@ DistIface::RecvScheduler::Desc::unserialize(CheckpointIn &cp)
{
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 @@ DistIface::packetOut(EthPacketPtr pkt, Tick send_delay)
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

View file

@ -86,6 +86,11 @@ class DistHeaderPkt
*/
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 @@ class DistHeaderPkt
union {
/**
* Actual length of the simulated Ethernet packet.
* (from EthPacketData::length).
*/
unsigned dataPacketLength;
struct {

View file

@ -98,7 +98,7 @@ EtherBus::send(EtherInt *sndr, EthPacketPtr &pkt)
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);

View file

@ -192,7 +192,7 @@ EtherLink::Link::transmit(EthPacketPtr pkt)
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 @@ EtherLink::Link::unserialize(const string &base, CheckpointIn &cp)
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 @@ EtherLink::Link::unserialize(const string &base, CheckpointIn &cp)
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(

View file

@ -41,6 +41,7 @@ using namespace std;
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 @@ void
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;
}

View file

@ -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;

View file

@ -200,7 +200,7 @@ EtherSwitch::Interface::transmit()
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);

View file

@ -239,6 +239,7 @@ EtherTap::process(int revent)
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));

View file

@ -1771,12 +1771,15 @@ IGbE::TxDescCache::pktComplete()
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 @@ IGbE::unserialize(CheckpointIn &cp)
bool txPktExists;
UNSERIALIZE_SCALAR(txPktExists);
if (txPktExists) {
txPacket = std::make_shared<EthPacketData>(16384);
txPacket = std::make_shared<EthPacketData>();
txPacket->unserialize("txpacket", cp);
}

View file

@ -1738,6 +1738,7 @@ NSGigE::txKick()
}
}
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 @@ NSGigE::serialize(CheckpointOut &cp) const
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 @@ NSGigE::unserialize(CheckpointIn &cp)
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 @@ NSGigE::unserialize(CheckpointIn &cp)
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);

View file

@ -77,7 +77,7 @@ PacketFifoEntry::serialize(const string &base, CheckpointOut &cp) const
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);

View file

@ -1085,6 +1085,7 @@ Device::txKick()
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 @@ Device::unserialize(CheckpointIn &cp)
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);

View file

@ -329,6 +329,7 @@ TCPIface::recvPacket(const Header &header, EthPacketPtr &packet)
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;
}