PacketFifo: Get slack out of the EthPacketData structure. This allows
a packet to exist in multiple FIFOs if desired.
This commit is contained in:
parent
163465ac08
commit
8042b8f4c7
5 changed files with 120 additions and 70 deletions
|
@ -40,7 +40,6 @@ void
|
|||
EthPacketData::serialize(const string &base, ostream &os)
|
||||
{
|
||||
paramOut(os, base + ".length", length);
|
||||
paramOut(os, base + ".slack", slack);
|
||||
arrayParamOut(os, base + ".data", data, length);
|
||||
}
|
||||
|
||||
|
@ -49,7 +48,6 @@ EthPacketData::unserialize(const string &base, Checkpoint *cp,
|
|||
const string §ion)
|
||||
{
|
||||
paramIn(cp, section, base + ".length", length);
|
||||
paramIn(cp, section, base + ".slack", slack);
|
||||
if (length)
|
||||
arrayParamIn(cp, section, base + ".data", data, length);
|
||||
}
|
||||
|
|
|
@ -60,24 +60,17 @@ class EthPacketData : public RefCounted
|
|||
*/
|
||||
int length;
|
||||
|
||||
/*
|
||||
* Extra space taken up by the packet in whatever data structure
|
||||
* it is in.
|
||||
*
|
||||
* NOTE: This can only be use by *one* data structure at a time!
|
||||
*/
|
||||
int slack;
|
||||
|
||||
public:
|
||||
EthPacketData() : data(NULL), length(0), slack(0)
|
||||
EthPacketData()
|
||||
: data(NULL), length(0)
|
||||
{ }
|
||||
|
||||
explicit EthPacketData(size_t size)
|
||||
: data(new uint8_t[size]), length(0), slack(0)
|
||||
: data(new uint8_t[size]), length(0)
|
||||
{ }
|
||||
|
||||
EthPacketData(std::auto_ptr<uint8_t> d, int l, int s = 0)
|
||||
: data(d.release()), length(l), slack(s)
|
||||
EthPacketData(std::auto_ptr<uint8_t> d, int l)
|
||||
: data(d.release()), length(l)
|
||||
{ }
|
||||
|
||||
~EthPacketData() { if (data) delete [] data; }
|
||||
|
|
|
@ -40,29 +40,50 @@ PacketFifo::copyout(void *dest, int offset, int len)
|
|||
if (offset + len >= size())
|
||||
return false;
|
||||
|
||||
list<EthPacketPtr>::iterator p = fifo.begin();
|
||||
list<EthPacketPtr>::iterator end = fifo.end();
|
||||
iterator i = fifo.begin();
|
||||
iterator end = fifo.end();
|
||||
while (len > 0) {
|
||||
while (offset >= (*p)->length) {
|
||||
offset -= (*p)->length;
|
||||
++p;
|
||||
EthPacketPtr &pkt = i->packet;
|
||||
while (offset >= pkt->length) {
|
||||
offset -= pkt->length;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (p == end)
|
||||
if (i == end)
|
||||
panic("invalid fifo");
|
||||
|
||||
int size = min((*p)->length - offset, len);
|
||||
memcpy(data, (*p)->data, size);
|
||||
int size = min(pkt->length - offset, len);
|
||||
memcpy(data, pkt->data, size);
|
||||
offset = 0;
|
||||
len -= size;
|
||||
data += size;
|
||||
++p;
|
||||
++i;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PacketFifoEntry::serialize(const string &base, ostream &os)
|
||||
{
|
||||
packet->serialize(base + ".packet", os);
|
||||
paramOut(os, base + ".slack", slack);
|
||||
paramOut(os, base + ".number", number);
|
||||
paramOut(os, base + ".priv", priv);
|
||||
}
|
||||
|
||||
void
|
||||
PacketFifoEntry::unserialize(const string &base, Checkpoint *cp,
|
||||
const string §ion)
|
||||
{
|
||||
packet = new EthPacketData(16384);
|
||||
packet->unserialize(base + ".packet", cp, section);
|
||||
paramIn(cp, section, base + ".slack", slack);
|
||||
paramIn(cp, section, base + ".number", number);
|
||||
paramIn(cp, section, base + ".priv", priv);
|
||||
}
|
||||
|
||||
void
|
||||
PacketFifo::serialize(const string &base, ostream &os)
|
||||
{
|
||||
|
@ -72,11 +93,11 @@ PacketFifo::serialize(const string &base, ostream &os)
|
|||
paramOut(os, base + ".packets", fifo.size());
|
||||
|
||||
int i = 0;
|
||||
list<EthPacketPtr>::iterator p = fifo.begin();
|
||||
list<EthPacketPtr>::iterator end = fifo.end();
|
||||
while (p != end) {
|
||||
(*p)->serialize(csprintf("%s.packet%d", base, i), os);
|
||||
++p;
|
||||
iterator entry = fifo.begin();
|
||||
iterator end = fifo.end();
|
||||
while (entry != end) {
|
||||
entry->serialize(csprintf("%s.entry%d", base, i), os);
|
||||
++entry;
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
@ -94,8 +115,8 @@ PacketFifo::unserialize(const string &base, Checkpoint *cp,
|
|||
fifo.clear();
|
||||
|
||||
for (int i = 0; i < fifosize; ++i) {
|
||||
EthPacketPtr p = new EthPacketData(16384);
|
||||
p->unserialize(csprintf("%s.packet%d", base, i), cp, section);
|
||||
fifo.push_back(p);
|
||||
PacketFifoEntry entry;
|
||||
entry.unserialize(csprintf("%s.entry%d", base, i), cp, section);
|
||||
fifo.push_back(entry);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,20 +39,59 @@
|
|||
#include "sim/serialize.hh"
|
||||
|
||||
class Checkpoint;
|
||||
|
||||
struct PacketFifoEntry
|
||||
{
|
||||
EthPacketPtr packet;
|
||||
uint64_t number;
|
||||
int slack;
|
||||
int priv;
|
||||
|
||||
PacketFifoEntry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
PacketFifoEntry(const PacketFifoEntry &s)
|
||||
: packet(s.packet), number(s.number), slack(s.slack), priv(s.priv)
|
||||
{
|
||||
}
|
||||
|
||||
PacketFifoEntry(EthPacketPtr p, uint64_t n)
|
||||
: packet(p), number(n), slack(0), priv(-1)
|
||||
{
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
packet = NULL;
|
||||
number = 0;
|
||||
slack = 0;
|
||||
priv = -1;
|
||||
}
|
||||
|
||||
void serialize(const std::string &base, std::ostream &os);
|
||||
void unserialize(const std::string &base, Checkpoint *cp,
|
||||
const std::string §ion);
|
||||
};
|
||||
|
||||
class PacketFifo
|
||||
{
|
||||
public:
|
||||
typedef std::list<EthPacketPtr> fifo_list;
|
||||
|
||||
typedef std::list<PacketFifoEntry> fifo_list;
|
||||
typedef fifo_list::iterator iterator;
|
||||
|
||||
protected:
|
||||
std::list<EthPacketPtr> fifo;
|
||||
std::list<PacketFifoEntry> fifo;
|
||||
uint64_t _counter;
|
||||
int _maxsize;
|
||||
int _size;
|
||||
int _reserved;
|
||||
|
||||
public:
|
||||
explicit PacketFifo(int max) : _maxsize(max), _size(0), _reserved(0) {}
|
||||
explicit PacketFifo(int max)
|
||||
: _counter(0), _maxsize(max), _size(0), _reserved(0) {}
|
||||
virtual ~PacketFifo() {}
|
||||
|
||||
int packets() const { return fifo.size(); }
|
||||
|
@ -73,18 +112,21 @@ class PacketFifo
|
|||
iterator begin() { return fifo.begin(); }
|
||||
iterator end() { return fifo.end(); }
|
||||
|
||||
EthPacketPtr front() { return fifo.front(); }
|
||||
EthPacketPtr front() { return fifo.begin()->packet; }
|
||||
|
||||
bool push(EthPacketPtr ptr)
|
||||
{
|
||||
assert(ptr->length);
|
||||
assert(_reserved <= ptr->length);
|
||||
assert(ptr->slack == 0);
|
||||
if (avail() < ptr->length - _reserved)
|
||||
return false;
|
||||
|
||||
_size += ptr->length;
|
||||
fifo.push_back(ptr);
|
||||
|
||||
PacketFifoEntry entry;
|
||||
entry.packet = ptr;
|
||||
entry.number = _counter++;
|
||||
fifo.push_back(entry);
|
||||
_reserved = 0;
|
||||
return true;
|
||||
}
|
||||
|
@ -94,18 +136,17 @@ class PacketFifo
|
|||
if (empty())
|
||||
return;
|
||||
|
||||
EthPacketPtr &packet = fifo.front();
|
||||
_size -= packet->length;
|
||||
_size -= packet->slack;
|
||||
packet->slack = 0;
|
||||
packet = NULL;
|
||||
iterator entry = fifo.begin();
|
||||
_size -= entry->packet->length;
|
||||
_size -= entry->slack;
|
||||
entry->packet = NULL;
|
||||
fifo.pop_front();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
for (iterator i = begin(); i != end(); ++i)
|
||||
(*i)->slack = 0;
|
||||
i->clear();
|
||||
fifo.clear();
|
||||
_size = 0;
|
||||
_reserved = 0;
|
||||
|
@ -113,50 +154,47 @@ class PacketFifo
|
|||
|
||||
void remove(iterator i)
|
||||
{
|
||||
EthPacketPtr &packet = *i;
|
||||
if (i != fifo.begin()) {
|
||||
iterator prev = i;
|
||||
--prev;
|
||||
assert(prev != fifo.end());
|
||||
(*prev)->slack += packet->length;
|
||||
prev->slack += i->packet->length;
|
||||
prev->slack += i->slack;
|
||||
} else {
|
||||
_size -= packet->length;
|
||||
_size -= packet->slack;
|
||||
_size -= i->packet->length;
|
||||
_size -= i->slack;
|
||||
}
|
||||
|
||||
packet->slack = 0;
|
||||
packet = NULL;
|
||||
i->clear();
|
||||
fifo.erase(i);
|
||||
}
|
||||
|
||||
bool copyout(void *dest, int offset, int len);
|
||||
|
||||
int countPacketsBefore(iterator end)
|
||||
int countPacketsBefore(iterator i)
|
||||
{
|
||||
iterator i = fifo.begin();
|
||||
int count = 0;
|
||||
|
||||
while (i != end) {
|
||||
++count;
|
||||
++i;
|
||||
}
|
||||
|
||||
return count;
|
||||
if (i == fifo.end())
|
||||
return 0;
|
||||
return i->number - fifo.begin()->number;
|
||||
}
|
||||
|
||||
int countPacketsAfter(iterator i)
|
||||
{
|
||||
iterator end = fifo.end();
|
||||
int count = 0;
|
||||
|
||||
while (i != end) {
|
||||
++count;
|
||||
++i;
|
||||
}
|
||||
|
||||
return count;
|
||||
if (i == end)
|
||||
return 0;
|
||||
return (--end)->number - i->number;
|
||||
}
|
||||
|
||||
void check()
|
||||
{
|
||||
int total = 0;
|
||||
for (iterator i = begin(); i != end(); ++i)
|
||||
total += i->packet->length + i->slack;
|
||||
|
||||
if (total != _size)
|
||||
panic("total (%d) is not == to size (%d)\n", total, _size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialization stuff
|
||||
|
|
|
@ -893,12 +893,12 @@ Device::rxKick()
|
|||
// Grab a new packet from the fifo.
|
||||
vnic->rxPacket = rxFifoPtr++;
|
||||
vnic->rxPacketOffset = 0;
|
||||
vnic->rxPacketBytes = (*vnic->rxPacket)->length;
|
||||
vnic->rxPacketBytes = vnic->rxPacket->packet->length;
|
||||
assert(vnic->rxPacketBytes);
|
||||
|
||||
vnic->rxDoneData = 0;
|
||||
/* scope for variables */ {
|
||||
IpPtr ip(*vnic->rxPacket);
|
||||
IpPtr ip(vnic->rxPacket->packet);
|
||||
if (ip) {
|
||||
DPRINTF(Ethernet, "ID is %d\n", ip->id());
|
||||
vnic->rxDoneData |= Regs::RxDone_IpPacket;
|
||||
|
@ -941,7 +941,7 @@ Device::rxKick()
|
|||
Regs::get_RxData_Addr(vnic->RxData));
|
||||
rxDmaLen = std::min<int>(Regs::get_RxData_Len(vnic->RxData),
|
||||
vnic->rxPacketBytes);
|
||||
rxDmaData = (*vnic->rxPacket)->data + vnic->rxPacketOffset;
|
||||
rxDmaData = vnic->rxPacket->packet->data + vnic->rxPacketOffset;
|
||||
rxState = rxCopy;
|
||||
if (rxDmaAddr == 1LL) {
|
||||
rxState = rxCopyDone;
|
||||
|
|
Loading…
Reference in a new issue