--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/mtag-list.cc Thu Apr 24 14:52:59 2008 -0700
@@ -0,0 +1,237 @@
+#include "mtag-list.h"
+
+namespace ns3 {
+
+MtagList::Iterator::Item::Item (MtagBuffer buf_)
+ : buf (buf_)
+{}
+
+bool
+MtagList::Iterator::HasNext (void) const
+{
+ return m_current < m_end;
+}
+struct MtagList::Iterator::Item
+MtagList::Iterator::Next (void)
+{
+ NS_ASSERT (HasNext ());
+ struct Item item = Item (MtagBuffer (m_current, m_end));
+ item.tid.SetUid (item.buf.ReadU32 ());
+ item.size = item.buf.ReadU32 ();
+ item.start = item.buf.ReadU32 ();
+ item.end = item.buf.ReadU32 ();
+ item.start = std::max (item.start, m_offsetStart);
+ item.end = std::min (item.end, m_offsetEnd);
+ m_current += 4 + 4 + 4 + 4 + item.size;
+ item.buf.TrimAtEnd (m_end - m_current);
+ PrepareForNext ();
+ return item;
+}
+void
+MtagList::Iterator::PrepareForNext (void)
+{
+ while (m_current < m_end)
+ {
+ struct Item item = Item (MtagBuffer (m_current, m_end));
+ item.tid.SetUid (item.buf.ReadU32 ());
+ item.size = item.buf.ReadU32 ();
+ item.start = item.buf.ReadU32 ();
+ item.end = item.buf.ReadU32 ();
+ if (item.start > m_offsetEnd || item.end < m_offsetStart)
+ {
+ m_current += 4 + 4 + 4 + 4 + item.size;
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+MtagList::Iterator::Iterator (uint8_t *start, uint8_t *end, uint32_t offsetStart, uint32_t offsetEnd)
+ : m_current (start),
+ m_end (end),
+ m_offsetStart (offsetStart),
+ m_offsetEnd (offsetEnd)
+{
+ PrepareForNext ();
+}
+
+uint32_t
+MtagList::Iterator::GetOffsetStart (void) const
+{
+ return m_offsetStart;
+}
+
+
+MtagList::MtagList ()
+ : m_buffer (0),
+ m_size (0)
+{}
+MtagList::MtagList (const MtagList &o)
+ : m_size (o.m_size)
+{
+ m_buffer = new uint8_t [o.m_size] ();
+ memcpy (m_buffer, o.m_buffer, o.m_size);
+}
+MtagList &
+MtagList::operator = (const MtagList &o)
+{
+ delete [] m_buffer;
+ m_buffer = new uint8_t [o.m_size] ();
+ memcpy (m_buffer, o.m_buffer, m_size);
+ m_size = o.m_size;
+ return *this;
+}
+MtagList::~MtagList ()
+{
+ delete [] m_buffer;
+ m_buffer = 0;
+ m_size = 0;
+}
+
+MtagBuffer
+MtagList::Add (TypeId tid, uint32_t bufferSize, uint32_t start, uint32_t end)
+{
+ uint32_t newSize = m_size + bufferSize + 4 + 4 + 4 + 4;
+ uint8_t *newBuffer = new uint8_t [newSize] ();
+ memcpy (newBuffer, m_buffer, m_size);
+ MtagBuffer tag = MtagBuffer (newBuffer + m_size, newBuffer + newSize);
+ tag.WriteU32 (tid.GetUid ());
+ tag.WriteU32 (bufferSize);
+ tag.WriteU32 (start);
+ tag.WriteU32 (end);
+ delete [] m_buffer;
+ m_buffer = newBuffer;
+ m_size = newSize;
+ return tag;
+}
+
+void
+MtagList::Add (const MtagList &o)
+{
+ MtagList::Iterator i = o.Begin (0, 0xffffffff);
+ while (i.HasNext ())
+ {
+ MtagList::Iterator::Item item = i.Next ();
+ MtagBuffer buf = Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+}
+
+void
+MtagList::Remove (const Iterator &i)
+{
+ // XXX: more complex to implement.
+}
+
+void
+MtagList::RemoveAll (void)
+{
+ delete [] m_buffer;
+ m_buffer = 0;
+ m_size = 0;
+}
+
+MtagList::Iterator
+MtagList::Begin (uint32_t offsetStart, uint32_t offsetEnd) const
+{
+ return Iterator (m_buffer, m_buffer + m_size, offsetStart, offsetEnd);
+}
+
+bool
+MtagList::IsDirtyAtEnd (uint32_t appendOffset)
+{
+ MtagList::Iterator i = Begin (0, 0xffffffff);
+ while (i.HasNext ())
+ {
+ MtagList::Iterator::Item item = i.Next ();
+ if (item.end > appendOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+MtagList::IsDirtyAtStart (uint32_t prependOffset)
+{
+ MtagList::Iterator i = Begin (0, 0xffffffff);
+ while (i.HasNext ())
+ {
+ MtagList::Iterator::Item item = i.Next ();
+ if (item.start < prependOffset)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void
+MtagList::AddAtEnd (int32_t adjustment, uint32_t appendOffset)
+{
+ if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
+ {
+ return;
+ }
+ MtagList list;
+ MtagList::Iterator i = Begin (0, 0xffffffff);
+ while (i.HasNext ())
+ {
+ MtagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.start > appendOffset)
+ {
+ continue;
+ }
+ else if (item.start < appendOffset && item.end > appendOffset)
+ {
+ item.end = appendOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ MtagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+void
+MtagList::AddAtStart (int32_t adjustment, uint32_t prependOffset)
+{
+ if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
+ {
+ return;
+ }
+ MtagList list;
+ MtagList::Iterator i = Begin (0, 0xffffffff);
+ while (i.HasNext ())
+ {
+ MtagList::Iterator::Item item = i.Next ();
+ item.start += adjustment;
+ item.end += adjustment;
+
+ if (item.end < prependOffset)
+ {
+ continue;
+ }
+ else if (item.end > prependOffset && item.start < prependOffset)
+ {
+ item.start = prependOffset;
+ }
+ else
+ {
+ // nothing to do.
+ }
+ MtagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
+ buf.CopyFrom (item.buf);
+ }
+ *this = list;
+}
+
+} // namespace ns3
--- a/src/common/packet.cc Wed Apr 23 15:01:27 2008 -0700
+++ b/src/common/packet.cc Thu Apr 24 14:52:59 2008 -0700
@@ -24,6 +24,59 @@
uint32_t Packet::m_globalUid = 0;
+TypeId
+TagIterator::Item::GetTypeId (void) const
+{
+ return m_tid;
+}
+uint32_t
+TagIterator::Item::GetStart (void) const
+{
+ return m_start;
+}
+uint32_t
+TagIterator::Item::GetEnd (void) const
+{
+ return m_end;
+}
+void
+TagIterator::Item::GetTag (Mtag &tag) const
+{
+ if (tag.GetInstanceTypeId () != GetTypeId ())
+ {
+ NS_FATAL_ERROR ("The tag you provided is not of the right type.");
+ }
+ tag.Deserialize (m_buffer);
+}
+TagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, MtagBuffer buffer)
+ : m_tid (tid),
+ m_start (start),
+ m_end (end),
+ m_buffer (buffer)
+{}
+bool
+TagIterator::HasNext (void) const
+{
+ return m_current.HasNext ();
+}
+TagIterator::Item
+TagIterator::Next (void)
+{
+ MtagList::Iterator::Item i = m_current.Next ();
+
+ TagIterator::Item item = TagIterator::Item (i.tid,
+ i.start-m_current.GetOffsetStart (),
+ i.end-m_current.GetOffsetStart (),
+ i.buf);
+
+
+ return item;
+}
+TagIterator::TagIterator (MtagList::Iterator i)
+ : m_current (i)
+{}
+
+
void
Packet::Ref (void) const
{
@@ -51,6 +104,7 @@
Packet::Packet ()
: m_buffer (),
m_tags (),
+ m_tagList (),
m_metadata (m_globalUid, 0),
m_refCount (1)
{
@@ -60,6 +114,7 @@
Packet::Packet (const Packet &o)
: m_buffer (o.m_buffer),
m_tags (o.m_tags),
+ m_tagList (o.m_tagList),
m_metadata (o.m_metadata),
m_refCount (1)
{}
@@ -73,6 +128,7 @@
}
m_buffer = o.m_buffer;
m_tags = o.m_tags;
+ m_tagList = o.m_tagList;
m_metadata = o.m_metadata;
return *this;
}
@@ -80,6 +136,7 @@
Packet::Packet (uint32_t size)
: m_buffer (size),
m_tags (),
+ m_tagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -88,6 +145,7 @@
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
m_tags (),
+ m_tagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
{
@@ -97,9 +155,10 @@
i.Write (buffer, size);
}
-Packet::Packet (Buffer buffer, Tags tags, PacketMetadata metadata)
+Packet::Packet (const Buffer &buffer, const Tags &tags, const MtagList &tagList, const PacketMetadata &metadata)
: m_buffer (buffer),
m_tags (tags),
+ m_tagList (tagList),
m_metadata (metadata),
m_refCount (1)
{}
@@ -113,7 +172,7 @@
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
// again, call the constructor directly rather than
// through Create because it is private.
- return Ptr<Packet> (new Packet (buffer, m_tags, metadata), false);
+ return Ptr<Packet> (new Packet (buffer, m_tags, m_tagList, metadata), false);
}
uint32_t
@@ -126,7 +185,13 @@
Packet::AddHeader (const Header &header)
{
uint32_t size = header.GetSerializedSize ();
- m_buffer.AddAtStart (size);
+ uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
+ bool resized = m_buffer.AddAtStart (size);
+ if (resized)
+ {
+ m_tagList.AddAtStart (m_buffer.GetCurrentStartOffset () - orgStart,
+ m_buffer.GetCurrentStartOffset () + size);
+ }
header.Serialize (m_buffer.Begin ());
m_metadata.AddHeader (header, size);
}
@@ -142,7 +207,13 @@
Packet::AddTrailer (const Trailer &trailer)
{
uint32_t size = trailer.GetSerializedSize ();
- m_buffer.AddAtEnd (size);
+ uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
+ bool resized = m_buffer.AddAtEnd (size);
+ if (resized)
+ {
+ m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+ m_buffer.GetCurrentEndOffset () - size);
+ }
Buffer::Iterator end = m_buffer.End ();
trailer.Serialize (end);
m_metadata.AddTrailer (trailer, size);
@@ -159,17 +230,28 @@
void
Packet::AddAtEnd (Ptr<const Packet> packet)
{
+ uint32_t aStart = m_buffer.GetCurrentStartOffset ();
+ uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
m_buffer.AddAtEnd (packet->m_buffer);
- /**
- * XXX: we might need to merge the tag list of the
- * other packet into the current packet.
- */
+ uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
+ m_tagList.AddAtEnd (m_buffer.GetCurrentStartOffset () - aStart,
+ appendPrependOffset);
+ MtagList copy = packet->m_tagList;
+ copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
+ appendPrependOffset);
+ m_tagList.Add (copy);
m_metadata.AddAtEnd (packet->m_metadata);
}
void
Packet::AddPaddingAtEnd (uint32_t size)
{
- m_buffer.AddAtEnd (size);
+ uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
+ bool resized = m_buffer.AddAtEnd (size);
+ if (resized)
+ {
+ m_tagList.AddAtEnd (m_buffer.GetCurrentEndOffset () - orgEnd,
+ m_buffer.GetCurrentEndOffset () - size);
+ }
m_metadata.AddPaddingAtEnd (size);
}
void
@@ -189,6 +271,7 @@
Packet::RemoveAllTags (void)
{
m_tags.RemoveAll ();
+ m_tagList.RemoveAll ();
}
uint8_t const *
@@ -207,6 +290,7 @@
Packet::PrintTags (std::ostream &os) const
{
m_tags.Print (os, " ");
+ // XXX: tagList.
}
void
@@ -388,6 +472,38 @@
buffer.RemoveAtStart (metadataDeserialized);
}
+void
+Packet::AddMtag (const Mtag &tag) const
+{
+ MtagList *list = const_cast<MtagList *> (&m_tagList);
+ MtagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
+ m_buffer.GetCurrentStartOffset (),
+ m_buffer.GetCurrentEndOffset ());
+ tag.Serialize (buffer);
+}
+TagIterator
+Packet::GetTagIterator (void) const
+{
+ return TagIterator (m_tagList.Begin (m_buffer.GetCurrentStartOffset (), m_buffer.GetCurrentEndOffset ()));
+}
+
+bool
+Packet::FindFirstMatchingTag (Mtag &tag) const
+{
+ TypeId tid = tag.GetInstanceTypeId ();
+ TagIterator i = GetTagIterator ();
+ while (i.HasNext ())
+ {
+ TagIterator::Item item = i.Next ();
+ if (tid == item.GetTypeId ())
+ {
+ item.GetTag (tag);
+ return true;
+ }
+ }
+ return false;
+}
+
std::ostream& operator<< (std::ostream& os, const Packet &packet)
{
packet.Print (os);
@@ -403,24 +519,136 @@
#include "ns3/test.h"
#include <string>
+#include <stdarg.h>
+
+using namespace ns3;
+
+namespace {
+
+class ATestTagBase : public Mtag
+{
+public:
+ ATestTagBase () : m_error (false) {}
+ bool m_error;
+};
+
+template <int N>
+class ATestTag : public ATestTagBase
+{
+public:
+ static TypeId GetTypeId (void) {
+ std::ostringstream oss;
+ oss << "anon::ATestTag<" << N << ">";
+ static TypeId tid = TypeId (oss.str ().c_str ())
+ .SetParent<Mtag> ()
+ .AddConstructor<ATestTag<N> > ()
+ .HideFromDocumentation ()
+ ;
+ return tid;
+ }
+ virtual TypeId GetInstanceTypeId (void) const {
+ return GetTypeId ();
+ }
+ virtual uint32_t GetSerializedSize (void) const {
+ return N;
+ }
+ virtual void Serialize (MtagBuffer buf) const {
+ for (uint32_t i = 0; i < N; ++i)
+ {
+ buf.WriteU8 (N);
+ }
+ }
+ virtual void Deserialize (MtagBuffer buf) {
+ for (uint32_t i = 0; i < N; ++i)
+ {
+ uint8_t v = buf.ReadU8 ();
+ if (v != N)
+ {
+ m_error = true;
+ }
+ }
+ }
+ ATestTag ()
+ : ATestTagBase () {}
+};
+
+struct Expected
+{
+ Expected (uint32_t n_, uint32_t start_, uint32_t end_)
+ : n (n_), start (start_), end (end_) {}
+
+ uint32_t n;
+ uint32_t start;
+ uint32_t end;
+};
+
+}
+
+#define E(a,b,c) a,b,c
+
+#define CHECK(p, n, ...) \
+ if (!DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)) \
+ { \
+ result = false; \
+ }
namespace ns3 {
-class PacketTest: public Test {
+
+class PacketTest: public Test
+{
public:
+ PacketTest ();
virtual bool RunTests (void);
- PacketTest ();
+private:
+ bool DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
};
PacketTest::PacketTest ()
: Test ("Packet") {}
+bool
+PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
+{
+ bool result = true;
+ std::vector<struct Expected> expected;
+ va_list ap;
+ va_start (ap, n);
+ for (uint32_t k = 0; k < n; ++k)
+ {
+ uint32_t N = va_arg (ap, uint32_t);
+ uint32_t start = va_arg (ap, uint32_t);
+ uint32_t end = va_arg (ap, uint32_t);
+ expected.push_back (Expected (N, start, end));
+ }
+ va_end (ap);
+
+ TagIterator i = p->GetTagIterator ();
+ uint32_t j = 0;
+ while (i.HasNext () && j < expected.size ())
+ {
+ TagIterator::Item item = i.Next ();
+ struct Expected e = expected[j];
+ std::ostringstream oss;
+ oss << "anon::ATestTag<" << e.n << ">";
+ NS_TEST_ASSERT_EQUAL_FILELINE (item.GetTypeId ().GetName (), oss.str (), file, line);
+ NS_TEST_ASSERT_EQUAL_FILELINE (item.GetStart (), e.start, file, line);
+ NS_TEST_ASSERT_EQUAL_FILELINE (item.GetEnd (), e.end, file, line);
+ ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
+ NS_TEST_ASSERT (tag != 0);
+ item.GetTag (*tag);
+ NS_TEST_ASSERT (!tag->m_error);
+ delete tag;
+ j++;
+ }
+ return result;
+}
bool
PacketTest::RunTests (void)
{
- bool ok = true;
+ bool result = true;
Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
@@ -428,25 +656,49 @@
packet->AddAtEnd (pkt1);
packet->AddAtEnd (pkt2);
- if (packet->GetSize () != 11)
- {
- Failure () << "expected size 11, got " << packet->GetSize () << std::endl;
- ok = false;
- }
+ NS_TEST_ASSERT_EQUAL (packet->GetSize (), 11);
std::string msg = std::string (reinterpret_cast<const char *>(packet->PeekData ()),
packet->GetSize ());
- if (msg != "hello world")
- {
- Failure () << "expected 'hello world', got '" << msg << "'" << std::endl;
- ok = false;
- }
+ NS_TEST_ASSERT_EQUAL (msg, "hello world");
+
+
+ Ptr<const Packet> p = Create<Packet> (1000);
+
+ p->AddMtag (ATestTag<1> ());
+ CHECK (p, 1, E (1, 0, 1000));
+ Ptr<const Packet> copy = p->Copy ();
+ CHECK (copy, 1, E (1, 0, 1000));
+
+ p->AddMtag (ATestTag<2> ());
+ CHECK (p, 2, E (1, 0, 1000), E(2, 0, 1000));
+ CHECK (copy, 1, E (1, 0, 1000));
- return ok;
+ Ptr<Packet> frag0 = p->CreateFragment (0, 10);
+ Ptr<Packet> frag1 = p->CreateFragment (10, 90);
+ Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
+ frag0->AddMtag (ATestTag<3> ());
+ CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
+ frag1->AddMtag (ATestTag<4> ());
+ CHECK (frag1, 3, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90));
+ frag2->AddMtag (ATestTag<5> ());
+ CHECK (frag2, 3, E (1, 0, 900), E(2, 0, 900), E (5, 0, 900));
+
+ frag1->AddAtEnd (frag2);
+ CHECK (frag1, 6, E (1, 0, 90), E(2, 0, 90), E (4, 0, 90), E (1, 90, 990), E(2, 90, 990), E (5, 90, 990));
+
+ CHECK (frag0, 3, E (1, 0, 10), E(2, 0, 10), E (3, 0, 10));
+ frag0->AddAtEnd (frag1);
+ CHECK (frag0, 9,
+ E (1, 0, 10), E(2, 0, 10), E (3, 0, 10),
+ E (1, 10, 100), E(2, 10, 100), E (4, 10, 100),
+ E (1, 100, 1000), E(2, 100, 1000), E (5, 100, 1000));
+
+ return result;
}
-static PacketTest gPacketTest;
+static PacketTest g_packetTest;
}; // namespace ns3