network: (merges !413) Add serialization for byte and packet tags
This commit is contained in:
committed by
Tom Henderson
parent
eeadfbb182
commit
df89d8fafd
@@ -339,10 +339,6 @@ behavior of packet tags and byte tags.
|
||||
from the packet. Removing one of possibly multiple byte tags is not supported
|
||||
by the current API.
|
||||
|
||||
As of *ns-3.5* and later, Tags are not serialized and deserialized to a buffer when
|
||||
``Packet::Serialize ()`` and ``Packet::Deserialize ()`` are called; this is an
|
||||
open bug.
|
||||
|
||||
If a user wants to take an existing packet object and reuse it as a new packet,
|
||||
he or she should remove all byte tags and packet tags before doing so. An
|
||||
example is the UdpEchoServer class, which takes the received packet and "turns
|
||||
|
||||
@@ -424,5 +424,179 @@ ByteTagList::Deallocate (struct ByteTagListData *data)
|
||||
|
||||
#endif /* USE_FREE_LIST */
|
||||
|
||||
uint32_t
|
||||
ByteTagList::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
uint32_t size = 0;
|
||||
|
||||
// Number of tags in list
|
||||
size += 4; // numberOfTags
|
||||
|
||||
ByteTagList::Iterator i = BeginAll ();
|
||||
while (i.HasNext ())
|
||||
{
|
||||
ByteTagList::Iterator::Item item = i.Next ();
|
||||
|
||||
// TypeId hash; ensure size is multiple of 4 bytes
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
size += hashSize;
|
||||
|
||||
size += 3 * 4; // size, start, end
|
||||
|
||||
// tag data; ensure size is multiple of 4 bytes
|
||||
uint32_t tagWordSize = (item.size+3) & (~3);
|
||||
size += tagWordSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ByteTagList::Serialize (uint32_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << buffer << maxSize);
|
||||
|
||||
uint32_t* p = buffer;
|
||||
uint32_t size = 0;
|
||||
|
||||
uint32_t* numberOfTags = 0;
|
||||
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
numberOfTags = p;
|
||||
*p++ = 0;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ByteTagList::Iterator i = BeginAll ();
|
||||
while (i.HasNext ())
|
||||
{
|
||||
ByteTagList::Iterator::Item item = i.Next ();
|
||||
|
||||
NS_LOG_INFO ("Serializing " << item.tid);
|
||||
|
||||
// ensure size is multiple of 4 bytes for 4 byte boundaries
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
if (size + hashSize <= maxSize)
|
||||
{
|
||||
TypeId::hash_t tid = item.tid.GetHash ();
|
||||
memcpy (p, &tid, sizeof (TypeId::hash_t));
|
||||
p += hashSize / 4;
|
||||
size += hashSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
*p++ = item.size;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
*p++ = item.start;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
*p++ = item.end;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ensure size is multiple of 4 bytes for 4 byte boundaries
|
||||
uint32_t tagWordSize = (item.size+3) & (~3);
|
||||
|
||||
if (size + tagWordSize <= maxSize)
|
||||
{
|
||||
item.buf.Read (reinterpret_cast<uint8_t *> (p), item.size);
|
||||
size += tagWordSize;
|
||||
p += tagWordSize / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*numberOfTags)++;
|
||||
}
|
||||
|
||||
// Serialized successfully
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ByteTagList::Deserialize (const uint32_t* buffer, uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << buffer << size);
|
||||
const uint32_t* p = buffer;
|
||||
uint32_t sizeCheck = size - 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t numberTagData = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_LOG_INFO ("Deserializing number of tags " << numberTagData);
|
||||
|
||||
for(uint32_t i = 0; i < numberTagData; ++i)
|
||||
{
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
NS_ASSERT (sizeCheck >= hashSize);
|
||||
TypeId::hash_t hash;
|
||||
memcpy (&hash, p, sizeof (TypeId::hash_t));
|
||||
p += hashSize / 4;
|
||||
sizeCheck -= hashSize;
|
||||
|
||||
TypeId tid = TypeId::LookupByHash (hash);
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t bufferSize = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t start = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t end = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= bufferSize);
|
||||
TagBuffer buf = Add (tid, bufferSize, start, end);
|
||||
buf.Write ( reinterpret_cast<const uint8_t *> (p), bufferSize);
|
||||
|
||||
// ensure 4 byte boundary
|
||||
uint32_t tagSizeBytes = (bufferSize+3) & (~3);
|
||||
sizeCheck -= tagSizeBytes;
|
||||
p += tagSizeBytes / 4;
|
||||
}
|
||||
|
||||
NS_ASSERT (sizeCheck == 0);
|
||||
|
||||
// return zero if buffer did not
|
||||
// contain a complete message
|
||||
return (sizeCheck != 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
@@ -230,6 +230,30 @@ private:
|
||||
*
|
||||
*/
|
||||
void AddAtStart (int32_t prependOffset);
|
||||
/**
|
||||
* Returns number of bytes required for packet serialization.
|
||||
*
|
||||
* \returns number of bytes required for packet serialization
|
||||
*/
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
/**
|
||||
* Serialize the tag list into a byte buffer.
|
||||
*
|
||||
* \param [in,out] buffer The byte buffer to which the tag list will be serialized
|
||||
* \param [in] maxSize Max The max size of the buffer for bounds checking
|
||||
*
|
||||
* \returns zero if complete tag list is not serialized
|
||||
*/
|
||||
uint32_t Serialize (uint32_t* buffer, uint32_t maxSize) const;
|
||||
/**
|
||||
* Deserialize tag list from the provided buffer.
|
||||
*
|
||||
* \param [in] buffer The buffer to read from.
|
||||
* \param [in] size The number of bytes to deserialize.
|
||||
*
|
||||
* \returns zero if complete tag list is not deserialized
|
||||
*/
|
||||
uint32_t Deserialize (const uint32_t* buffer, uint32_t size);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -256,12 +256,12 @@ PacketTagList::ReplaceWriter (Tag & tag, bool preMerge,
|
||||
return found;
|
||||
}
|
||||
|
||||
void
|
||||
void
|
||||
PacketTagList::Add (const Tag &tag) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
|
||||
// ensure this id was not yet added
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
{
|
||||
NS_ASSERT_MSG (cur->tid != tag.GetInstanceTypeId (),
|
||||
"Error: cannot add the same kind of tag twice.");
|
||||
@@ -281,9 +281,9 @@ PacketTagList::Peek (Tag &tag) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ());
|
||||
TypeId tid = tag.GetInstanceTypeId ();
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
{
|
||||
if (cur->tid == tid)
|
||||
if (cur->tid == tid)
|
||||
{
|
||||
/* found tag */
|
||||
tag.Deserialize (TagBuffer (cur->data, cur->data + cur->size));
|
||||
@@ -300,5 +300,164 @@ PacketTagList::Head (void) const
|
||||
return m_next;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PacketTagList::GetSerializedSize (void) const
|
||||
{
|
||||
NS_LOG_FUNCTION_NOARGS ();
|
||||
|
||||
uint32_t size = 0;
|
||||
|
||||
size = 4; // numberOfTags
|
||||
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
{
|
||||
size += 4; // TagData -> size
|
||||
|
||||
// TypeId hash; ensure size is multiple of 4 bytes
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
size += hashSize;
|
||||
|
||||
// TagData -> data; ensure size is multiple of 4 bytes
|
||||
uint32_t tagWordSize = (cur->size+3) & (~3);
|
||||
size += tagWordSize;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PacketTagList::Serialize (uint32_t* buffer, uint32_t maxSize) const
|
||||
{
|
||||
NS_LOG_FUNCTION (this << buffer << maxSize);
|
||||
|
||||
uint32_t* p = buffer;
|
||||
uint32_t size = 0;
|
||||
|
||||
uint32_t* numberOfTags = 0;
|
||||
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
numberOfTags = p;
|
||||
*p++ = 0;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->next)
|
||||
{
|
||||
if (size + 4 <= maxSize)
|
||||
{
|
||||
*p++ = cur->size;
|
||||
size += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_LOG_INFO("Serializing tag id " << cur->tid);
|
||||
|
||||
// ensure size is multiple of 4 bytes for 4 byte boundaries
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
if (size + hashSize <= maxSize)
|
||||
{
|
||||
TypeId::hash_t tid = cur->tid.GetHash ();
|
||||
memcpy (p, &tid, sizeof (TypeId::hash_t));
|
||||
p += hashSize / 4;
|
||||
size += hashSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ensure size is multiple of 4 bytes for 4 byte boundaries
|
||||
uint32_t tagWordSize = (cur->size+3) & (~3);
|
||||
if (size + tagWordSize <= maxSize)
|
||||
{
|
||||
memcpy (p, cur->data, cur->size);
|
||||
size += tagWordSize;
|
||||
p += tagWordSize / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*numberOfTags)++;
|
||||
}
|
||||
|
||||
// Serialized successfully
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PacketTagList::Deserialize (const uint32_t* buffer, uint32_t size)
|
||||
{
|
||||
NS_LOG_FUNCTION (this << buffer << size);
|
||||
const uint32_t* p = buffer;
|
||||
uint32_t sizeCheck = size - 4;
|
||||
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t numberOfTags = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
NS_LOG_INFO("Deserializing number of tags " << numberOfTags);
|
||||
|
||||
struct TagData * prevTag = 0;
|
||||
for (uint32_t i = 0; i < numberOfTags; ++i)
|
||||
{
|
||||
NS_ASSERT (sizeCheck >= 4);
|
||||
uint32_t tagSize = *p++;
|
||||
sizeCheck -= 4;
|
||||
|
||||
uint32_t hashSize = (sizeof (TypeId::hash_t)+3) & (~3);
|
||||
NS_ASSERT (sizeCheck >= hashSize);
|
||||
TypeId::hash_t hash;
|
||||
memcpy (&hash, p, sizeof (TypeId::hash_t));
|
||||
p += hashSize / 4;
|
||||
sizeCheck -= hashSize;
|
||||
|
||||
TypeId tid = TypeId::LookupByHash(hash);
|
||||
|
||||
NS_LOG_INFO ("Deserializing tag of type " << tid);
|
||||
|
||||
struct TagData * newTag = CreateTagData (tagSize);
|
||||
newTag->count = 1;
|
||||
newTag->next = 0;
|
||||
newTag->tid = tid;
|
||||
|
||||
NS_ASSERT (sizeCheck >= tagSize);
|
||||
memcpy (newTag->data, p, tagSize);
|
||||
|
||||
// ensure 4 byte boundary
|
||||
uint32_t tagWordSize = (tagSize+3) & (~3);
|
||||
p += tagWordSize / 4;
|
||||
sizeCheck -= tagWordSize;
|
||||
|
||||
// Set link list pointers.
|
||||
if (i==0)
|
||||
{
|
||||
m_next = newTag;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevTag->next = newTag;
|
||||
}
|
||||
|
||||
prevTag = newTag;
|
||||
}
|
||||
|
||||
NS_ASSERT (sizeCheck == 0);
|
||||
|
||||
// return zero if buffer did not
|
||||
// contain a complete message
|
||||
return (sizeCheck != 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
} /* namespace ns3 */
|
||||
|
||||
|
||||
@@ -217,6 +217,30 @@ public:
|
||||
* \returns pointer to head of tag list
|
||||
*/
|
||||
const struct PacketTagList::TagData *Head (void) const;
|
||||
/**
|
||||
* Returns number of bytes required for packet serialization.
|
||||
*
|
||||
* \returns number of bytes required for packet serialization
|
||||
*/
|
||||
uint32_t GetSerializedSize (void) const;
|
||||
/**
|
||||
* Serialize the tag list into a byte buffer.
|
||||
*
|
||||
* \param [in,out] buffer The byte buffer to which the tag list will be serialized
|
||||
* \param [in] maxSize Max The max size of the buffer for bounds checking
|
||||
*
|
||||
* \returns zero if complete tag list is not serialized
|
||||
*/
|
||||
uint32_t Serialize (uint32_t* buffer, uint32_t maxSize) const;
|
||||
/**
|
||||
* Deserialize tag list from the provided buffer.
|
||||
*
|
||||
* \param [in] buffer The buffer to read from.
|
||||
* \param [in] size The number of bytes to deserialize.
|
||||
*
|
||||
* \returns zero if complete tag list is not deserialized
|
||||
*/
|
||||
uint32_t Deserialize (const uint32_t* buffer, uint32_t size);
|
||||
|
||||
private:
|
||||
/**
|
||||
|
||||
@@ -603,9 +603,19 @@ uint32_t Packet::GetSerializedSize (void) const
|
||||
size += 4;
|
||||
}
|
||||
|
||||
//Tag size
|
||||
/// \todo Serialze Tags size
|
||||
//size += m_tags.GetSerializedSize ();
|
||||
// increment total size by size of packet tag list
|
||||
// ensuring 4-byte boundary
|
||||
size += ((m_packetTagList.GetSerializedSize () + 3) & (~3));
|
||||
|
||||
// add 4-bytes for entry of total length of packet tag list
|
||||
size += 4;
|
||||
|
||||
// increment total size by size of byte tag list
|
||||
// ensuring 4-byte boundary
|
||||
size += ((m_byteTagList.GetSerializedSize () + 3) & (~3));
|
||||
|
||||
// add 4-bytes for entry of total length of byte tag list
|
||||
size += 4;
|
||||
|
||||
// increment total size by size of meta-data
|
||||
// ensuring 4-byte boundary
|
||||
@@ -677,8 +687,61 @@ Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
|
||||
}
|
||||
}
|
||||
|
||||
// Serialize Tags
|
||||
/// \todo Serialize Tags
|
||||
// Serialize byte tag list
|
||||
uint32_t byteTagSize = m_byteTagList.GetSerializedSize ();
|
||||
if (size + byteTagSize <= maxSize)
|
||||
{
|
||||
// put the total length of byte tag list in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = byteTagSize + 4;
|
||||
size += byteTagSize;
|
||||
|
||||
// serialize the byte tag list
|
||||
uint32_t serialized = m_byteTagList.Serialize (p, byteTagSize);
|
||||
if (serialized)
|
||||
{
|
||||
// increment p by byteTagSize bytes
|
||||
// ensuring 4-byte boundary
|
||||
p += ((byteTagSize+3) & (~3)) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Serialize packet tag list
|
||||
uint32_t packetTagSize = m_packetTagList.GetSerializedSize ();
|
||||
if (size + packetTagSize <= maxSize)
|
||||
{
|
||||
// put the total length of packet tag list in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = packetTagSize + 4;
|
||||
size += packetTagSize;
|
||||
|
||||
// serialize the packet tag list
|
||||
uint32_t serialized = m_packetTagList.Serialize (p, packetTagSize);
|
||||
if (serialized)
|
||||
{
|
||||
// increment p by packetTagSize bytes
|
||||
// ensuring 4-byte boundary
|
||||
p += ((packetTagSize+3) & (~3)) / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Serialize Metadata
|
||||
uint32_t metaSize = m_metadata.GetSerializedSize ();
|
||||
@@ -713,7 +776,7 @@ Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
|
||||
if (size + bufSize <= maxSize)
|
||||
{
|
||||
// put the total length of the buffer in the
|
||||
// buffer. this includes 4-bytes for total
|
||||
// buffer. this includes 4-bytes for total
|
||||
// length itself
|
||||
*p++ = bufSize + 4;
|
||||
|
||||
@@ -748,8 +811,6 @@ Packet::Deserialize (const uint8_t* buffer, uint32_t size)
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= nixSize);
|
||||
|
||||
size -= nixSize;
|
||||
|
||||
if (nixSize > 4)
|
||||
{
|
||||
Ptr<NixVector> nix = Create<NixVector> ();
|
||||
@@ -765,52 +826,84 @@ Packet::Deserialize (const uint8_t* buffer, uint32_t size)
|
||||
// 4-byte boundary
|
||||
p += ((((nixSize - 4) + 3) & (~3)) / 4);
|
||||
}
|
||||
size -= nixSize;
|
||||
|
||||
// read tags
|
||||
/// \todo Deserialize Tags
|
||||
//uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
|
||||
//buffer.RemoveAtStart (tagsDeserialized);
|
||||
// read byte tags
|
||||
uint32_t byteTagSize = *p++;
|
||||
|
||||
// if size less than byteTagSize, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= byteTagSize);
|
||||
|
||||
uint32_t byteTagDeserialized =
|
||||
m_byteTagList.Deserialize (p, byteTagSize);
|
||||
if (!byteTagDeserialized)
|
||||
{
|
||||
// byte tags not deserialized completely
|
||||
return 0;
|
||||
}
|
||||
// increment p by byteTagSize ensuring
|
||||
// 4-byte boundary
|
||||
p += ((((byteTagSize - 4) + 3) & (~3)) / 4);
|
||||
size -= byteTagSize;
|
||||
|
||||
// read packet tags
|
||||
uint32_t packetTagSize = *p++;
|
||||
|
||||
// if size less than packetTagSize, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= packetTagSize);
|
||||
|
||||
uint32_t packetTagDeserialized =
|
||||
m_packetTagList.Deserialize (p, packetTagSize);
|
||||
if (!packetTagDeserialized)
|
||||
{
|
||||
// packet tags not deserialized completely
|
||||
return 0;
|
||||
}
|
||||
// increment p by packetTagSize ensuring
|
||||
// 4-byte boundary
|
||||
p += ((((packetTagSize - 4) + 3) & (~3)) / 4);
|
||||
size -= packetTagSize;
|
||||
|
||||
// read metadata
|
||||
uint32_t metaSize = *p++;
|
||||
|
||||
// if size less than metaSize, the buffer
|
||||
// if size less than metaSize, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= metaSize);
|
||||
|
||||
size -= metaSize;
|
||||
|
||||
uint32_t metadataDeserialized =
|
||||
uint32_t metadataDeserialized =
|
||||
m_metadata.Deserialize (reinterpret_cast<const uint8_t *> (p), metaSize);
|
||||
if (!metadataDeserialized)
|
||||
{
|
||||
// meta-data not deserialized
|
||||
// meta-data not deserialized
|
||||
// completely
|
||||
return 0;
|
||||
}
|
||||
// increment p by metaSize ensuring
|
||||
// increment p by metaSize ensuring
|
||||
// 4-byte boundary
|
||||
p += ((((metaSize - 4) + 3) & (~3)) / 4);
|
||||
size -= metaSize;
|
||||
|
||||
// read buffer contents
|
||||
uint32_t bufSize = *p++;
|
||||
|
||||
// if size less than bufSize, the buffer
|
||||
// if size less than bufSize, the buffer
|
||||
// will be overrun, assert
|
||||
NS_ASSERT (size >= bufSize);
|
||||
|
||||
size -= bufSize;
|
||||
|
||||
uint32_t bufferDeserialized =
|
||||
m_buffer.Deserialize (reinterpret_cast<const uint8_t *> (p), bufSize);
|
||||
if (!bufferDeserialized)
|
||||
{
|
||||
// buffer not deserialized
|
||||
// buffer not deserialized
|
||||
// completely
|
||||
return 0;
|
||||
}
|
||||
size -= bufSize;
|
||||
|
||||
// return zero if did not deserialize the
|
||||
// return zero if did not deserialize the
|
||||
// number of expected bytes
|
||||
return (size == 0);
|
||||
}
|
||||
|
||||
@@ -394,21 +394,40 @@ struct Expected
|
||||
* \param end_ End
|
||||
*/
|
||||
Expected (uint32_t n_, uint32_t start_, uint32_t end_)
|
||||
: n (n_), start (start_), end (end_) {}
|
||||
: n (n_), start (start_), end (end_), data(0) {}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* \param n_ Number of elements
|
||||
* \param start_ Start
|
||||
* \param end_ End
|
||||
* \param data_ Data stored in tag
|
||||
*/
|
||||
Expected (uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
|
||||
: n (n_), start (start_), end (end_), data(data_) {}
|
||||
|
||||
uint32_t n; //!< Number of elements
|
||||
uint32_t start; //!< Start
|
||||
uint32_t end; //!< End
|
||||
uint8_t data; //!< Optional data
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// tag name, start, end
|
||||
#define E(a,b,c) a,b,c
|
||||
#define E(name,start,end) name,start,end
|
||||
|
||||
// tag name, start, end, data
|
||||
#define E_DATA(name,start,end,data) name,start,end,data
|
||||
|
||||
// Check byte tags on a packet, checks name, start, end
|
||||
#define CHECK(p, n, ...) \
|
||||
DoCheck (p, __FILE__, __LINE__, n, __VA_ARGS__)
|
||||
|
||||
// Check byte tags on a packet, checks name, start, end, data
|
||||
#define CHECK_DATA(p, n, ...) \
|
||||
DoCheckData (p, __FILE__, __LINE__, n, __VA_ARGS__)
|
||||
|
||||
/**
|
||||
* \ingroup network-test
|
||||
* \ingroup tests
|
||||
@@ -430,6 +449,7 @@ private:
|
||||
* \param ... The variable arguments
|
||||
*/
|
||||
void DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
|
||||
void DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...);
|
||||
};
|
||||
|
||||
|
||||
@@ -474,6 +494,45 @@ PacketTest::DoCheck (Ptr<const Packet> p, const char *file, int line, uint32_t n
|
||||
NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
|
||||
}
|
||||
|
||||
void
|
||||
PacketTest::DoCheckData (Ptr<const Packet> p, const char *file, int line, uint32_t n, ...)
|
||||
{
|
||||
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);
|
||||
int data = va_arg (ap, int);
|
||||
expected.push_back (Expected (N, start, end, data));
|
||||
}
|
||||
va_end (ap);
|
||||
|
||||
ByteTagIterator i = p->GetByteTagIterator ();
|
||||
uint32_t j = 0;
|
||||
while (i.HasNext () && j < expected.size ())
|
||||
{
|
||||
ByteTagIterator::Item item = i.Next ();
|
||||
struct Expected e = expected[j];
|
||||
std::ostringstream oss;
|
||||
oss << "anon::ATestTag<" << e.n << ">";
|
||||
NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetTypeId ().GetName (), oss.str (), "trivial", file, line);
|
||||
NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetStart (), e.start, "trivial", file, line);
|
||||
NS_TEST_EXPECT_MSG_EQ_INTERNAL (item.GetEnd (), e.end, "trivial", file, line);
|
||||
ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
|
||||
NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
|
||||
item.GetTag (*tag);
|
||||
NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (tag->GetData (), e.data, "trivial");
|
||||
delete tag;
|
||||
j++;
|
||||
}
|
||||
NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
|
||||
NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
|
||||
}
|
||||
|
||||
void
|
||||
PacketTest::DoRun (void)
|
||||
{
|
||||
@@ -641,6 +700,58 @@ PacketTest::DoRun (void)
|
||||
NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
|
||||
}
|
||||
|
||||
/* Test Serialization and Deserialization of Packet with PacketTag data */
|
||||
{
|
||||
Ptr<Packet> p1 = Create<Packet> (1000);;
|
||||
ATestTag<10> a1(65);
|
||||
ATestTag<11> b1(66);
|
||||
ATestTag<12> c1(67);
|
||||
|
||||
p1->AddPacketTag (a1);
|
||||
p1->AddPacketTag (b1);
|
||||
p1->AddPacketTag (c1);
|
||||
|
||||
uint32_t serializedSize = p1->GetSerializedSize ();
|
||||
uint8_t* buffer = new uint8_t[serializedSize + 16];
|
||||
p1->Serialize (buffer, serializedSize);
|
||||
|
||||
Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
|
||||
|
||||
ATestTag<10> a2;
|
||||
ATestTag<11> b2;
|
||||
ATestTag<12> c2;
|
||||
|
||||
NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(a2), true, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (a2.GetData (), 65, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(b2), true, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (b2.GetData (), 66, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(c2), true, "trivial");
|
||||
NS_TEST_EXPECT_MSG_EQ (c2.GetData (), 67, "trivial");
|
||||
}
|
||||
|
||||
/* Test Serialization and Deserialization of Packet with ByteTag data */
|
||||
{
|
||||
Ptr<Packet> p1 = Create<Packet> (1000);;
|
||||
|
||||
ATestTag<10> a1(65);
|
||||
ATestTag<11> b1(66);
|
||||
ATestTag<12> c1(67);
|
||||
|
||||
p1->AddByteTag (a1);
|
||||
p1->AddByteTag (b1);
|
||||
p1->AddByteTag (c1);
|
||||
|
||||
CHECK (p1, 3, E (10, 0, 1000), E (11, 0, 1000), E (12, 0, 1000));
|
||||
|
||||
uint32_t serializedSize = p1->GetSerializedSize ();
|
||||
uint8_t* buffer = new uint8_t[serializedSize];
|
||||
p1->Serialize (buffer, serializedSize);
|
||||
|
||||
Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
|
||||
|
||||
CHECK_DATA (p2, 3, E_DATA (10, 0, 1000, 65), E_DATA (11, 0, 1000, 66), E_DATA (12, 0, 1000, 67));
|
||||
}
|
||||
|
||||
{
|
||||
/// \internal
|
||||
/// See \bugid{572}
|
||||
|
||||
Reference in New Issue
Block a user