src/common/packet.h
changeset 1136 d5fe8364bcdf
parent 1132 de8ccffc8485
child 1138 27245d50e5e0
equal deleted inserted replaced
1135:39ed8ebc1635 1136:d5fe8364bcdf
    68  * a public method named GetUid, as documented in the ns3::Header and ns::Trailer
    68  * a public method named GetUid, as documented in the ns3::Header and ns::Trailer
    69  * API documentations.
    69  * API documentations.
    70  *
    70  *
    71  * Implementing a new type of Tag requires roughly the same amount of
    71  * Implementing a new type of Tag requires roughly the same amount of
    72  * work: users must implement a total of 6 methods which are described in
    72  * work: users must implement a total of 6 methods which are described in
    73  * the ns3::Tags API documentation.
    73  * \ref tags
    74  *
    74  *
       
    75  * The performance aspects of the Packet API are discussed in 
       
    76  * \ref packetperf
       
    77  */
       
    78 class Packet {
       
    79 public:
       
    80   /**
       
    81    * Create an empty packet with a new uid (as returned
       
    82    * by getUid).
       
    83    */
       
    84   Packet ();
       
    85   /**
       
    86    * Create a packet with a zero-filled payload.
       
    87    * The memory necessary for the payload is not allocated:
       
    88    * it will be allocated at any later point if you attempt
       
    89    * to fragment this packet or to access the zero-filled
       
    90    * bytes. The packet is allocated with a new uid (as 
       
    91    * returned by getUid).
       
    92    * 
       
    93    * \param size the size of the zero-filled payload
       
    94    */
       
    95   Packet (uint32_t size);
       
    96   /**
       
    97    * Create a packet with payload filled with the content
       
    98    * of this buffer. The input data is copied: the input
       
    99    * buffer is untouched.
       
   100    *
       
   101    * \param buffer the data to store in the packet.
       
   102    * \param size the size of the input buffer.
       
   103    */
       
   104   Packet (uint8_t const*buffer, uint32_t size);
       
   105   /**
       
   106    * Create a new packet which contains a fragment of the original
       
   107    * packet. The returned packet shares the same uid as this packet.
       
   108    *
       
   109    * \param start offset from start of packet to start of fragment to create
       
   110    * \param length length of fragment to create
       
   111    * \returns a fragment of the original packet
       
   112    */
       
   113   Packet CreateFragment (uint32_t start, uint32_t length) const;
       
   114   /**
       
   115    * \returns the size in bytes of the packet (including the zero-filled
       
   116    *          initial payload)
       
   117    */
       
   118   uint32_t GetSize (void) const;
       
   119   /**
       
   120    * Add header to this packet. This method invokes the
       
   121    * ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo 
       
   122    * methods to reserve space in the buffer and request the 
       
   123    * header to serialize itself in the packet buffer.
       
   124    *
       
   125    * \param header a reference to the header to add to this packet.
       
   126    */
       
   127   template <typename T>
       
   128   void AddHeader (T const &header);
       
   129   /**
       
   130    * Deserialize and remove the header from the internal buffer.
       
   131    * This method invokes ns3::Chunk::DeserializeFrom.
       
   132    *
       
   133    * \param header a reference to the header to remove from the internal buffer.
       
   134    * \returns the number of bytes removed from the packet.
       
   135    */
       
   136   template <typename T>
       
   137   uint32_t RemoveHeader (T &header);
       
   138   /**
       
   139    * Add trailer to this packet. This method invokes the
       
   140    * ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo 
       
   141    * methods to reserve space in the buffer and request the trailer 
       
   142    * to serialize itself in the packet buffer.
       
   143    *
       
   144    * \param trailer a reference to the trailer to add to this packet.
       
   145    */
       
   146   template <typename T>
       
   147   void AddTrailer (T const &trailer);
       
   148   /**
       
   149    * Remove a deserialized trailer from the internal buffer.
       
   150    * This method invokes the ns3::Chunk::DeserializeFrom method.
       
   151    *
       
   152    * \param trailer a reference to the trailer to remove from the internal buffer.
       
   153    * \returns the number of bytes removed from the end of the packet.
       
   154    */
       
   155   template <typename T>
       
   156   uint32_t RemoveTrailer (T &trailer);
       
   157   /**
       
   158    * Attach a tag to this packet. The tag is fully copied
       
   159    * in a packet-specific internal buffer. This operation 
       
   160    * is expected to be really fast.
       
   161    *
       
   162    * \param tag a pointer to the tag to attach to this packet.
       
   163    */
       
   164   template <typename T>
       
   165   void AddTag (T const &tag);
       
   166   /**
       
   167    * Remove a tag from this packet. The data stored internally
       
   168    * for this tag is copied in the input tag if an instance
       
   169    * of this tag type is present in the internal buffer. If this
       
   170    * tag type is not present, the input tag is not modified. 
       
   171    *
       
   172    * This operation can be potentially slow and might trigger
       
   173    * unexpectedly large memory allocations. It is thus
       
   174    * usually a better idea to create a copy of this packet,
       
   175    * and invoke removeAllTags on the copy to remove all 
       
   176    * tags rather than remove the tags one by one from a packet.
       
   177    *
       
   178    * \param tag a pointer to the tag to remove from this packet
       
   179    * \returns true if an instance of this tag type is stored
       
   180    *          in this packet, false otherwise.
       
   181    */
       
   182   template <typename T>
       
   183   bool RemoveTag (T &tag);
       
   184   /**
       
   185    * Copy a tag stored internally to the input tag. If no instance
       
   186    * of this tag is present internally, the input tag is not modified.
       
   187    *
       
   188    * \param tag a pointer to the tag to read from this packet
       
   189    * \returns true if an instance of this tag type is stored
       
   190    *          in this packet, false otherwise.
       
   191    */
       
   192   template <typename T>
       
   193   bool PeekTag (T &tag) const;
       
   194   /**
       
   195    * Remove all the tags stored in this packet. This operation is
       
   196    * much much faster than invoking removeTag n times.
       
   197    */
       
   198   void RemoveAllTags (void);
       
   199   /**
       
   200    * Concatenate the input packet at the end of the current
       
   201    * packet. This does not alter the uid of either packet.
       
   202    *
       
   203    * \param packet packet to concatenate
       
   204    */
       
   205   void AddAtEnd (Packet packet);
       
   206   /**
       
   207    * \param size number of padding bytes to add.
       
   208    */
       
   209   void AddPaddingAtEnd (uint32_t size);
       
   210   /** 
       
   211    * Remove size bytes from the end of the current packet
       
   212    * It is safe to remove more bytes that what is present in
       
   213    * the packet.
       
   214    *
       
   215    * \param size number of bytes from remove
       
   216    */
       
   217   void RemoveAtEnd (uint32_t size);
       
   218   /** 
       
   219    * Remove size bytes from the start of the current packet.
       
   220    * It is safe to remove more bytes that what is present in
       
   221    * the packet.
       
   222    *
       
   223    * \param size number of bytes from remove
       
   224    */
       
   225   void RemoveAtStart (uint32_t size);
       
   226   
       
   227   /**
       
   228    * If you try to change the content of the buffer
       
   229    * returned by this method, you will die.
       
   230    *
       
   231    * \returns a pointer to the internal buffer of the packet.
       
   232    */
       
   233   uint8_t const *PeekData (void) const;
       
   234 
       
   235   /**
       
   236    * A packet is allocated a new uid when it is created
       
   237    * empty or with zero-filled payload.
       
   238    *
       
   239    * \returns an integer identifier which uniquely
       
   240    *          identifies this packet.
       
   241    */
       
   242   uint32_t GetUid (void) const;
       
   243 
       
   244   /**
       
   245    * \param os output stream in which the data should be printed.
       
   246    *
       
   247    * Iterate over the headers and trailers present in this packet, 
       
   248    * from the first header to the last trailer and invoke, for
       
   249    * each of them, the user-provided method Header::DoPrint or 
       
   250    * Trailer::DoPrint methods.
       
   251    */
       
   252   void Print (std::ostream &os) const;
       
   253   /**
       
   254    * \param os output stream in which the data should be printed.
       
   255    * \param printer the output formatter to use to print
       
   256    *        the content of this packet.
       
   257    *
       
   258    * Iterate over the headers and trailers present in this packet,
       
   259    * either in the "forward" (first header to last trailer) or in
       
   260    * the "backward" (last trailer to first header) direction, as
       
   261    * specified by the PacketPrinter::PrintForward or the
       
   262    * PacketPrinter::PrintBackward methods. For each header, trailer,
       
   263    * or fragment of a header or a trailer, invoke the user-specified
       
   264    * print callback stored in the specified PacketPrinter.
       
   265    */
       
   266   void Print (std::ostream &os, const PacketPrinter &printer) const;
       
   267 
       
   268   /**
       
   269    * By default, packets do not keep around enough metadata to
       
   270    * perform the operations requested by the Print methods. If you
       
   271    * want to be able to invoke any of the two ::Print methods, 
       
   272    * you need to invoke this method at least once during the 
       
   273    * simulation setup and before any packet is created.
       
   274    *
       
   275    * The packet metadata is also used to perform extensive
       
   276    * sanity checks at runtime when performing operations on a 
       
   277    * Packet. For example, this metadata is used to verify that
       
   278    * when you remove a header from a packet, this same header
       
   279    * was actually present at the front of the packet. These
       
   280    * errors will be detected and will abort the program.
       
   281    */
       
   282   static void EnableMetadata (void);
       
   283 private:
       
   284   Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
       
   285   Buffer m_buffer;
       
   286   Tags m_tags;
       
   287   PacketMetadata m_metadata;
       
   288   static uint32_t m_globalUid;
       
   289 };
       
   290 
       
   291 /**
       
   292  * \defgroup tags Packet Tags
       
   293  *
       
   294  * A tag is a class which must define:
       
   295  *  - a public default constructor
       
   296  *  - a public static method named GetUid
       
   297  *  - a public method named Print
       
   298  *  - a public method named GetSerializedSize
       
   299  *  - a public method named Serialize
       
   300  *  - a public method named Deserialize
       
   301  *
       
   302  * So, a tag class should look like this:
       
   303  * \code
       
   304  * // note how a tag class does not derive from any other class.
       
   305  * class MyTag 
       
   306  * {
       
   307  * public:
       
   308  *   // we need a public default constructor
       
   309  *   MyTag ();
       
   310  *   // we need a public static GetUid
       
   311  *   // GetUid must return a string which uniquely
       
   312  *   // identifies this tag type
       
   313  *   static std::string GetUid (void);
       
   314  *   // Print should record in the output stream
       
   315  *   // the content of the tag instance.
       
   316  *   void Print (std::ostream &os) const;
       
   317  *   // GetSerializedSize should return the number of bytes needed
       
   318  *   // to store the state of a tag instance
       
   319  *   uint32_t GetSerializedSize (void) const;
       
   320  *   // Serialize should store its state in the input
       
   321  *   // buffer with the help of the iterator. It should
       
   322  *   // write exactly size bytes.
       
   323  *   void Serialize (Buffer::Iterator i, uint32_t size) const;
       
   324  *   // Deserialize should restore the state of a Tag instance
       
   325  *   // from a byte buffer with the help of the iterator
       
   326  *   uint32_t Deserialize (Buffer::Iterator i);
       
   327  * };
       
   328  *
       
   329  * std::string MyTag::GetUid (void)
       
   330  * {
       
   331  *   // we really want to make sure that this
       
   332  *   // string is unique in the universe.
       
   333  *   return "MyTag.unique.prefix";
       
   334  * }
       
   335  * \endcode
       
   336  */
       
   337 
       
   338 /**
       
   339  * \defgroup packetperf Packet Performance
    75  * The current implementation of the byte buffers and tag list is based
   340  * The current implementation of the byte buffers and tag list is based
    76  * on COW (Copy On Write. An introduction to COW can be found in Scott 
   341  * on COW (Copy On Write. An introduction to COW can be found in Scott 
    77  * Meyer's "More Effective C++", items 17 and 29). What this means is that
   342  * Meyer's "More Effective C++", items 17 and 29). What this means is that
    78  * copying packets without modifying them is very cheap (in terms of cpu
   343  * copying packets without modifying them is very cheap (in terms of cpu
    79  * and memory usage) and modifying them can be also very cheap. What is 
   344  * and memory usage) and modifying them can be also very cheap. What is 
   102  * sometimes by several orders of magnitude. However, even the
   367  * sometimes by several orders of magnitude. However, even the
   103  * dirty operations have been optimized for common use-cases which
   368  * dirty operations have been optimized for common use-cases which
   104  * means that most of the time, these operations will not trigger
   369  * means that most of the time, these operations will not trigger
   105  * data copies and will thus be still very fast.
   370  * data copies and will thus be still very fast.
   106  */
   371  */
   107 class Packet {
   372 
   108 public:
   373 } // namespace ns3
   109   /**
       
   110    * Create an empty packet with a new uid (as returned
       
   111    * by getUid).
       
   112    */
       
   113   Packet ();
       
   114   /**
       
   115    * Create a packet with a zero-filled payload.
       
   116    * The memory necessary for the payload is not allocated:
       
   117    * it will be allocated at any later point if you attempt
       
   118    * to fragment this packet or to access the zero-filled
       
   119    * bytes. The packet is allocated with a new uid (as 
       
   120    * returned by getUid).
       
   121    * 
       
   122    * \param size the size of the zero-filled payload
       
   123    */
       
   124   Packet (uint32_t size);
       
   125   /**
       
   126    * Create a packet with payload filled with the content
       
   127    * of this buffer. The input data is copied: the input
       
   128    * buffer is untouched.
       
   129    *
       
   130    * \param buffer the data to store in the packet.
       
   131    * \param size the size of the input buffer.
       
   132    */
       
   133   Packet (uint8_t const*buffer, uint32_t size);
       
   134   /**
       
   135    * Create a new packet which contains a fragment of the original
       
   136    * packet. The returned packet shares the same uid as this packet.
       
   137    *
       
   138    * \param start offset from start of packet to start of fragment to create
       
   139    * \param length length of fragment to create
       
   140    * \returns a fragment of the original packet
       
   141    */
       
   142   Packet CreateFragment (uint32_t start, uint32_t length) const;
       
   143   /**
       
   144    * \returns the size in bytes of the packet (including the zero-filled
       
   145    *          initial payload)
       
   146    */
       
   147   uint32_t GetSize (void) const;
       
   148   /**
       
   149    * Add header to this packet. This method invokes the
       
   150    * ns3::Chunk::GetSerializedSize and ns3::Chunk::SerializeTo 
       
   151    * methods to reserve space in the buffer and request the 
       
   152    * header to serialize itself in the packet buffer.
       
   153    *
       
   154    * \param header a reference to the header to add to this packet.
       
   155    */
       
   156   template <typename T>
       
   157   void AddHeader (T const &header);
       
   158   /**
       
   159    * Deserialize and remove the header from the internal buffer.
       
   160    * This method invokes ns3::Chunk::DeserializeFrom.
       
   161    *
       
   162    * \param header a reference to the header to remove from the internal buffer.
       
   163    * \returns the number of bytes removed from the packet.
       
   164    */
       
   165   template <typename T>
       
   166   uint32_t RemoveHeader (T &header);
       
   167   /**
       
   168    * Add trailer to this packet. This method invokes the
       
   169    * ns3::Chunk::GetSerializedSize and ns3::Trailer::serializeTo 
       
   170    * methods to reserve space in the buffer and request the trailer 
       
   171    * to serialize itself in the packet buffer.
       
   172    *
       
   173    * \param trailer a reference to the trailer to add to this packet.
       
   174    */
       
   175   template <typename T>
       
   176   void AddTrailer (T const &trailer);
       
   177   /**
       
   178    * Remove a deserialized trailer from the internal buffer.
       
   179    * This method invokes the ns3::Chunk::DeserializeFrom method.
       
   180    *
       
   181    * \param trailer a reference to the trailer to remove from the internal buffer.
       
   182    * \returns the number of bytes removed from the end of the packet.
       
   183    */
       
   184   template <typename T>
       
   185   uint32_t RemoveTrailer (T &trailer);
       
   186   /**
       
   187    * Attach a tag to this packet. The tag is fully copied
       
   188    * in a packet-specific internal buffer. This operation 
       
   189    * is expected to be really fast.
       
   190    *
       
   191    * \param tag a pointer to the tag to attach to this packet.
       
   192    */
       
   193   template <typename T>
       
   194   void AddTag (T const &tag);
       
   195   /**
       
   196    * Remove a tag from this packet. The data stored internally
       
   197    * for this tag is copied in the input tag if an instance
       
   198    * of this tag type is present in the internal buffer. If this
       
   199    * tag type is not present, the input tag is not modified. 
       
   200    *
       
   201    * This operation can be potentially slow and might trigger
       
   202    * unexpectedly large memory allocations. It is thus
       
   203    * usually a better idea to create a copy of this packet,
       
   204    * and invoke removeAllTags on the copy to remove all 
       
   205    * tags rather than remove the tags one by one from a packet.
       
   206    *
       
   207    * \param tag a pointer to the tag to remove from this packet
       
   208    * \returns true if an instance of this tag type is stored
       
   209    *          in this packet, false otherwise.
       
   210    */
       
   211   template <typename T>
       
   212   bool RemoveTag (T &tag);
       
   213   /**
       
   214    * Copy a tag stored internally to the input tag. If no instance
       
   215    * of this tag is present internally, the input tag is not modified.
       
   216    *
       
   217    * \param tag a pointer to the tag to read from this packet
       
   218    * \returns true if an instance of this tag type is stored
       
   219    *          in this packet, false otherwise.
       
   220    */
       
   221   template <typename T>
       
   222   bool PeekTag (T &tag) const;
       
   223   /**
       
   224    * Remove all the tags stored in this packet. This operation is
       
   225    * much much faster than invoking removeTag n times.
       
   226    */
       
   227   void RemoveAllTags (void);
       
   228   /**
       
   229    * Concatenate the input packet at the end of the current
       
   230    * packet. This does not alter the uid of either packet.
       
   231    *
       
   232    * \param packet packet to concatenate
       
   233    */
       
   234   void AddAtEnd (Packet packet);
       
   235   /**
       
   236    * \param size number of padding bytes to add.
       
   237    */
       
   238   void AddPaddingAtEnd (uint32_t size);
       
   239   /** 
       
   240    * Remove size bytes from the end of the current packet
       
   241    * It is safe to remove more bytes that what is present in
       
   242    * the packet.
       
   243    *
       
   244    * \param size number of bytes from remove
       
   245    */
       
   246   void RemoveAtEnd (uint32_t size);
       
   247   /** 
       
   248    * Remove size bytes from the start of the current packet.
       
   249    * It is safe to remove more bytes that what is present in
       
   250    * the packet.
       
   251    *
       
   252    * \param size number of bytes from remove
       
   253    */
       
   254   void RemoveAtStart (uint32_t size);
       
   255   
       
   256   /**
       
   257    * If you try to change the content of the buffer
       
   258    * returned by this method, you will die.
       
   259    *
       
   260    * \returns a pointer to the internal buffer of the packet.
       
   261    */
       
   262   uint8_t const *PeekData (void) const;
       
   263 
       
   264   /**
       
   265    * A packet is allocated a new uid when it is created
       
   266    * empty or with zero-filled payload.
       
   267    *
       
   268    * \returns an integer identifier which uniquely
       
   269    *          identifies this packet.
       
   270    */
       
   271   uint32_t GetUid (void) const;
       
   272 
       
   273   /**
       
   274    * \param os output stream in which the data should be printed.
       
   275    *
       
   276    * Iterate over the headers and trailers present in this packet, 
       
   277    * from the first header to the last trailer and invoke, for
       
   278    * each of them, the user-provided method Header::DoPrint or 
       
   279    * Trailer::DoPrint methods.
       
   280    */
       
   281   void Print (std::ostream &os) const;
       
   282   /**
       
   283    * \param os output stream in which the data should be printed.
       
   284    * \param printer the output formatter to use to print
       
   285    *        the content of this packet.
       
   286    *
       
   287    * Iterate over the headers and trailers present in this packet,
       
   288    * either in the "forward" (first header to last trailer) or in
       
   289    * the "backward" (last trailer to first header) direction, as
       
   290    * specified by the PacketPrinter::PrintForward or the
       
   291    * PacketPrinter::PrintBackward methods. For each header, trailer,
       
   292    * or fragment of a header or a trailer, invoke the user-specified
       
   293    * print callback stored in the specified PacketPrinter.
       
   294    */
       
   295   void Print (std::ostream &os, const PacketPrinter &printer) const;
       
   296 
       
   297   /**
       
   298    * By default, packets do not keep around enough metadata to
       
   299    * perform the operations requested by the Print methods. If you
       
   300    * want to be able to invoke any of the two ::Print methods, 
       
   301    * you need to invoke this method at least once during the 
       
   302    * simulation setup and before any packet is created.
       
   303    *
       
   304    * The packet metadata is also used to perform extensive
       
   305    * sanity checks at runtime when performing operations on a 
       
   306    * Packet. For example, this metadata is used to verify that
       
   307    * when you remove a header from a packet, this same header
       
   308    * was actually present at the front of the packet. These
       
   309    * errors will be detected and will abort the program.
       
   310    */
       
   311   static void EnableMetadata (void);
       
   312 private:
       
   313   Packet (Buffer buffer, Tags tags, PacketMetadata metadata);
       
   314   Buffer m_buffer;
       
   315   Tags m_tags;
       
   316   PacketMetadata m_metadata;
       
   317   static uint32_t m_globalUid;
       
   318 };
       
   319 
       
   320 }; // namespace ns3
       
   321 
   374 
   322 
   375 
   323 /**************************************************
   376 /**************************************************
   324   Start of implementation of templates defined
   377   Start of implementation of templates defined
   325   above
   378   above