src/common/packet.h
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu Nov 12 13:01:01 2009 +0100 (2009-11-12)
changeset 5505 c0ac392289c3
parent 5492 5718e4171536
child 5751 b50011dc95b1
permissions -rw-r--r--
replace RefCountBase with SimpleRefCount<> to avoid duplicate refcounting implementations.
mathieu@150
     1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
mathieu@9
     2
/*
mathieu@9
     3
 * Copyright (c) 2005,2006 INRIA
mathieu@9
     4
 *
mathieu@9
     5
 * This program is free software; you can redistribute it and/or modify
mathieu@9
     6
 * it under the terms of the GNU General Public License version 2 as
mathieu@9
     7
 * published by the Free Software Foundation;
mathieu@9
     8
 *
mathieu@9
     9
 * This program is distributed in the hope that it will be useful,
mathieu@9
    10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@9
    11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@9
    12
 * GNU General Public License for more details.
mathieu@9
    13
 *
mathieu@9
    14
 * You should have received a copy of the GNU General Public License
mathieu@9
    15
 * along with this program; if not, write to the Free Software
mathieu@9
    16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@9
    17
 *
mathieu@9
    18
 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
mathieu@9
    19
 */
mathieu@9
    20
#ifndef PACKET_H
mathieu@9
    21
#define PACKET_H
mathieu@9
    22
mathieu@9
    23
#include <stdint.h>
mathieu@9
    24
#include "buffer.h"
mathieu@104
    25
#include "header.h"
mathieu@107
    26
#include "trailer.h"
mathieu@882
    27
#include "packet-metadata.h"
mathieu@3041
    28
#include "tag.h"
mathieu@4502
    29
#include "byte-tag-list.h"
mathieu@4502
    30
#include "packet-tag-list.h"
jpelkey@5224
    31
#include "nix-vector.h"
mathieu@14
    32
#include "ns3/callback.h"
mathieu@463
    33
#include "ns3/assert.h"
mathieu@1865
    34
#include "ns3/ptr.h"
mathieu@9
    35
mathieu@16
    36
namespace ns3 {
mathieu@9
    37
mathieu@79
    38
/**
mathieu@3222
    39
 * \ingroup common
mathieu@3222
    40
 * \defgroup packet Packet
mathieu@3222
    41
 */
mathieu@3222
    42
mathieu@3222
    43
/**
mathieu@3222
    44
 * \ingroup packet
mathieu@3035
    45
 * \brief Iterator over the set of tags in a packet
mathieu@3036
    46
 *
mathieu@3036
    47
 * This is a java-style iterator.
mathieu@3035
    48
 */
mathieu@4502
    49
class ByteTagIterator
mathieu@3035
    50
{
mathieu@3035
    51
public:
mathieu@3035
    52
  /**
mathieu@3193
    53
   * Identifies a tag and a set of bytes within a packet
mathieu@3035
    54
   * to which the tag applies.
mathieu@3035
    55
   */
mathieu@3035
    56
  class Item
mathieu@3035
    57
  {
mathieu@3035
    58
  public:
mathieu@3035
    59
    /**
mathieu@3035
    60
     * \returns the ns3::TypeId associated to this tag.
mathieu@3035
    61
     */
mathieu@3035
    62
    TypeId GetTypeId (void) const;
mathieu@3035
    63
    /**
mathieu@3035
    64
     * \returns the index of the first byte tagged by this tag.
mathieu@3035
    65
     *
mathieu@3035
    66
     * The index is an offset from the start of the packet.
mathieu@3035
    67
     */
mathieu@3035
    68
    uint32_t GetStart (void) const;
mathieu@3035
    69
    /**
mathieu@3035
    70
     * \returns the index of the last byte tagged by this tag.
mathieu@3035
    71
     *
mathieu@3035
    72
     * The index is an offset from the start of the packet.
mathieu@3035
    73
     */
mathieu@3035
    74
    uint32_t GetEnd (void) const;
mathieu@3035
    75
    /**
mathieu@3035
    76
     * \param tag the user tag to which the data should be copied.
mathieu@3035
    77
     *
mathieu@3035
    78
     * Read the requested tag and store it in the user-provided
mathieu@3035
    79
     * tag instance. This method will crash if the type of the
mathieu@3035
    80
     * tag provided by the user does not match the type of
mathieu@3035
    81
     * the underlying tag.
mathieu@3035
    82
     */
mathieu@3040
    83
    void GetTag (Tag &tag) const;
mathieu@3035
    84
  private:
mathieu@4502
    85
    friend class ByteTagIterator;
mathieu@3040
    86
    Item (TypeId tid, uint32_t start, uint32_t end, TagBuffer buffer);
mathieu@3035
    87
    TypeId m_tid;
mathieu@3035
    88
    uint32_t m_start;
mathieu@3035
    89
    uint32_t m_end;
mathieu@3040
    90
    TagBuffer m_buffer;
mathieu@3035
    91
  };
mathieu@3036
    92
  /**
mathieu@3036
    93
   * \returns true if calling Next is safe, false otherwise.
mathieu@3036
    94
   */
mathieu@3035
    95
  bool HasNext (void) const;
mathieu@3036
    96
  /**
mathieu@3036
    97
   * \returns the next item found and prepare for the next one.
mathieu@3036
    98
   */
mathieu@3035
    99
  Item Next (void);
mathieu@3035
   100
private:
mathieu@3035
   101
  friend class Packet;
mathieu@4502
   102
  ByteTagIterator (ByteTagList::Iterator i);
mathieu@4502
   103
  ByteTagList::Iterator m_current;
mathieu@4502
   104
};
mathieu@4502
   105
mathieu@4502
   106
/**
mathieu@4502
   107
 * \ingroup packet
mathieu@4502
   108
 * \brief Iterator over the set of 'packet' tags in a packet
mathieu@4502
   109
 *
mathieu@4502
   110
 * This is a java-style iterator.
mathieu@4502
   111
 */
mathieu@4502
   112
class PacketTagIterator
mathieu@4502
   113
{
mathieu@4502
   114
public:
mathieu@4502
   115
  /**
mathieu@4502
   116
   * Identifies a tag within a packet.
mathieu@4502
   117
   */
mathieu@4502
   118
  class Item 
mathieu@4502
   119
  {
mathieu@4502
   120
  public:
mathieu@4502
   121
    /**
mathieu@4502
   122
     * \returns the ns3::TypeId associated to this tag.
mathieu@4502
   123
     */
mathieu@4502
   124
    TypeId GetTypeId (void) const;
mathieu@4502
   125
    /**
mathieu@4502
   126
     * \param tag the user tag to which the data should be copied.
mathieu@4502
   127
     *
mathieu@4502
   128
     * Read the requested tag and store it in the user-provided
mathieu@4502
   129
     * tag instance. This method will crash if the type of the
mathieu@4502
   130
     * tag provided by the user does not match the type of
mathieu@4502
   131
     * the underlying tag.
mathieu@4502
   132
     */
mathieu@4502
   133
    void GetTag (Tag &tag) const;
mathieu@4502
   134
  private:
mathieu@4502
   135
    friend class PacketTagIterator;
mathieu@4502
   136
    Item (const struct PacketTagList::TagData *data);
mathieu@4502
   137
    const struct PacketTagList::TagData *m_data;
mathieu@4502
   138
  };
mathieu@4502
   139
  /**
mathieu@4502
   140
   * \returns true if calling Next is safe, false otherwise.
mathieu@4502
   141
   */
mathieu@4502
   142
  bool HasNext (void) const;
mathieu@4502
   143
  /**
mathieu@4502
   144
   * \returns the next item found and prepare for the next one.
mathieu@4502
   145
   */
mathieu@4502
   146
  Item Next (void);
mathieu@4502
   147
private:
mathieu@4502
   148
  friend class Packet;
mathieu@4502
   149
  PacketTagIterator (const struct PacketTagList::TagData *head);
mathieu@4502
   150
  const struct PacketTagList::TagData *m_current;
mathieu@3035
   151
};
mathieu@3035
   152
mathieu@3035
   153
/**
mathieu@3222
   154
 * \ingroup packet
mathieu@79
   155
 * \brief network packets
mathieu@80
   156
 *
mathieu@4502
   157
 * Each network packet contains a byte buffer, a set of byte tags, a set of
mathieu@4502
   158
 * packet tags, and metadata.
mathieu@1131
   159
 *
mathieu@106
   160
 * - The byte buffer stores the serialized content of the headers and trailers 
mathieu@106
   161
 * added to a packet. The serialized representation of these headers is expected
mathieu@80
   162
 * to match that of real network packets bit for bit (although nothing
mathieu@80
   163
 * forces you to do this) which means that the content of a packet buffer
mathieu@80
   164
 * is expected to be that of a real packet.
mathieu@1131
   165
 *
mathieu@1131
   166
 * - The metadata describes the type of the headers and trailers which
mathieu@1131
   167
 * were serialized in the byte buffer. The maintenance of metadata is
mathieu@1131
   168
 * optional and disabled by default. To enable it, you must call
mathieu@4507
   169
 * Packet::EnablePrinting and this will allow you to get non-empty
mathieu@4507
   170
 * output from Packet::Print and Packet::Print. If you wish to only enable
mathieu@4507
   171
 * checking of metadata, and do not need any printing capability, you can
mathieu@4507
   172
 * call Packet::EnableChecking: its runtime cost is lower than Packet::EnablePrinting.
mathieu@1131
   173
 *
mathieu@4502
   174
 * - The set of tags contain simulation-specific information which cannot
mathieu@4502
   175
 * be stored in the packet byte buffer because the protocol headers or trailers
mathieu@4502
   176
 * have no standard-conformant field for this information. So-called
mathieu@4502
   177
 * 'byte' tags are used to tag a subset of the bytes in the packet byte buffer
mathieu@4502
   178
 * while 'packet' tags are used to tag the packet itself. The main difference
mathieu@4502
   179
 * between these two kinds of tags is what happens when packets are copied,
mathieu@4502
   180
 * fragmented, and reassembled: 'byte' tags follow bytes while 'packet' tags
mathieu@4503
   181
 * follow packets. Another important difference between these two kinds of tags
mathieu@4503
   182
 * is that byte tags cannot be removed and are expected to be written once,
mathieu@4503
   183
 * and read many times, while packet tags are expected to be written once,
mathieu@4503
   184
 * read many times, and removed exactly once. An example of a 'byte' 
mathieu@4503
   185
 * tag is a FlowIdTag which contains a flow id and is set by the application
mathieu@4503
   186
 * generating traffic. An example of a 'packet' tag is a cross-layer 
mathieu@4503
   187
 * qos class id set by an application and processed by a lower-level MAC 
mathieu@4503
   188
 * layer.
mathieu@4502
   189
 *
mathieu@1131
   190
 * Implementing a new type of Header or Trailer for a new protocol is 
mathieu@1131
   191
 * pretty easy and is a matter of creating a subclass of the ns3::Header 
mathieu@1246
   192
 * or of the ns3::Trailer base class, and implementing the methods
mathieu@1246
   193
 * described in their respective API documentation.
mathieu@1131
   194
 *
mathieu@1131
   195
 * Implementing a new type of Tag requires roughly the same amount of
mathieu@1246
   196
 * work and this work is described in the ns3::Tag API documentation.
mathieu@84
   197
 *
mathieu@1136
   198
 * The performance aspects of the Packet API are discussed in 
mathieu@1136
   199
 * \ref packetperf
mathieu@79
   200
 */
mathieu@5505
   201
class Packet : public SimpleRefCount<Packet>
mathieu@2630
   202
{
mathieu@9
   203
public:
mathieu@1865
   204
  Ptr<Packet> Copy (void) const;
mathieu@1865
   205
mathieu@150
   206
  /**
mathieu@150
   207
   * Create an empty packet with a new uid (as returned
mathieu@150
   208
   * by getUid).
mathieu@150
   209
   */
mathieu@150
   210
  Packet ();
mathieu@3046
   211
  Packet (const Packet &o);
mathieu@3046
   212
  Packet &operator = (const Packet &o);  
mathieu@150
   213
  /**
mathieu@150
   214
   * Create a packet with a zero-filled payload.
mathieu@150
   215
   * The memory necessary for the payload is not allocated:
mathieu@150
   216
   * it will be allocated at any later point if you attempt
mathieu@150
   217
   * to fragment this packet or to access the zero-filled
mathieu@150
   218
   * bytes. The packet is allocated with a new uid (as 
mathieu@150
   219
   * returned by getUid).
mathieu@150
   220
   * 
mathieu@150
   221
   * \param size the size of the zero-filled payload
mathieu@150
   222
   */
mathieu@150
   223
  Packet (uint32_t size);
mathieu@150
   224
  /**
mathieu@239
   225
   * Create a packet with payload filled with the content
mathieu@239
   226
   * of this buffer. The input data is copied: the input
mathieu@239
   227
   * buffer is untouched.
mathieu@239
   228
   *
mathieu@239
   229
   * \param buffer the data to store in the packet.
mathieu@239
   230
   * \param size the size of the input buffer.
mathieu@239
   231
   */
mathieu@239
   232
  Packet (uint8_t const*buffer, uint32_t size);
mathieu@239
   233
  /**
mathieu@150
   234
   * Create a new packet which contains a fragment of the original
mathieu@150
   235
   * packet. The returned packet shares the same uid as this packet.
mathieu@150
   236
   *
mathieu@150
   237
   * \param start offset from start of packet to start of fragment to create
mathieu@150
   238
   * \param length length of fragment to create
mathieu@150
   239
   * \returns a fragment of the original packet
mathieu@150
   240
   */
mathieu@1865
   241
  Ptr<Packet> CreateFragment (uint32_t start, uint32_t length) const;
mathieu@150
   242
  /**
mathieu@150
   243
   * \returns the size in bytes of the packet (including the zero-filled
mathieu@150
   244
   *          initial payload)
mathieu@150
   245
   */
mathieu@150
   246
  uint32_t GetSize (void) const;
mathieu@150
   247
  /**
mathieu@150
   248
   * Add header to this packet. This method invokes the
mathieu@3364
   249
   * Header::GetSerializedSize and Header::Serialize
mathieu@463
   250
   * methods to reserve space in the buffer and request the 
mathieu@463
   251
   * header to serialize itself in the packet buffer.
mathieu@150
   252
   *
mathieu@150
   253
   * \param header a reference to the header to add to this packet.
mathieu@150
   254
   */
mathieu@2663
   255
  void AddHeader (const Header & header);
mathieu@150
   256
  /**
mathieu@463
   257
   * Deserialize and remove the header from the internal buffer.
mathieu@3364
   258
   * This method invokes Header::Deserialize.
mathieu@150
   259
   *
mathieu@150
   260
   * \param header a reference to the header to remove from the internal buffer.
mathieu@463
   261
   * \returns the number of bytes removed from the packet.
mathieu@150
   262
   */
mathieu@2663
   263
  uint32_t RemoveHeader (Header &header);
mathieu@150
   264
  /**
mathieu@3364
   265
   * Deserialize but does _not_ remove the header from the internal buffer.
mathieu@3364
   266
   * This method invokes Header::Deserialize.
mathieu@3364
   267
   *
mathieu@3364
   268
   * \param header a reference to the header to read from the internal buffer.
mathieu@3364
   269
   * \returns the number of bytes read from the packet.
mathieu@3364
   270
   */  
mathieu@3738
   271
  uint32_t PeekHeader (Header &header) const;
mathieu@3364
   272
  /**
mathieu@150
   273
   * Add trailer to this packet. This method invokes the
mathieu@3364
   274
   * Trailer::GetSerializedSize and Trailer::Serialize
mathieu@463
   275
   * methods to reserve space in the buffer and request the trailer 
mathieu@463
   276
   * to serialize itself in the packet buffer.
mathieu@150
   277
   *
mathieu@150
   278
   * \param trailer a reference to the trailer to add to this packet.
mathieu@150
   279
   */
mathieu@2663
   280
  void AddTrailer (const Trailer &trailer);
mathieu@150
   281
  /**
mathieu@150
   282
   * Remove a deserialized trailer from the internal buffer.
mathieu@1246
   283
   * This method invokes the Deserialize method.
mathieu@150
   284
   *
mathieu@150
   285
   * \param trailer a reference to the trailer to remove from the internal buffer.
mathieu@463
   286
   * \returns the number of bytes removed from the end of the packet.
mathieu@150
   287
   */
mathieu@2663
   288
  uint32_t RemoveTrailer (Trailer &trailer);
mathieu@150
   289
  /**
mathieu@3364
   290
   * Deserialize but does _not_ remove a trailer from the internal buffer.
mathieu@3364
   291
   * This method invokes the Trailer::Deserialize method.
mathieu@3364
   292
   *
mathieu@3364
   293
   * \param trailer a reference to the trailer to read from the internal buffer.
mathieu@3364
   294
   * \returns the number of bytes read from the end of the packet.
mathieu@3364
   295
   */
mathieu@3364
   296
  uint32_t PeekTrailer (Trailer &trailer);
mathieu@1246
   297
mathieu@1246
   298
  /**
mathieu@150
   299
   * Concatenate the input packet at the end of the current
mathieu@150
   300
   * packet. This does not alter the uid of either packet.
mathieu@150
   301
   *
mathieu@150
   302
   * \param packet packet to concatenate
mathieu@150
   303
   */
mathieu@1865
   304
  void AddAtEnd (Ptr<const Packet> packet);
mathieu@150
   305
  /**
mathieu@463
   306
   * \param size number of padding bytes to add.
mathieu@150
   307
   */
mathieu@463
   308
  void AddPaddingAtEnd (uint32_t size);
mathieu@150
   309
  /** 
mathieu@150
   310
   * Remove size bytes from the end of the current packet
mathieu@150
   311
   * It is safe to remove more bytes that what is present in
mathieu@150
   312
   * the packet.
mathieu@150
   313
   *
mathieu@150
   314
   * \param size number of bytes from remove
mathieu@150
   315
   */
mathieu@150
   316
  void RemoveAtEnd (uint32_t size);
mathieu@150
   317
  /** 
mathieu@150
   318
   * Remove size bytes from the start of the current packet.
mathieu@150
   319
   * It is safe to remove more bytes that what is present in
mathieu@150
   320
   * the packet.
mathieu@150
   321
   *
mathieu@150
   322
   * \param size number of bytes from remove
mathieu@150
   323
   */
mathieu@150
   324
  void RemoveAtStart (uint32_t size);
mathieu@150
   325
  
mathieu@150
   326
  /**
mathieu@150
   327
   * If you try to change the content of the buffer
mathieu@150
   328
   * returned by this method, you will die.
mathieu@150
   329
   *
mathieu@150
   330
   * \returns a pointer to the internal buffer of the packet.
mathieu@150
   331
   */
mathieu@150
   332
  uint8_t const *PeekData (void) const;
mathieu@91
   333
mathieu@150
   334
  /**
mathieu@3764
   335
   * \param buffer a pointer to a byte buffer where the packet data 
mathieu@3764
   336
   *        should be copied.
mathieu@3764
   337
   * \param size the size of the byte buffer. 
mathieu@3764
   338
   * \returns the number of bytes read from the packet
mathieu@3764
   339
   *
mathieu@3764
   340
   * No more than \b size bytes will be copied by this function.
mathieu@3764
   341
   */
mathieu@3764
   342
  uint32_t CopyData (uint8_t *buffer, uint32_t size) const;
mathieu@3764
   343
mathieu@4518
   344
  void CopyData(std::ostream *os, uint32_t size) const;
mathieu@4518
   345
mathieu@3764
   346
  /**
mathieu@150
   347
   * A packet is allocated a new uid when it is created
mathieu@150
   348
   * empty or with zero-filled payload.
mathieu@150
   349
   *
tomh@1782
   350
   * Note: This uid is an internal uid and cannot be counted on to
tomh@1782
   351
   * provide an accurate counter of how many "simulated packets" of a
tomh@1782
   352
   * particular protocol are in the system. It is not trivial to make
tomh@1782
   353
   * this uid into such a counter, because of questions such as what
tomh@1782
   354
   * should the uid be when the packet is sent over broadcast media, or
tomh@1782
   355
   * when fragmentation occurs. If a user wants to trace actual packet
tomh@1782
   356
   * counts, he or she should look at e.g. the IP ID field or transport
tomh@1782
   357
   * sequence numbers, or other packet or frame counters at other
tomh@1782
   358
   * protocol layers.
tomh@1782
   359
   *
mathieu@150
   360
   * \returns an integer identifier which uniquely
mathieu@150
   361
   *          identifies this packet.
mathieu@150
   362
   */
mathieu@150
   363
  uint32_t GetUid (void) const;
mathieu@463
   364
mathieu@880
   365
  /**
mathieu@880
   366
   * \param os output stream in which the data should be printed.
mathieu@880
   367
   *
mathieu@880
   368
   * Iterate over the headers and trailers present in this packet, 
mathieu@880
   369
   * from the first header to the last trailer and invoke, for
mathieu@880
   370
   * each of them, the user-provided method Header::DoPrint or 
mathieu@880
   371
   * Trailer::DoPrint methods.
mathieu@880
   372
   */
mathieu@463
   373
  void Print (std::ostream &os) const;
mathieu@2639
   374
mathieu@2639
   375
  PacketMetadata::ItemIterator BeginItem (void) const;
mathieu@875
   376
mathieu@880
   377
  /**
mathieu@880
   378
   * By default, packets do not keep around enough metadata to
mathieu@880
   379
   * perform the operations requested by the Print methods. If you
mathieu@880
   380
   * want to be able to invoke any of the two ::Print methods, 
mathieu@880
   381
   * you need to invoke this method at least once during the 
mathieu@880
   382
   * simulation setup and before any packet is created.
mathieu@3553
   383
   */
mathieu@3553
   384
  static void EnablePrinting (void);
mathieu@3553
   385
  /**
mathieu@880
   386
   * The packet metadata is also used to perform extensive
mathieu@880
   387
   * sanity checks at runtime when performing operations on a 
mathieu@880
   388
   * Packet. For example, this metadata is used to verify that
mathieu@880
   389
   * when you remove a header from a packet, this same header
mathieu@880
   390
   * was actually present at the front of the packet. These
mathieu@880
   391
   * errors will be detected and will abort the program.
mathieu@880
   392
   */
mathieu@3553
   393
  static void EnableChecking (void);
mathieu@1138
   394
mathieu@1142
   395
  /**
mathieu@1142
   396
   * \returns a byte buffer
mathieu@1142
   397
   *
mathieu@1142
   398
   * This method creates a serialized representation of a Packet object
mathieu@1142
   399
   * ready to be transmitted over a network to another system. This
mathieu@1142
   400
   * serialized representation contains a copy of the packet byte buffer,
mathieu@1142
   401
   * the tag list, and the packet metadata (if there is one).
mathieu@1142
   402
   *
mathieu@1246
   403
   * This method will trigger calls to the Serialize and GetSerializedSize
mathieu@1246
   404
   * methods of each tag stored in this packet.
mathieu@1246
   405
   *
mathieu@1142
   406
   * This method will typically be used by parallel simulations where
mathieu@1142
   407
   * the simulated system is partitioned and each partition runs on
mathieu@1142
   408
   * a different CPU.
mathieu@1142
   409
   */
mathieu@1142
   410
  Buffer Serialize (void) const;
mathieu@1142
   411
  /**
mathieu@1249
   412
   * \param buffer a byte buffer
mathieu@1142
   413
   *
mathieu@1142
   414
   * This method reads a byte buffer as created by Packet::Serialize
mathieu@1246
   415
   * and restores the state of the Packet to what it was prior to
mathieu@1142
   416
   * calling Serialize.
mathieu@1142
   417
   *
mathieu@1246
   418
   * This method will trigger calls to the Deserialize method
mathieu@1246
   419
   * of each tag stored in this packet.
mathieu@1246
   420
   *
mathieu@1142
   421
   * This method will typically be used by parallel simulations where
mathieu@1142
   422
   * the simulated system is partitioned and each partition runs on
mathieu@1142
   423
   * a different CPU.
mathieu@1142
   424
   */
mathieu@1138
   425
  void Deserialize (Buffer buffer);
mathieu@3035
   426
mathieu@3035
   427
  /**
mathieu@3035
   428
   * \param tag the new tag to add to this packet
mathieu@3035
   429
   *
mathieu@3035
   430
   * Tag each byte included in this packet with the
mathieu@3035
   431
   * new tag.
mathieu@3039
   432
   *
mathieu@3039
   433
   * Note that adding a tag is a const operation which is pretty 
mathieu@3039
   434
   * un-intuitive. The rationale is that the content and behavior of
mathieu@3039
   435
   * a packet is _not_ changed when a tag is added to a packet: any
mathieu@3039
   436
   * code which was not aware of the new tag is going to work just
mathieu@3039
   437
   * the same if the new tag is added. The real reason why adding a
mathieu@3039
   438
   * tag was made a const operation is to allow a trace sink which gets
mathieu@3039
   439
   * a packet to tag the packet, even if the packet is const (and most
mathieu@3039
   440
   * trace sources should use const packets because it would be
mathieu@3039
   441
   * totally evil to allow a trace sink to modify the content of a
mathieu@3039
   442
   * packet).
mathieu@3035
   443
   */
mathieu@4502
   444
  void AddByteTag (const Tag &tag) const;
mathieu@3035
   445
  /**
mathieu@4502
   446
   * \returns an iterator over the set of byte tags included in this packet.
mathieu@3035
   447
   */
mathieu@4502
   448
  ByteTagIterator GetByteTagIterator (void) const;
mathieu@3035
   449
  /**
mathieu@3035
   450
   * \param tag the tag to search in this packet
mathieu@3035
   451
   * \returns true if the requested tag type was found, false otherwise.
mathieu@3035
   452
   *
mathieu@3035
   453
   * If the requested tag type is found, it is copied in the user's 
mathieu@3035
   454
   * provided tag instance.
mathieu@3035
   455
   */
mathieu@4502
   456
  bool FindFirstMatchingByteTag (Tag &tag) const;
mathieu@3035
   457
mathieu@3039
   458
  /**
mathieu@3039
   459
   * Remove all the tags stored in this packet.
mathieu@3039
   460
   */
mathieu@4502
   461
  void RemoveAllByteTags (void);
mathieu@4502
   462
mathieu@4502
   463
  /**
mathieu@4502
   464
   * \param os output stream in which the data should be printed.
mathieu@4502
   465
   *
mathieu@4502
   466
   * Iterate over the tags present in this packet, and
mathieu@4502
   467
   * invoke the Print method of each tag stored in the packet.
mathieu@4502
   468
   */
mathieu@4502
   469
  void PrintByteTags (std::ostream &os) const;
mathieu@4502
   470
mathieu@4502
   471
  /**
mathieu@4502
   472
   * \param tag the tag to store in this packet
mathieu@4502
   473
   *
mathieu@4502
   474
   * Add a tag to this packet. This method calls the
mathieu@4502
   475
   * Tag::GetSerializedSize and, then, Tag::Serialize.
mathieu@4502
   476
   *
mathieu@4502
   477
   * Note that this method is const, that is, it does not
mathieu@4502
   478
   * modify the state of this packet, which is fairly
mathieu@4502
   479
   * un-intuitive.
mathieu@4502
   480
   */
mathieu@4502
   481
  void AddPacketTag (const Tag &tag) const;
mathieu@4502
   482
  /**
mathieu@4502
   483
   * \param tag the tag to remove from this packet
mathieu@4502
   484
   * \returns true if the requested tag is found, false
mathieu@4502
   485
   *          otherwise.
mathieu@4502
   486
   *
mathieu@4502
   487
   * Remove a tag from this packet. This method calls
mathieu@4502
   488
   * Tag::Deserialize if the tag is found.
mathieu@4502
   489
   */
mathieu@4502
   490
  bool RemovePacketTag (Tag &tag);
mathieu@4502
   491
  /**
mathieu@4502
   492
   * \param tag the tag to search in this packet
mathieu@4502
   493
   * \returns true if the requested tag is found, false
mathieu@4502
   494
   *          otherwise.
mathieu@4502
   495
   *
mathieu@4502
   496
   * Search a matching tag and call Tag::Deserialize if it is found.
mathieu@4502
   497
   */
mathieu@4502
   498
  bool PeekPacketTag (Tag &tag) const;
mathieu@4502
   499
  /**
mathieu@4502
   500
   * Remove all packet tags.
mathieu@4502
   501
   */
mathieu@4502
   502
  void RemoveAllPacketTags (void);
mathieu@4502
   503
mathieu@4502
   504
  /**
mathieu@4502
   505
   * \param os the stream in which we want to print data.
mathieu@4502
   506
   *
mathieu@4502
   507
   * Print the list of 'packet' tags.
mathieu@4502
   508
   *
mathieu@4502
   509
   * \sa Packet::AddPacketTag, Packet::RemovePacketTag, Packet::PeekPacketTag,
mathieu@4502
   510
   *  Packet::RemoveAllPacketTags
mathieu@4502
   511
   */
mathieu@4502
   512
  void PrintPacketTags (std::ostream &os) const;
mathieu@4502
   513
mathieu@4502
   514
  /**
mathieu@4502
   515
   * \returns an object which can be used to iterate over the list of
mathieu@4502
   516
   *  packet tags.
mathieu@4502
   517
   */
mathieu@4502
   518
  PacketTagIterator GetPacketTagIterator (void) const;
mathieu@3039
   519
jpelkey@5226
   520
  /* Note: These functions support a temporary solution 
jpelkey@5224
   521
   * to a specific problem in this generic class, i.e. 
jpelkey@5224
   522
   * how to associate something specific like nix-vector 
jpelkey@5224
   523
   * with a packet.  This design methodology 
jpelkey@5224
   524
   * should _not_ be followed, and is only here as an 
jpelkey@5224
   525
   * impetus to fix this general issue. */
jpelkey@5224
   526
  void SetNixVector (Ptr<NixVector>);
jpelkey@5224
   527
  Ptr<NixVector> GetNixVector (void) const; 
jpelkey@5224
   528
mathieu@9
   529
private:
mathieu@4502
   530
  Packet (const Buffer &buffer, const ByteTagList &byteTagList, 
mathieu@4502
   531
          const PacketTagList &packetTagList, const PacketMetadata &metadata);
mathieu@150
   532
  Buffer m_buffer;
mathieu@4502
   533
  ByteTagList m_byteTagList;
mathieu@4502
   534
  PacketTagList m_packetTagList;
mathieu@888
   535
  PacketMetadata m_metadata;
jpelkey@5224
   536
jpelkey@5224
   537
  /* Please see comments above about nix-vector */
jpelkey@5224
   538
  Ptr<NixVector> m_nixVector;
jpelkey@5224
   539
mathieu@463
   540
  static uint32_t m_globalUid;
mathieu@9
   541
};
mathieu@9
   542
mathieu@1360
   543
std::ostream& operator<< (std::ostream& os, const Packet &packet);
mathieu@1360
   544
mathieu@1136
   545
/**
tomh@2217
   546
 * \ingroup common
mathieu@1136
   547
 * \defgroup packetperf Packet Performance
mathieu@1136
   548
 * The current implementation of the byte buffers and tag list is based
mathieu@1136
   549
 * on COW (Copy On Write. An introduction to COW can be found in Scott 
mathieu@1136
   550
 * Meyer's "More Effective C++", items 17 and 29). What this means is that
mathieu@1136
   551
 * copying packets without modifying them is very cheap (in terms of cpu
mathieu@1136
   552
 * and memory usage) and modifying them can be also very cheap. What is 
mathieu@1136
   553
 * key for proper COW implementations is being
mathieu@1136
   554
 * able to detect when a given modification of the state of a packet triggers
mathieu@1136
   555
 * a full copy of the data prior to the modification: COW systems need
mathieu@1136
   556
 * to detect when an operation is "dirty".
mathieu@1136
   557
 *
mathieu@1136
   558
 * Dirty operations:
mathieu@1136
   559
 *   - ns3::Packet::AddHeader
mathieu@1136
   560
 *   - ns3::Packet::AddTrailer
mathieu@1136
   561
 *   - both versions of ns3::Packet::AddAtEnd
mathieu@4502
   562
 *   - ns3::Packet::RemovePacketTag
mathieu@1136
   563
 *
mathieu@1136
   564
 * Non-dirty operations:
mathieu@4503
   565
 *   - ns3::Packet::AddPacketTag
mathieu@4503
   566
 *   - ns3::Packet::PeekPacketTag
mathieu@4502
   567
 *   - ns3::Packet::RemoveAllPacketTags
mathieu@4503
   568
 *   - ns3::Packet::AddByteTag
mathieu@4503
   569
 *   - ns3::Packet::FindFirstMatchingByteTag
mathieu@4503
   570
 *   - ns3::Packet::RemoveAllByteTags
mathieu@1136
   571
 *   - ns3::Packet::RemoveHeader
mathieu@1136
   572
 *   - ns3::Packet::RemoveTrailer
mathieu@1136
   573
 *   - ns3::Packet::CreateFragment
mathieu@1136
   574
 *   - ns3::Packet::RemoveAtStart
mathieu@1136
   575
 *   - ns3::Packet::RemoveAtEnd
mathieu@3764
   576
 *   - ns3::Packet::CopyData
mathieu@1136
   577
 *
mathieu@1136
   578
 * Dirty operations will always be slower than non-dirty operations,
mathieu@1136
   579
 * sometimes by several orders of magnitude. However, even the
mathieu@1136
   580
 * dirty operations have been optimized for common use-cases which
mathieu@1136
   581
 * means that most of the time, these operations will not trigger
mathieu@1136
   582
 * data copies and will thus be still very fast.
mathieu@1136
   583
 */
mathieu@1136
   584
mathieu@1136
   585
} // namespace ns3
mathieu@9
   586
mathieu@9
   587
#endif /* PACKET_H */