1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3 * Copyright (c) 2005,2006 INRIA
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19 */
20 #include "packet.h"
21 #include "ns3/assert.h"
22 #include "ns3/log.h"
23 #include "ns3/simulator.h"
24 #include <string>
25 #include <cstdarg>
26
27 namespace ns3 {
28
29 NS_LOG_COMPONENT_DEFINE ("Packet");
30
31 uint32_t Packet::m_globalUid = 0;
32
33 TypeId
GetTypeId(void) const34 ByteTagIterator::Item::GetTypeId (void) const
35 {
36 return m_tid;
37 }
38 uint32_t
GetStart(void) const39 ByteTagIterator::Item::GetStart (void) const
40 {
41 return m_start;
42 }
43 uint32_t
GetEnd(void) const44 ByteTagIterator::Item::GetEnd (void) const
45 {
46 return m_end;
47 }
48 void
GetTag(Tag & tag) const49 ByteTagIterator::Item::GetTag (Tag &tag) const
50 {
51 if (tag.GetInstanceTypeId () != GetTypeId ())
52 {
53 NS_FATAL_ERROR ("The tag you provided is not of the right type.");
54 }
55 tag.Deserialize (m_buffer);
56 }
Item(TypeId tid,uint32_t start,uint32_t end,TagBuffer buffer)57 ByteTagIterator::Item::Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer)
58 : m_tid (tid),
59 m_start (start),
60 m_end (end),
61 m_buffer (buffer)
62 {
63 }
64 bool
HasNext(void) const65 ByteTagIterator::HasNext (void) const
66 {
67 return m_current.HasNext ();
68 }
69 ByteTagIterator::Item
Next(void)70 ByteTagIterator::Next (void)
71 {
72 ByteTagList::Iterator::Item i = m_current.Next ();
73 return ByteTagIterator::Item (i.tid,
74 i.start-m_current.GetOffsetStart (),
75 i.end-m_current.GetOffsetStart (),
76 i.buf);
77 }
ByteTagIterator(ByteTagList::Iterator i)78 ByteTagIterator::ByteTagIterator (ByteTagList::Iterator i)
79 : m_current (i)
80 {
81 }
82
83
PacketTagIterator(const struct PacketTagList::TagData * head)84 PacketTagIterator::PacketTagIterator (const struct PacketTagList::TagData *head)
85 : m_current (head)
86 {
87 }
88 bool
HasNext(void) const89 PacketTagIterator::HasNext (void) const
90 {
91 return m_current != 0;
92 }
93 PacketTagIterator::Item
Next(void)94 PacketTagIterator::Next (void)
95 {
96 NS_ASSERT (HasNext ());
97 const struct PacketTagList::TagData *prev = m_current;
98 m_current = m_current->next;
99 return PacketTagIterator::Item (prev);
100 }
101
Item(const struct PacketTagList::TagData * data)102 PacketTagIterator::Item::Item (const struct PacketTagList::TagData *data)
103 : m_data (data)
104 {
105 }
106 TypeId
GetTypeId(void) const107 PacketTagIterator::Item::GetTypeId (void) const
108 {
109 return m_data->tid;
110 }
111 void
GetTag(Tag & tag) const112 PacketTagIterator::Item::GetTag (Tag &tag) const
113 {
114 NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
115 tag.Deserialize (TagBuffer ((uint8_t*)m_data->data,
116 (uint8_t*)m_data->data + m_data->size));
117 }
118
119
120 Ptr<Packet>
Copy(void) const121 Packet::Copy (void) const
122 {
123 // we need to invoke the copy constructor directly
124 // rather than calling Create because the copy constructor
125 // is private.
126 return Ptr<Packet> (new Packet (*this), false);
127 }
128
Packet()129 Packet::Packet ()
130 : m_buffer (),
131 m_byteTagList (),
132 m_packetTagList (),
133 /* The upper 32 bits of the packet id in
134 * metadata is for the system id. For non-
135 * distributed simulations, this is simply
136 * zero. The lower 32 bits are for the
137 * global UID
138 */
139 m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, 0),
140 m_nixVector (0)
141 {
142 m_globalUid++;
143 }
144
Packet(const Packet & o)145 Packet::Packet (const Packet &o)
146 : m_buffer (o.m_buffer),
147 m_byteTagList (o.m_byteTagList),
148 m_packetTagList (o.m_packetTagList),
149 m_metadata (o.m_metadata)
150 {
151 o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
152 : m_nixVector = 0;
153 }
154
155 Packet &
operator =(const Packet & o)156 Packet::operator = (const Packet &o)
157 {
158 if (this == &o)
159 {
160 return *this;
161 }
162 m_buffer = o.m_buffer;
163 m_byteTagList = o.m_byteTagList;
164 m_packetTagList = o.m_packetTagList;
165 m_metadata = o.m_metadata;
166 o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
167 : m_nixVector = 0;
168 return *this;
169 }
170
Packet(uint32_t size)171 Packet::Packet (uint32_t size)
172 : m_buffer (size),
173 m_byteTagList (),
174 m_packetTagList (),
175 /* The upper 32 bits of the packet id in
176 * metadata is for the system id. For non-
177 * distributed simulations, this is simply
178 * zero. The lower 32 bits are for the
179 * global UID
180 */
181 m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
182 m_nixVector (0)
183 {
184 m_globalUid++;
185 }
Packet(uint8_t const * buffer,uint32_t size,bool magic)186 Packet::Packet (uint8_t const *buffer, uint32_t size, bool magic)
187 : m_buffer (0, false),
188 m_byteTagList (),
189 m_packetTagList (),
190 m_metadata (0,0),
191 m_nixVector (0)
192 {
193 NS_ASSERT (magic);
194 Deserialize (buffer, size);
195 }
196
Packet(uint8_t const * buffer,uint32_t size)197 Packet::Packet (uint8_t const*buffer, uint32_t size)
198 : m_buffer (),
199 m_byteTagList (),
200 m_packetTagList (),
201 /* The upper 32 bits of the packet id in
202 * metadata is for the system id. For non-
203 * distributed simulations, this is simply
204 * zero. The lower 32 bits are for the
205 * global UID
206 */
207 m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
208 m_nixVector (0)
209 {
210 m_globalUid++;
211 m_buffer.AddAtStart (size);
212 Buffer::Iterator i = m_buffer.Begin ();
213 i.Write (buffer, size);
214 }
215
Packet(const Buffer & buffer,const ByteTagList & byteTagList,const PacketTagList & packetTagList,const PacketMetadata & metadata)216 Packet::Packet (const Buffer &buffer, const ByteTagList &byteTagList,
217 const PacketTagList &packetTagList, const PacketMetadata &metadata)
218 : m_buffer (buffer),
219 m_byteTagList (byteTagList),
220 m_packetTagList (packetTagList),
221 m_metadata (metadata),
222 m_nixVector (0)
223 {
224 }
225
226 Ptr<Packet>
CreateFragment(uint32_t start,uint32_t length) const227 Packet::CreateFragment (uint32_t start, uint32_t length) const
228 {
229 NS_LOG_FUNCTION (this << start << length);
230 Buffer buffer = m_buffer.CreateFragment (start, length);
231 ByteTagList byteTagList = m_byteTagList;
232 byteTagList.Adjust (-start);
233 NS_ASSERT (m_buffer.GetSize () >= start + length);
234 uint32_t end = m_buffer.GetSize () - (start + length);
235 PacketMetadata metadata = m_metadata.CreateFragment (start, end);
236 // again, call the constructor directly rather than
237 // through Create because it is private.
238 Ptr<Packet> ret = Ptr<Packet> (new Packet (buffer, byteTagList, m_packetTagList, metadata), false);
239 ret->SetNixVector (GetNixVector ());
240 return ret;
241 }
242
243 void
SetNixVector(Ptr<NixVector> nixVector)244 Packet::SetNixVector (Ptr<NixVector> nixVector)
245 {
246 m_nixVector = nixVector;
247 }
248
249 Ptr<NixVector>
GetNixVector(void) const250 Packet::GetNixVector (void) const
251 {
252 return m_nixVector;
253 }
254
255 void
AddHeader(const Header & header)256 Packet::AddHeader (const Header &header)
257 {
258 uint32_t size = header.GetSerializedSize ();
259 NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << size);
260 m_buffer.AddAtStart (size);
261 m_byteTagList.Adjust (size);
262 m_byteTagList.AddAtStart (size);
263 header.Serialize (m_buffer.Begin ());
264 m_metadata.AddHeader (header, size);
265 }
266 uint32_t
RemoveHeader(Header & header,uint32_t size)267 Packet::RemoveHeader (Header &header, uint32_t size)
268 {
269 Buffer::Iterator end;
270 end = m_buffer.Begin ();
271 end.Next (size);
272 uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end);
273 NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
274 m_buffer.RemoveAtStart (deserialized);
275 m_byteTagList.Adjust (-deserialized);
276 m_metadata.RemoveHeader (header, deserialized);
277 return deserialized;
278 }
279 uint32_t
RemoveHeader(Header & header)280 Packet::RemoveHeader (Header &header)
281 {
282 uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
283 NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
284 m_buffer.RemoveAtStart (deserialized);
285 m_byteTagList.Adjust (-deserialized);
286 m_metadata.RemoveHeader (header, deserialized);
287 return deserialized;
288 }
289 uint32_t
PeekHeader(Header & header) const290 Packet::PeekHeader (Header &header) const
291 {
292 uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
293 NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
294 return deserialized;
295 }
296 uint32_t
PeekHeader(Header & header,uint32_t size) const297 Packet::PeekHeader (Header &header, uint32_t size) const
298 {
299 Buffer::Iterator end;
300 end = m_buffer.Begin ();
301 end.Next (size);
302 uint32_t deserialized = header.Deserialize (m_buffer.Begin (), end);
303 NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
304 return deserialized;
305 }
306 void
AddTrailer(const Trailer & trailer)307 Packet::AddTrailer (const Trailer &trailer)
308 {
309 uint32_t size = trailer.GetSerializedSize ();
310 NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << size);
311 m_byteTagList.AddAtEnd (GetSize ());
312 m_buffer.AddAtEnd (size);
313 Buffer::Iterator end = m_buffer.End ();
314 trailer.Serialize (end);
315 m_metadata.AddTrailer (trailer, size);
316 }
317 uint32_t
RemoveTrailer(Trailer & trailer)318 Packet::RemoveTrailer (Trailer &trailer)
319 {
320 uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
321 NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
322 m_buffer.RemoveAtEnd (deserialized);
323 m_metadata.RemoveTrailer (trailer, deserialized);
324 return deserialized;
325 }
326 uint32_t
PeekTrailer(Trailer & trailer)327 Packet::PeekTrailer (Trailer &trailer)
328 {
329 uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
330 NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
331 return deserialized;
332 }
333
334 void
AddAtEnd(Ptr<const Packet> packet)335 Packet::AddAtEnd (Ptr<const Packet> packet)
336 {
337 NS_LOG_FUNCTION (this << packet << packet->GetSize ());
338 m_byteTagList.AddAtEnd (GetSize ());
339 ByteTagList copy = packet->m_byteTagList;
340 copy.AddAtStart (0);
341 copy.Adjust (GetSize ());
342 m_byteTagList.Add (copy);
343 m_buffer.AddAtEnd (packet->m_buffer);
344 m_metadata.AddAtEnd (packet->m_metadata);
345 }
346 void
AddPaddingAtEnd(uint32_t size)347 Packet::AddPaddingAtEnd (uint32_t size)
348 {
349 NS_LOG_FUNCTION (this << size);
350 m_byteTagList.AddAtEnd (GetSize ());
351 m_buffer.AddAtEnd (size);
352 m_metadata.AddPaddingAtEnd (size);
353 }
354 void
RemoveAtEnd(uint32_t size)355 Packet::RemoveAtEnd (uint32_t size)
356 {
357 NS_LOG_FUNCTION (this << size);
358 m_buffer.RemoveAtEnd (size);
359 m_metadata.RemoveAtEnd (size);
360 }
361 void
RemoveAtStart(uint32_t size)362 Packet::RemoveAtStart (uint32_t size)
363 {
364 NS_LOG_FUNCTION (this << size);
365 m_buffer.RemoveAtStart (size);
366 m_byteTagList.Adjust (-size);
367 m_metadata.RemoveAtStart (size);
368 }
369
370 void
RemoveAllByteTags(void)371 Packet::RemoveAllByteTags (void)
372 {
373 NS_LOG_FUNCTION (this);
374 m_byteTagList.RemoveAll ();
375 }
376
377 uint32_t
CopyData(uint8_t * buffer,uint32_t size) const378 Packet::CopyData (uint8_t *buffer, uint32_t size) const
379 {
380 return m_buffer.CopyData (buffer, size);
381 }
382
383 void
CopyData(std::ostream * os,uint32_t size) const384 Packet::CopyData (std::ostream *os, uint32_t size) const
385 {
386 return m_buffer.CopyData (os, size);
387 }
388
389 uint64_t
GetUid(void) const390 Packet::GetUid (void) const
391 {
392 return m_metadata.GetUid ();
393 }
394
395 void
PrintByteTags(std::ostream & os) const396 Packet::PrintByteTags (std::ostream &os) const
397 {
398 ByteTagIterator i = GetByteTagIterator ();
399 while (i.HasNext ())
400 {
401 ByteTagIterator::Item item = i.Next ();
402 os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
403 Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
404 if (constructor.IsNull ())
405 {
406 if (i.HasNext ())
407 {
408 os << " ";
409 }
410 continue;
411 }
412 Tag *tag = dynamic_cast<Tag *> (constructor ());
413 NS_ASSERT (tag != 0);
414 os << " ";
415 item.GetTag (*tag);
416 tag->Print (os);
417 if (i.HasNext ())
418 {
419 os << " ";
420 }
421 delete tag;
422 }
423 }
424
425 std::string
ToString() const426 Packet::ToString() const
427 {
428 std::ostringstream oss;
429 Print (oss);
430 return oss.str();
431 }
432
433 void
Print(std::ostream & os) const434 Packet::Print (std::ostream &os) const
435 {
436 PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
437 while (i.HasNext ())
438 {
439 PacketMetadata::Item item = i.Next ();
440 if (item.isFragment)
441 {
442 switch (item.type) {
443 case PacketMetadata::Item::PAYLOAD:
444 os << "Payload";
445 break;
446 case PacketMetadata::Item::HEADER:
447 case PacketMetadata::Item::TRAILER:
448 os << item.tid.GetName ();
449 break;
450 }
451 os << " Fragment [" << item.currentTrimedFromStart<<":"
452 << (item.currentTrimedFromStart + item.currentSize) << "]";
453 }
454 else
455 {
456 switch (item.type) {
457 case PacketMetadata::Item::PAYLOAD:
458 os << "Payload (size=" << item.currentSize << ")";
459 break;
460 case PacketMetadata::Item::HEADER:
461 case PacketMetadata::Item::TRAILER:
462 os << item.tid.GetName () << " (";
463 {
464 NS_ASSERT (item.tid.HasConstructor ());
465 Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
466 NS_ASSERT (!constructor.IsNull ());
467 ObjectBase *instance = constructor ();
468 NS_ASSERT (instance != 0);
469 Chunk *chunk = dynamic_cast<Chunk *> (instance);
470 NS_ASSERT (chunk != 0);
471 if (item.type == PacketMetadata::Item::HEADER)
472 {
473 Buffer::Iterator end = item.current;
474 end.Next (item.currentSize); // move from start
475 chunk->Deserialize (item.current, end);
476 }
477 else if (item.type == PacketMetadata::Item::TRAILER)
478 {
479 Buffer::Iterator start = item.current;
480 start.Prev (item.currentSize); // move from end
481 chunk->Deserialize (start, item.current);
482 }
483 else
484 {
485 chunk->Deserialize (item.current);
486 }
487 chunk->Print (os);
488 delete chunk;
489 }
490 os << ")";
491 break;
492 }
493 }
494 if (i.HasNext ())
495 {
496 os << " ";
497 }
498 }
499 #if 0
500 // The code below will work only if headers and trailers
501 // define the right attributes which is not the case for
502 // now. So, as a temporary measure, we use the
503 // headers' and trailers' Print method as shown above.
504 PacketMetadata::ItemIterator i = m_metadata.BeginItem (m_buffer);
505 while (i.HasNext ())
506 {
507 PacketMetadata::Item item = i.Next ();
508 if (item.isFragment)
509 {
510 switch (item.type) {
511 case PacketMetadata::Item::PAYLOAD:
512 os << "Payload";
513 break;
514 case PacketMetadata::Item::HEADER:
515 case PacketMetadata::Item::TRAILER:
516 os << item.tid.GetName ();
517 break;
518 }
519 os << " Fragment [" << item.currentTrimedFromStart<<":"
520 << (item.currentTrimedFromStart + item.currentSize) << "]";
521 }
522 else
523 {
524 switch (item.type) {
525 case PacketMetadata::Item::PAYLOAD:
526 os << "Payload (size=" << item.currentSize << ")";
527 break;
528 case PacketMetadata::Item::HEADER:
529 case PacketMetadata::Item::TRAILER:
530 os << item.tid.GetName () << "(";
531 {
532 NS_ASSERT (item.tid.HasConstructor ());
533 Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
534 NS_ASSERT (constructor.IsNull ());
535 ObjectBase *instance = constructor ();
536 NS_ASSERT (instance != 0);
537 Chunk *chunk = dynamic_cast<Chunk *> (instance);
538 NS_ASSERT (chunk != 0);
539 chunk->Deserialize (item.current);
540 for (uint32_t j = 0; j < item.tid.GetAttributeN (); j++)
541 {
542 std::string attrName = item.tid.GetAttributeName (j);
543 std::string value;
544 bool ok = chunk->GetAttribute (attrName, value);
545 NS_ASSERT (ok);
546 os << attrName << "=" << value;
547 if ((j + 1) < item.tid.GetAttributeN ())
548 {
549 os << ",";
550 }
551 }
552 }
553 os << ")";
554 break;
555 }
556 }
557 if (i.HasNext ())
558 {
559 os << " ";
560 }
561 }
562 #endif
563 }
564
565 PacketMetadata::ItemIterator
BeginItem(void) const566 Packet::BeginItem (void) const
567 {
568 return m_metadata.BeginItem (m_buffer);
569 }
570
571 void
EnablePrinting(void)572 Packet::EnablePrinting (void)
573 {
574 NS_LOG_FUNCTION_NOARGS ();
575 PacketMetadata::Enable ();
576 }
577
578 void
EnableChecking(void)579 Packet::EnableChecking (void)
580 {
581 NS_LOG_FUNCTION_NOARGS ();
582 PacketMetadata::EnableChecking ();
583 }
584
GetSerializedSize(void) const585 uint32_t Packet::GetSerializedSize (void) const
586 {
587 uint32_t size = 0;
588
589 if (m_nixVector)
590 {
591 // increment total size by the size of the nix-vector
592 // ensuring 4-byte boundary
593 size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
594
595 // add 4-bytes for entry of total length of nix-vector
596 size += 4;
597 }
598 else
599 {
600 // if no nix-vector, still have to add 4-bytes
601 // to account for the entry of total size for
602 // nix-vector in the buffer
603 size += 4;
604 }
605
606 // increment total size by size of packet tag list
607 // ensuring 4-byte boundary
608 size += ((m_packetTagList.GetSerializedSize () + 3) & (~3));
609
610 // add 4-bytes for entry of total length of packet tag list
611 size += 4;
612
613 // increment total size by size of byte tag list
614 // ensuring 4-byte boundary
615 size += ((m_byteTagList.GetSerializedSize () + 3) & (~3));
616
617 // add 4-bytes for entry of total length of byte tag list
618 size += 4;
619
620 // increment total size by size of meta-data
621 // ensuring 4-byte boundary
622 size += ((m_metadata.GetSerializedSize () + 3) & (~3));
623
624 // add 4-bytes for entry of total length of meta-data
625 size += 4;
626
627 // increment total size by size of buffer
628 // ensuring 4-byte boundary
629 size += ((m_buffer.GetSerializedSize () + 3) & (~3));
630
631 // add 4-bytes for entry of total length of buffer
632 size += 4;
633
634 return size;
635 }
636
637 uint32_t
Serialize(uint8_t * buffer,uint32_t maxSize) const638 Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
639 {
640 uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
641 uint32_t size = 0;
642
643 // if nix-vector exists, serialize it
644 if (m_nixVector)
645 {
646 uint32_t nixSize = m_nixVector->GetSerializedSize ();
647 if (size + nixSize <= maxSize)
648 {
649 // put the total length of nix-vector in the
650 // buffer. this includes 4-bytes for total
651 // length itself
652 *p++ = nixSize + 4;
653 size += nixSize;
654
655 // serialize the nix-vector
656 uint32_t serialized =
657 m_nixVector->Serialize (p, nixSize);
658 if (serialized)
659 {
660 // increment p by nixSize bytes
661 // ensuring 4-byte boundary
662 p += ((nixSize+3) & (~3)) / 4;
663 }
664 else
665 {
666 return 0;
667 }
668 }
669 else
670 {
671 return 0;
672 }
673 }
674 else
675 {
676 // no nix vector, set zero length,
677 // ie 4-bytes, since it must include
678 // length for itself
679 if (size + 4 <= maxSize)
680 {
681 size += 4;
682 *p++ = 4;
683 }
684 else
685 {
686 return 0;
687 }
688 }
689
690 // Serialize byte tag list
691 uint32_t byteTagSize = m_byteTagList.GetSerializedSize ();
692 if (size + byteTagSize <= maxSize)
693 {
694 // put the total length of byte tag list in the
695 // buffer. this includes 4-bytes for total
696 // length itself
697 *p++ = byteTagSize + 4;
698 size += byteTagSize;
699
700 // serialize the byte tag list
701 uint32_t serialized = m_byteTagList.Serialize (p, byteTagSize);
702 if (serialized)
703 {
704 // increment p by byteTagSize bytes
705 // ensuring 4-byte boundary
706 p += ((byteTagSize+3) & (~3)) / 4;
707 }
708 else
709 {
710 return 0;
711 }
712 }
713 else
714 {
715 return 0;
716 }
717
718 // Serialize packet tag list
719 uint32_t packetTagSize = m_packetTagList.GetSerializedSize ();
720 if (size + packetTagSize <= maxSize)
721 {
722 // put the total length of packet tag list in the
723 // buffer. this includes 4-bytes for total
724 // length itself
725 *p++ = packetTagSize + 4;
726 size += packetTagSize;
727
728 // serialize the packet tag list
729 uint32_t serialized = m_packetTagList.Serialize (p, packetTagSize);
730 if (serialized)
731 {
732 // increment p by packetTagSize bytes
733 // ensuring 4-byte boundary
734 p += ((packetTagSize+3) & (~3)) / 4;
735 }
736 else
737 {
738 return 0;
739 }
740 }
741 else
742 {
743 return 0;
744 }
745
746 // Serialize Metadata
747 uint32_t metaSize = m_metadata.GetSerializedSize ();
748 if (size + metaSize <= maxSize)
749 {
750 // put the total length of metadata in the
751 // buffer. this includes 4-bytes for total
752 // length itself
753 *p++ = metaSize + 4;
754 size += metaSize;
755
756 // serialize the metadata
757 uint32_t serialized = m_metadata.Serialize (reinterpret_cast<uint8_t *> (p), metaSize);
758 if (serialized)
759 {
760 // increment p by metaSize bytes
761 // ensuring 4-byte boundary
762 p += ((metaSize+3) & (~3)) / 4;
763 }
764 else
765 {
766 return 0;
767 }
768 }
769 else
770 {
771 return 0;
772 }
773
774 // Serialize the packet contents
775 uint32_t bufSize = m_buffer.GetSerializedSize ();
776 if (size + bufSize <= maxSize)
777 {
778 // put the total length of the buffer in the
779 // buffer. this includes 4-bytes for total
780 // length itself
781 *p++ = bufSize + 4;
782
783 // serialize the buffer
784 uint32_t serialized = m_buffer.Serialize (reinterpret_cast<uint8_t *> (p), bufSize);
785 if (!serialized)
786 {
787 return 0;
788 }
789 }
790 else
791 {
792 return 0;
793 }
794
795 // Serialized successfully
796 return 1;
797 }
798
799 uint32_t
Deserialize(const uint8_t * buffer,uint32_t size)800 Packet::Deserialize (const uint8_t* buffer, uint32_t size)
801 {
802 NS_LOG_FUNCTION (this);
803
804 const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
805
806 // read nix-vector
807 NS_ASSERT (!m_nixVector);
808 uint32_t nixSize = *p++;
809
810 // if size less than nixSize, the buffer
811 // will be overrun, assert
812 NS_ASSERT (size >= nixSize);
813
814 if (nixSize > 4)
815 {
816 Ptr<NixVector> nix = Create<NixVector> ();
817 uint32_t nixDeserialized = nix->Deserialize (p, nixSize);
818 if (!nixDeserialized)
819 {
820 // nix-vector not deserialized
821 // completely
822 return 0;
823 }
824 m_nixVector = nix;
825 // increment p by nixSize ensuring
826 // 4-byte boundary
827 p += ((((nixSize - 4) + 3) & (~3)) / 4);
828 }
829 size -= nixSize;
830
831 // read byte tags
832 uint32_t byteTagSize = *p++;
833
834 // if size less than byteTagSize, the buffer
835 // will be overrun, assert
836 NS_ASSERT (size >= byteTagSize);
837
838 uint32_t byteTagDeserialized =
839 m_byteTagList.Deserialize (p, byteTagSize);
840 if (!byteTagDeserialized)
841 {
842 // byte tags not deserialized completely
843 return 0;
844 }
845 // increment p by byteTagSize ensuring
846 // 4-byte boundary
847 p += ((((byteTagSize - 4) + 3) & (~3)) / 4);
848 size -= byteTagSize;
849
850 // read packet tags
851 uint32_t packetTagSize = *p++;
852
853 // if size less than packetTagSize, the buffer
854 // will be overrun, assert
855 NS_ASSERT (size >= packetTagSize);
856
857 uint32_t packetTagDeserialized =
858 m_packetTagList.Deserialize (p, packetTagSize);
859 if (!packetTagDeserialized)
860 {
861 // packet tags not deserialized completely
862 return 0;
863 }
864 // increment p by packetTagSize ensuring
865 // 4-byte boundary
866 p += ((((packetTagSize - 4) + 3) & (~3)) / 4);
867 size -= packetTagSize;
868
869 // read metadata
870 uint32_t metaSize = *p++;
871
872 // if size less than metaSize, the buffer
873 // will be overrun, assert
874 NS_ASSERT (size >= metaSize);
875
876 uint32_t metadataDeserialized =
877 m_metadata.Deserialize (reinterpret_cast<const uint8_t *> (p), metaSize);
878 if (!metadataDeserialized)
879 {
880 // meta-data not deserialized
881 // completely
882 return 0;
883 }
884 // increment p by metaSize ensuring
885 // 4-byte boundary
886 p += ((((metaSize - 4) + 3) & (~3)) / 4);
887 size -= metaSize;
888
889 // read buffer contents
890 uint32_t bufSize = *p++;
891
892 // if size less than bufSize, the buffer
893 // will be overrun, assert
894 NS_ASSERT (size >= bufSize);
895
896 uint32_t bufferDeserialized =
897 m_buffer.Deserialize (reinterpret_cast<const uint8_t *> (p), bufSize);
898 if (!bufferDeserialized)
899 {
900 // buffer not deserialized
901 // completely
902 return 0;
903 }
904 size -= bufSize;
905
906 // return zero if did not deserialize the
907 // number of expected bytes
908 return (size == 0);
909 }
910
911 void
AddByteTag(const Tag & tag) const912 Packet::AddByteTag (const Tag &tag) const
913 {
914 NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
915 ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
916 TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
917 0,
918 GetSize ());
919 tag.Serialize (buffer);
920 }
921 void
AddByteTag(const Tag & tag,uint32_t start,uint32_t end) const922 Packet::AddByteTag (const Tag &tag, uint32_t start, uint32_t end) const
923 {
924 NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
925 NS_ABORT_MSG_IF (end < start, "Invalid byte range");
926 ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
927 TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
928 static_cast<int32_t> (start),
929 static_cast<int32_t> (end));
930 tag.Serialize (buffer);
931 }
932 ByteTagIterator
GetByteTagIterator(void) const933 Packet::GetByteTagIterator (void) const
934 {
935 return ByteTagIterator (m_byteTagList.Begin (0, GetSize ()));
936 }
937
938 bool
FindFirstMatchingByteTag(Tag & tag) const939 Packet::FindFirstMatchingByteTag (Tag &tag) const
940 {
941 TypeId tid = tag.GetInstanceTypeId ();
942 ByteTagIterator i = GetByteTagIterator ();
943 while (i.HasNext ())
944 {
945 ByteTagIterator::Item item = i.Next ();
946 if (tid == item.GetTypeId ())
947 {
948 item.GetTag (tag);
949 return true;
950 }
951 }
952 return false;
953 }
954
955 void
AddPacketTag(const Tag & tag) const956 Packet::AddPacketTag (const Tag &tag) const
957 {
958 NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
959 m_packetTagList.Add (tag);
960 }
961
962 bool
RemovePacketTag(Tag & tag)963 Packet::RemovePacketTag (Tag &tag)
964 {
965 NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
966 bool found = m_packetTagList.Remove (tag);
967 return found;
968 }
969 bool
ReplacePacketTag(Tag & tag)970 Packet::ReplacePacketTag (Tag &tag)
971 {
972 NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
973 bool found = m_packetTagList.Replace (tag);
974 return found;
975 }
976
977 bool
PeekPacketTag(Tag & tag) const978 Packet::PeekPacketTag (Tag &tag) const
979 {
980 bool found = m_packetTagList.Peek (tag);
981 return found;
982 }
983 void
RemoveAllPacketTags(void)984 Packet::RemoveAllPacketTags (void)
985 {
986 NS_LOG_FUNCTION (this);
987 m_packetTagList.RemoveAll ();
988 }
989
990 void
PrintPacketTags(std::ostream & os) const991 Packet::PrintPacketTags (std::ostream &os) const
992 {
993 PacketTagIterator i = GetPacketTagIterator ();
994 while (i.HasNext ())
995 {
996 PacketTagIterator::Item item = i.Next ();
997 NS_ASSERT (item.GetTypeId ().HasConstructor ());
998 Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
999 NS_ASSERT (!constructor.IsNull ());
1000 ObjectBase *instance = constructor ();
1001 Tag *tag = dynamic_cast<Tag *> (instance);
1002 NS_ASSERT (tag != 0);
1003 item.GetTag (*tag);
1004 tag->Print (os);
1005 delete tag;
1006 if (i.HasNext ())
1007 {
1008 os << " ";
1009 }
1010 }
1011 }
1012
1013 PacketTagIterator
GetPacketTagIterator(void) const1014 Packet::GetPacketTagIterator (void) const
1015 {
1016 return PacketTagIterator (m_packetTagList.Head ());
1017 }
1018
operator <<(std::ostream & os,const Packet & packet)1019 std::ostream& operator<< (std::ostream& os, const Packet &packet)
1020 {
1021 packet.Print (os);
1022 return os;
1023 }
1024
1025 } // namespace ns3
1026