diff --git a/dev/etherpkt.cc b/dev/etherpkt.cc index 5dee7dc0d..44dbd7c18 100644 --- a/dev/etherpkt.cc +++ b/dev/etherpkt.cc @@ -38,6 +38,7 @@ void PacketData::serialize(const string &base, ostream &os) { paramOut(os, base + ".length", length); + paramOut(os, base + ".slack", slack); arrayParamOut(os, base + ".data", data, length); } @@ -46,6 +47,7 @@ PacketData::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); } diff --git a/dev/etherpkt.hh b/dev/etherpkt.hh index 82d22bfad..cb9022d72 100644 --- a/dev/etherpkt.hh +++ b/dev/etherpkt.hh @@ -47,14 +47,30 @@ class Checkpoint; class PacketData : public RefCounted { public: + /* + * Pointer to packet data will be deleted + */ uint8_t *data; + + /* + * Length of the current packet + */ 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: - PacketData() : data(NULL), length(0) { } - explicit PacketData(size_t size) : data(new uint8_t[size]), length(0) { } - PacketData(std::auto_ptr d, int l) - : data(d.release()), length(l) { } + PacketData() : data(NULL), length(0), slack(0) { } + explicit PacketData(size_t size) + : data(new uint8_t[size]), length(0), slack(0) { } + PacketData(std::auto_ptr d, int l, int s = 0) + : data(d.release()), length(l), slack(s) { } ~PacketData() { if (data) delete [] data; } public: diff --git a/dev/pktfifo.hh b/dev/pktfifo.hh index a8b626618..61e4ead1b 100644 --- a/dev/pktfifo.hh +++ b/dev/pktfifo.hh @@ -39,6 +39,10 @@ class Checkpoint; class PacketFifo { + public: + typedef std::list fifo_list; + typedef fifo_list::iterator iterator; + protected: std::list fifo; int _maxsize; @@ -64,9 +68,16 @@ class PacketFifo return _reserved; } + iterator begin() { return fifo.begin(); } + iterator end() { return fifo.end(); } + + PacketPtr front() { return fifo.front(); } + bool push(PacketPtr ptr) { + assert(ptr->length); assert(_reserved <= ptr->length); + assert(ptr->slack == 0); if (avail() < ptr->length - _reserved) return false; @@ -76,25 +87,44 @@ class PacketFifo return true; } - PacketPtr front() { return fifo.front(); } - void pop() { if (empty()) return; - _size -= fifo.front()->length; - fifo.front() = NULL; + PacketPtr &packet = fifo.front(); + _size -= packet->length; + _size -= packet->slack; + packet->slack = 0; + packet = NULL; fifo.pop_front(); } void clear() { + for (iterator i = begin(); i != end(); ++i) + (*i)->slack = 0; fifo.clear(); _size = 0; _reserved = 0; } + void remove(iterator i) + { + PacketPtr &packet = *i; + if (i != fifo.begin()) { + --i; + (*i)->slack += packet->length; + } else { + _size -= packet->length; + _size -= packet->slack; + } + + packet->slack = 0; + packet = NULL; + fifo.erase(i); + } + /** * Serialization stuff */