A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
packet.cc
Go to the documentation of this file.
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 <stdarg.h>
26 
27 NS_LOG_COMPONENT_DEFINE ("Packet");
28 
29 namespace ns3 {
30 
31 uint32_t Packet::m_globalUid = 0;
32 
33 TypeId
35 {
36  return m_tid;
37 }
38 uint32_t
40 {
41  return m_start;
42 }
43 uint32_t
45 {
46  return m_end;
47 }
48 void
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 }
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
66 {
67  return m_current.HasNext ();
68 }
71 {
73  return ByteTagIterator::Item (i.tid,
76  i.buf);
77 }
79  : m_current (i)
80 {
81 }
82 
83 
85  : m_current (head)
86 {
87 }
88 bool
90 {
91  return m_current != 0;
92 }
95 {
96  NS_ASSERT (HasNext ());
97  const struct PacketTagList::TagData *prev = m_current;
99  return PacketTagIterator::Item (prev);
100 }
101 
103  : m_data (data)
104 {
105 }
106 TypeId
108 {
109  return m_data->tid;
110 }
111 void
113 {
114  NS_ASSERT (tag.GetInstanceTypeId () == m_data->tid);
115  tag.Deserialize (TagBuffer ((uint8_t*)m_data->data, (uint8_t*)m_data->data+PACKET_TAG_MAX_SIZE));
116 }
117 
118 
120 Packet::Copy (void) const
121 {
122  // we need to invoke the copy constructor directly
123  // rather than calling Create because the copy constructor
124  // is private.
125  return Ptr<Packet> (new Packet (*this), false);
126 }
127 
129  : m_buffer (),
130  m_byteTagList (),
131  m_packetTagList (),
132  /* The upper 32 bits of the packet id in
133  * metadata is for the system id. For non-
134  * distributed simulations, this is simply
135  * zero. The lower 32 bits are for the
136  * global UID
137  */
138  m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, 0),
139  m_nixVector (0)
140 {
141  m_globalUid++;
142 }
143 
145  : m_buffer (o.m_buffer),
146  m_byteTagList (o.m_byteTagList),
147  m_packetTagList (o.m_packetTagList),
148  m_metadata (o.m_metadata)
149 {
151  : m_nixVector = 0;
152 }
153 
154 Packet &
156 {
157  if (this == &o)
158  {
159  return *this;
160  }
161  m_buffer = o.m_buffer;
166  : m_nixVector = 0;
167  return *this;
168 }
169 
170 Packet::Packet (uint32_t size)
171  : m_buffer (size),
172  m_byteTagList (),
173  m_packetTagList (),
174  /* The upper 32 bits of the packet id in
175  * metadata is for the system id. For non-
176  * distributed simulations, this is simply
177  * zero. The lower 32 bits are for the
178  * global UID
179  */
180  m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
181  m_nixVector (0)
182 {
183  m_globalUid++;
184 }
185 Packet::Packet (uint8_t const *buffer, uint32_t size, bool magic)
186  : m_buffer (0, false),
187  m_byteTagList (),
188  m_packetTagList (),
189  m_metadata (0,0),
190  m_nixVector (0)
191 {
192  NS_ASSERT (magic);
193  Deserialize (buffer, size);
194 }
195 
196 Packet::Packet (uint8_t const*buffer, uint32_t size)
197  : m_buffer (),
198  m_byteTagList (),
199  m_packetTagList (),
200  /* The upper 32 bits of the packet id in
201  * metadata is for the system id. For non-
202  * distributed simulations, this is simply
203  * zero. The lower 32 bits are for the
204  * global UID
205  */
206  m_metadata (static_cast<uint64_t> (Simulator::GetSystemId ()) << 32 | m_globalUid, size),
207  m_nixVector (0)
208 {
209  m_globalUid++;
210  m_buffer.AddAtStart (size);
212  i.Write (buffer, size);
213 }
214 
215 Packet::Packet (const Buffer &buffer, const ByteTagList &byteTagList,
216  const PacketTagList &packetTagList, const PacketMetadata &metadata)
217  : m_buffer (buffer),
218  m_byteTagList (byteTagList),
219  m_packetTagList (packetTagList),
220  m_metadata (metadata),
221  m_nixVector (0)
222 {
223 }
224 
226 Packet::CreateFragment (uint32_t start, uint32_t length) const
227 {
228  NS_LOG_FUNCTION (this << start << length);
229  Buffer buffer = m_buffer.CreateFragment (start, length);
230  NS_ASSERT (m_buffer.GetSize () >= start + length);
231  uint32_t end = m_buffer.GetSize () - (start + length);
232  PacketMetadata metadata = m_metadata.CreateFragment (start, end);
233  // again, call the constructor directly rather than
234  // through Create because it is private.
235  return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
236 }
237 
238 void
240 {
241  m_nixVector = nixVector;
242 }
243 
246 {
247  return m_nixVector;
248 }
249 
250 void
251 Packet::AddHeader (const Header &header)
252 {
253  uint32_t size = header.GetSerializedSize ();
254  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << size);
255  uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
256  bool resized = m_buffer.AddAtStart (size);
257  if (resized)
258  {
260  m_buffer.GetCurrentStartOffset () + size);
261  }
262  header.Serialize (m_buffer.Begin ());
263  m_metadata.AddHeader (header, size);
264 }
265 uint32_t
267 {
268  uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
269  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
270  m_buffer.RemoveAtStart (deserialized);
271  m_metadata.RemoveHeader (header, deserialized);
272  return deserialized;
273 }
274 uint32_t
275 Packet::PeekHeader (Header &header) const
276 {
277  uint32_t deserialized = header.Deserialize (m_buffer.Begin ());
278  NS_LOG_FUNCTION (this << header.GetInstanceTypeId ().GetName () << deserialized);
279  return deserialized;
280 }
281 void
282 Packet::AddTrailer (const Trailer &trailer)
283 {
284  uint32_t size = trailer.GetSerializedSize ();
285  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << size);
286  uint32_t orgStart = m_buffer.GetCurrentStartOffset ();
287  bool resized = m_buffer.AddAtEnd (size);
288  if (resized)
289  {
291  m_buffer.GetCurrentEndOffset () - size);
292  }
293  Buffer::Iterator end = m_buffer.End ();
294  trailer.Serialize (end);
295  m_metadata.AddTrailer (trailer, size);
296 }
297 uint32_t
299 {
300  uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
301  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
302  m_buffer.RemoveAtEnd (deserialized);
303  m_metadata.RemoveTrailer (trailer, deserialized);
304  return deserialized;
305 }
306 uint32_t
308 {
309  uint32_t deserialized = trailer.Deserialize (m_buffer.End ());
310  NS_LOG_FUNCTION (this << trailer.GetInstanceTypeId ().GetName () << deserialized);
311  return deserialized;
312 }
313 
314 void
316 {
317  NS_LOG_FUNCTION (this << packet << packet->GetSize ());
318  uint32_t aStart = m_buffer.GetCurrentStartOffset ();
319  uint32_t bEnd = packet->m_buffer.GetCurrentEndOffset ();
320  m_buffer.AddAtEnd (packet->m_buffer);
321  uint32_t appendPrependOffset = m_buffer.GetCurrentEndOffset () - packet->m_buffer.GetSize ();
323  appendPrependOffset);
324  ByteTagList copy = packet->m_byteTagList;
325  copy.AddAtStart (m_buffer.GetCurrentEndOffset () - bEnd,
326  appendPrependOffset);
327  m_byteTagList.Add (copy);
328  m_metadata.AddAtEnd (packet->m_metadata);
329 }
330 void
331 Packet::AddPaddingAtEnd (uint32_t size)
332 {
333  NS_LOG_FUNCTION (this << size);
334  uint32_t orgEnd = m_buffer.GetCurrentEndOffset ();
335  bool resized = m_buffer.AddAtEnd (size);
336  if (resized)
337  {
339  m_buffer.GetCurrentEndOffset () - size);
340  }
342 }
343 void
344 Packet::RemoveAtEnd (uint32_t size)
345 {
346  NS_LOG_FUNCTION (this << size);
347  m_buffer.RemoveAtEnd (size);
348  m_metadata.RemoveAtEnd (size);
349 }
350 void
351 Packet::RemoveAtStart (uint32_t size)
352 {
353  NS_LOG_FUNCTION (this << size);
354  m_buffer.RemoveAtStart (size);
355  m_metadata.RemoveAtStart (size);
356 }
357 
358 void
360 {
361  NS_LOG_FUNCTION (this);
363 }
364 
365 uint8_t const *
366 Packet::PeekData (void) const
367 {
368  NS_LOG_FUNCTION (this);
369  uint32_t oldStart = m_buffer.GetCurrentStartOffset ();
370  uint8_t const * data = m_buffer.PeekData ();
371  uint32_t newStart = m_buffer.GetCurrentStartOffset ();
372 
373  // Update tag offsets if buffer offsets were changed
374  const_cast<ByteTagList &>(m_byteTagList).AddAtStart (newStart - oldStart, newStart);
375  return data;
376 }
377 
378 uint32_t
379 Packet::CopyData (uint8_t *buffer, uint32_t size) const
380 {
381  return m_buffer.CopyData (buffer, size);
382 }
383 
384 void
385 Packet::CopyData (std::ostream *os, uint32_t size) const
386 {
387  return m_buffer.CopyData (os, size);
388 }
389 
390 uint64_t
391 Packet::GetUid (void) const
392 {
393  return m_metadata.GetUid ();
394 }
395 
396 void
397 Packet::PrintByteTags (std::ostream &os) const
398 {
400  while (i.HasNext ())
401  {
402  ByteTagIterator::Item item = i.Next ();
403  os << item.GetTypeId ().GetName () << " [" << item.GetStart () << "-" << item.GetEnd () << "]";
404  Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
405  if (constructor.IsNull ())
406  {
407  if (i.HasNext ())
408  {
409  os << " ";
410  }
411  continue;
412  }
413  Tag *tag = dynamic_cast<Tag *> (constructor ());
414  NS_ASSERT (tag != 0);
415  os << " ";
416  item.GetTag (*tag);
417  tag->Print (os);
418  if (i.HasNext ())
419  {
420  os << " ";
421  }
422  delete tag;
423  }
424 }
425 
426 void
427 Packet::Print (std::ostream &os) const
428 {
430  while (i.HasNext ())
431  {
432  PacketMetadata::Item item = i.Next ();
433  if (item.isFragment)
434  {
435  switch (item.type) {
437  os << "Payload";
438  break;
441  os << item.tid.GetName ();
442  break;
443  }
444  os << " Fragment [" << item.currentTrimedFromStart<<":"
445  << (item.currentTrimedFromStart + item.currentSize) << "]";
446  }
447  else
448  {
449  switch (item.type) {
451  os << "Payload (size=" << item.currentSize << ")";
452  break;
455  os << item.tid.GetName () << " (";
456  {
457  NS_ASSERT (item.tid.HasConstructor ());
458  Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
459  NS_ASSERT (!constructor.IsNull ());
460  ObjectBase *instance = constructor ();
461  NS_ASSERT (instance != 0);
462  Chunk *chunk = dynamic_cast<Chunk *> (instance);
463  NS_ASSERT (chunk != 0);
464  chunk->Deserialize (item.current);
465  chunk->Print (os);
466  delete chunk;
467  }
468  os << ")";
469  break;
470  }
471  }
472  if (i.HasNext ())
473  {
474  os << " ";
475  }
476  }
477 #if 0
478  // The code below will work only if headers and trailers
479  // define the right attributes which is not the case for
480  // now. So, as a temporary measure, we use the
481  // headers' and trailers' Print method as shown above.
483  while (i.HasNext ())
484  {
485  PacketMetadata::Item item = i.Next ();
486  if (item.isFragment)
487  {
488  switch (item.type) {
490  os << "Payload";
491  break;
494  os << item.tid.GetName ();
495  break;
496  }
497  os << " Fragment [" << item.currentTrimedFromStart<<":"
498  << (item.currentTrimedFromStart + item.currentSize) << "]";
499  }
500  else
501  {
502  switch (item.type) {
504  os << "Payload (size=" << item.currentSize << ")";
505  break;
508  os << item.tid.GetName () << "(";
509  {
510  NS_ASSERT (item.tid.HasConstructor ());
511  Callback<ObjectBase *> constructor = item.tid.GetConstructor ();
512  NS_ASSERT (constructor.IsNull ());
513  ObjectBase *instance = constructor ();
514  NS_ASSERT (instance != 0);
515  Chunk *chunk = dynamic_cast<Chunk *> (instance);
516  NS_ASSERT (chunk != 0);
517  chunk->Deserialize (item.current);
518  for (uint32_t j = 0; j < item.tid.GetAttributeN (); j++)
519  {
520  std::string attrName = item.tid.GetAttributeName (j);
521  std::string value;
522  bool ok = chunk->GetAttribute (attrName, value);
523  NS_ASSERT (ok);
524  os << attrName << "=" << value;
525  if ((j + 1) < item.tid.GetAttributeN ())
526  {
527  os << ",";
528  }
529  }
530  }
531  os << ")";
532  break;
533  }
534  }
535  if (i.HasNext ())
536  {
537  os << " ";
538  }
539  }
540 #endif
541 }
542 
544 Packet::BeginItem (void) const
545 {
546  return m_metadata.BeginItem (m_buffer);
547 }
548 
549 void
551 {
554 }
555 
556 void
558 {
561 }
562 
563 uint32_t Packet::GetSerializedSize (void) const
564 {
565  uint32_t size = 0;
566 
567  if (m_nixVector)
568  {
569  // increment total size by the size of the nix-vector
570  // ensuring 4-byte boundary
571  size += ((m_nixVector->GetSerializedSize () + 3) & (~3));
572 
573  // add 4-bytes for entry of total length of nix-vector
574  size += 4;
575  }
576  else
577  {
578  // if no nix-vector, still have to add 4-bytes
579  // to account for the entry of total size for
580  // nix-vector in the buffer
581  size += 4;
582  }
583 
584  //Tag size
585  //XXX
586  //size += m_tags.GetSerializedSize ();
587 
588  // increment total size by size of meta-data
589  // ensuring 4-byte boundary
590  size += ((m_metadata.GetSerializedSize () + 3) & (~3));
591 
592  // add 4-bytes for entry of total length of meta-data
593  size += 4;
594 
595  // increment total size by size of buffer
596  // ensuring 4-byte boundary
597  size += ((m_buffer.GetSerializedSize () + 3) & (~3));
598 
599  // add 4-bytes for entry of total length of buffer
600  size += 4;
601 
602  return size;
603 }
604 
605 uint32_t
606 Packet::Serialize (uint8_t* buffer, uint32_t maxSize) const
607 {
608  uint32_t* p = reinterpret_cast<uint32_t *> (buffer);
609  uint32_t size = 0;
610 
611  // if nix-vector exists, serialize it
612  if (m_nixVector)
613  {
614  uint32_t nixSize = m_nixVector->GetSerializedSize ();
615  if (size + nixSize <= maxSize)
616  {
617  // put the total length of nix-vector in the
618  // buffer. this includes 4-bytes for total
619  // length itself
620  *p++ = nixSize + 4;
621  size += nixSize;
622 
623  // serialize the nix-vector
624  uint32_t serialized =
625  m_nixVector->Serialize (p, nixSize);
626  if (serialized)
627  {
628  // increment p by nixSize bytes
629  // ensuring 4-byte boundary
630  p += ((nixSize+3) & (~3)) / 4;
631  }
632  else
633  {
634  return 0;
635  }
636  }
637  else
638  {
639  return 0;
640  }
641  }
642  else
643  {
644  // no nix vector, set zero length,
645  // ie 4-bytes, since it must include
646  // length for itself
647  if (size + 4 <= maxSize)
648  {
649  size += 4;
650  *p++ = 4;
651  }
652  else
653  {
654  return 0;
655  }
656  }
657 
658  // Serialize Tags
659  // XXX
660 
661  // Serialize Metadata
662  uint32_t metaSize = m_metadata.GetSerializedSize ();
663  if (size + metaSize <= maxSize)
664  {
665  // put the total length of metadata in the
666  // buffer. this includes 4-bytes for total
667  // length itself
668  *p++ = metaSize + 4;
669  size += metaSize;
670 
671  // serialize the metadata
672  uint32_t serialized =
673  m_metadata.Serialize (reinterpret_cast<uint8_t *> (p), metaSize);
674  if (serialized)
675  {
676  // increment p by metaSize bytes
677  // ensuring 4-byte boundary
678  p += ((metaSize+3) & (~3)) / 4;
679  }
680  else
681  {
682  return 0;
683  }
684  }
685  else
686  {
687  return 0;
688  }
689 
690  // Serialize the packet contents
691  uint32_t bufSize = m_buffer.GetSerializedSize ();
692  if (size + bufSize <= maxSize)
693  {
694  // put the total length of the buffer in the
695  // buffer. this includes 4-bytes for total
696  // length itself
697  *p++ = bufSize + 4;
698  size += bufSize;
699 
700  // serialize the buffer
701  uint32_t serialized =
702  m_buffer.Serialize (reinterpret_cast<uint8_t *> (p), bufSize);
703  if (serialized)
704  {
705  // increment p by bufSize bytes
706  // ensuring 4-byte boundary
707  p += ((bufSize+3) & (~3)) / 4;
708  }
709  else
710  {
711  return 0;
712  }
713  }
714  else
715  {
716  return 0;
717  }
718 
719  // Serialized successfully
720  return 1;
721 }
722 
723 uint32_t
724 Packet::Deserialize (const uint8_t* buffer, uint32_t size)
725 {
726  NS_LOG_FUNCTION (this);
727 
728  const uint32_t* p = reinterpret_cast<const uint32_t *> (buffer);
729 
730  // read nix-vector
732  uint32_t nixSize = *p++;
733 
734  // if size less than nixSize, the buffer
735  // will be overrun, assert
736  NS_ASSERT (size >= nixSize);
737 
738  size -= nixSize;
739 
740  if (nixSize > 4)
741  {
742  Ptr<NixVector> nix = Create<NixVector> ();
743  uint32_t nixDeserialized = nix->Deserialize (p, nixSize);
744  if (!nixDeserialized)
745  {
746  // nix-vector not deserialized
747  // completely
748  return 0;
749  }
750  m_nixVector = nix;
751  // increment p by nixSize ensuring
752  // 4-byte boundary
753  p += ((((nixSize - 4) + 3) & (~3)) / 4);
754  }
755 
756  // read tags
757  //XXX
758  //uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
759  //buffer.RemoveAtStart (tagsDeserialized);
760 
761  // read metadata
762  uint32_t metaSize = *p++;
763 
764  // if size less than metaSize, the buffer
765  // will be overrun, assert
766  NS_ASSERT (size >= metaSize);
767 
768  size -= metaSize;
769 
770  uint32_t metadataDeserialized =
771  m_metadata.Deserialize (reinterpret_cast<const uint8_t *> (p), metaSize);
772  if (!metadataDeserialized)
773  {
774  // meta-data not deserialized
775  // completely
776  return 0;
777  }
778  // increment p by metaSize ensuring
779  // 4-byte boundary
780  p += ((((metaSize - 4) + 3) & (~3)) / 4);
781 
782  // read buffer contents
783  uint32_t bufSize = *p++;
784 
785  // if size less than bufSize, the buffer
786  // will be overrun, assert
787  NS_ASSERT (size >= bufSize);
788 
789  size -= bufSize;
790 
791  uint32_t bufferDeserialized =
792  m_buffer.Deserialize (reinterpret_cast<const uint8_t *> (p), bufSize);
793  if (!bufferDeserialized)
794  {
795  // buffer not deserialized
796  // completely
797  return 0;
798  }
799 
800  // return zero if did not deserialize the
801  // number of expected bytes
802  return (size == 0);
803 }
804 
805 void
806 Packet::AddByteTag (const Tag &tag) const
807 {
808  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
809  ByteTagList *list = const_cast<ByteTagList *> (&m_byteTagList);
810  TagBuffer buffer = list->Add (tag.GetInstanceTypeId (), tag.GetSerializedSize (),
813  tag.Serialize (buffer);
814 }
817 {
819 }
820 
821 bool
823 {
824  TypeId tid = tag.GetInstanceTypeId ();
826  while (i.HasNext ())
827  {
828  ByteTagIterator::Item item = i.Next ();
829  if (tid == item.GetTypeId ())
830  {
831  item.GetTag (tag);
832  return true;
833  }
834  }
835  return false;
836 }
837 
838 void
839 Packet::AddPacketTag (const Tag &tag) const
840 {
841  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
842  m_packetTagList.Add (tag);
843 }
844 bool
846 {
847  NS_LOG_FUNCTION (this << tag.GetInstanceTypeId ().GetName () << tag.GetSerializedSize ());
848  bool found = m_packetTagList.Remove (tag);
849  return found;
850 }
851 bool
853 {
854  bool found = m_packetTagList.Peek (tag);
855  return found;
856 }
857 void
859 {
860  NS_LOG_FUNCTION (this);
862 }
863 
864 void
865 Packet::PrintPacketTags (std::ostream &os) const
866 {
868  while (i.HasNext ())
869  {
870  PacketTagIterator::Item item = i.Next ();
871  NS_ASSERT (item.GetTypeId ().HasConstructor ());
872  Callback<ObjectBase *> constructor = item.GetTypeId ().GetConstructor ();
873  NS_ASSERT (!constructor.IsNull ());
874  ObjectBase *instance = constructor ();
875  Tag *tag = dynamic_cast<Tag *> (instance);
876  NS_ASSERT (tag != 0);
877  item.GetTag (*tag);
878  tag->Print (os);
879  delete tag;
880  if (i.HasNext ())
881  {
882  os << " ";
883  }
884  }
885 }
886 
889 {
891 }
892 
893 std::ostream& operator<< (std::ostream& os, const Packet &packet)
894 {
895  packet.Print (os);
896  return os;
897 }
898 
899 } // namespace ns3