A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
packet-metadata.h
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2006,2007 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 #ifndef PACKET_METADATA_H
21 #define PACKET_METADATA_H
22 
23 #include <stdint.h>
24 #include <vector>
25 #include <limits>
26 #include "ns3/callback.h"
27 #include "ns3/assert.h"
28 #include "ns3/type-id.h"
29 #include "buffer.h"
30 
31 namespace ns3 {
32 
33 class Chunk;
34 class Buffer;
35 class Header;
36 class Trailer;
37 
80 {
81 public:
82  struct Item
83  {
84  enum {
85  PAYLOAD,
86  HEADER,
87  TRAILER
88  } type;
89  /* true: this is a fragmented header, trailer, or, payload.
90  * false: this is a whole header, trailer, or, payload.
91  */
92  bool isFragment;
93  /* TypeId of Header or Trailer. Valid only if type is
94  * header or trailer.
95  */
96  TypeId tid;
97  /* size of item. If fragment, size of fragment. Otherwise,
98  * size of original item.
99  */
100  uint32_t currentSize;
101  /* how many bytes were trimed from the start of a fragment.
102  * if isFragment is true, this field is zero.
103  */
104  uint32_t currentTrimedFromStart;
105  /* how many bytes were trimed from the end of a fragment.
106  * if isFragment is true, this field is zero.
107  */
108  uint32_t currentTrimedFromEnd;
109  /* an iterator which can be fed to Deserialize. Valid only
110  * if isFragment and isPayload are false.
111  */
112  Buffer::Iterator current;
113  };
115  {
116 public:
117  ItemIterator (const PacketMetadata *metadata, Buffer buffer);
118  bool HasNext (void) const;
119  Item Next (void);
120 private:
121  const PacketMetadata *m_metadata;
122  Buffer m_buffer;
123  uint16_t m_current;
124  uint32_t m_offset;
125  bool m_hasReadTail;
126  };
127 
128  static void Enable (void);
129  static void EnableChecking (void);
130 
131  inline PacketMetadata (uint64_t uid, uint32_t size);
132  inline PacketMetadata (PacketMetadata const &o);
133  inline PacketMetadata &operator = (PacketMetadata const& o);
134  inline ~PacketMetadata ();
135 
136  void AddHeader (Header const &header, uint32_t size);
137  void RemoveHeader (Header const &header, uint32_t size);
138 
139  void AddTrailer (Trailer const &trailer, uint32_t size);
140  void RemoveTrailer (Trailer const &trailer, uint32_t size);
141 
149  PacketMetadata CreateFragment (uint32_t start, uint32_t end) const;
150  void AddAtEnd (PacketMetadata const&o);
151  void AddPaddingAtEnd (uint32_t end);
152  void RemoveAtStart (uint32_t start);
153  void RemoveAtEnd (uint32_t end);
154 
155  uint64_t GetUid (void) const;
156 
157  uint32_t GetSerializedSize (void) const;
158 
159  ItemIterator BeginItem (Buffer buffer) const;
160 
161  // Serialization to/from raw uint8_t*
162  uint32_t Serialize (uint8_t* buffer, uint32_t maxSize) const;
163  uint32_t Deserialize (const uint8_t* buffer, uint32_t size);
164 
165 private:
166  // Helper for the raw serilization/deserialization
167  static uint8_t* AddToRawU8 (const uint8_t& data,
168  uint8_t* start,
169  uint8_t* current,
170  uint32_t maxSize);
171 
172  static uint8_t* AddToRawU16 (const uint16_t& data,
173  uint8_t* start,
174  uint8_t* current,
175  uint32_t maxSize);
176 
177  static uint8_t* AddToRawU32 (const uint32_t& data,
178  uint8_t* start,
179  uint8_t* current,
180  uint32_t maxSize);
181 
182  static uint8_t* AddToRawU64 (const uint64_t& data,
183  uint8_t* start,
184  uint8_t* current,
185  uint32_t maxSize);
186 
187  static uint8_t* AddToRaw (const uint8_t* data,
188  uint32_t dataSize,
189  uint8_t* start,
190  uint8_t* current,
191  uint32_t maxSize);
192 
193  static uint8_t* ReadFromRawU8 (uint8_t& data,
194  const uint8_t* start,
195  const uint8_t* current,
196  uint32_t maxSize);
197 
198  static uint8_t* ReadFromRawU16 (uint16_t& data,
199  const uint8_t* start,
200  const uint8_t* current,
201  uint32_t maxSize);
202 
203  static uint8_t* ReadFromRawU32 (uint32_t& data,
204  const uint8_t* start,
205  const uint8_t* current,
206  uint32_t maxSize);
207 
208  static uint8_t* ReadFromRawU64 (uint64_t& data,
209  const uint8_t* start,
210  const uint8_t* current,
211  uint32_t maxSize);
212 
217 #define PACKET_METADATA_DATA_M_DATA_SIZE 8
218 
219  struct Data {
220  /* number of references to this struct Data instance. */
221  uint32_t m_count;
222  /* size (in bytes) of m_data buffer below */
223  uint16_t m_size;
224  /* max of the m_used field over all objects which
225  * reference this struct Data instance */
226  uint16_t m_dirtyEnd;
227  /* variable-sized buffer of bytes */
228  uint8_t m_data[PACKET_METADATA_DATA_M_DATA_SIZE];
229  };
230  /* Note that since the next and prev fields are 16 bit integers
231  and since the value 0xffff is reserved to identify the
232  fact that the end or the start of the list is reached,
233  only a limited number of elements can be stored in
234  a m_data byte buffer.
235  */
236  struct SmallItem {
237  /* offset (in bytes) from start of m_data buffer
238  to next element in linked list. value is 0xffff
239  if next element does not exist.
240  stored as a fixed-size 16 bit integer.
241  */
242  uint16_t next;
243  /* offset (in bytes) from start of m_data buffer
244  to previous element in linked list. value is 0xffff
245  if previous element does not exist.
246  stored as a fixed-size 16 bit integer.
247  */
248  uint16_t prev;
249  /* the high 31 bits of this field identify the
250  type of the header or trailer represented by
251  this item: the value zero represents payload.
252  If the low bit of this uid is one, an ExtraItem
253  structure follows this SmallItem structure.
254  stored as a variable-size 32 bit integer.
255  */
256  uint32_t typeUid;
257  /* the size (in bytes) of the header or trailer represented
258  by this element.
259  stored as a variable-size 32 bit integer.
260  */
261  uint32_t size;
262  /* this field tries to uniquely identify each header or
263  trailer _instance_ while the typeUid field uniquely
264  identifies each header or trailer _type_. This field
265  is used to test whether two items are equal in the sense
266  that they represent the same header or trailer instance.
267  That equality test is based on the typeUid and chunkUid
268  fields so, the likelyhood that two header instances
269  share the same chunkUid _and_ typeUid is very small
270  unless they are really representations of the same header
271  instance.
272  stored as a fixed-size 16 bit integer.
273  */
274  uint16_t chunkUid;
275  };
276  struct ExtraItem {
277  /* offset (in bytes) from start of original header to
278  the start of the fragment still present.
279  stored as a variable-size 32 bit integer.
280  */
281  uint32_t fragmentStart;
282  /* offset (in bytes) from start of original header to
283  the end of the fragment still present.
284  stored as a variable-size 32 bit integer.
285  */
286  uint32_t fragmentEnd;
287  /* the packetUid of the packet in which this header or trailer
288  was first added. It could be different from the m_packetUid
289  field if the user has aggregated multiple packets into one.
290  stored as a fixed-size 64 bit integer.
291  */
292  uint64_t packetUid;
293  };
294 
295  class DataFreeList : public std::vector<struct Data *>
296  {
297 public:
298  ~DataFreeList ();
299  };
300 
301  friend DataFreeList::~DataFreeList ();
302  friend class ItemIterator;
303 
304  PacketMetadata ();
305 
306  inline uint16_t AddSmall (const PacketMetadata::SmallItem *item);
307  uint16_t AddBig (uint32_t head, uint32_t tail,
308  const PacketMetadata::SmallItem *item,
309  const PacketMetadata::ExtraItem *extraItem);
311  PacketMetadata::ExtraItem *extraItem,
312  uint32_t available);
313  inline void UpdateHead (uint16_t written);
314  inline void UpdateTail (uint16_t written);
315  inline uint32_t GetUleb128Size (uint32_t value) const;
316  uint32_t ReadUleb128 (const uint8_t **pBuffer) const;
317  inline void Append16 (uint16_t value, uint8_t *buffer);
318  inline void Append32 (uint32_t value, uint8_t *buffer);
319  inline void AppendValue (uint32_t value, uint8_t *buffer);
320  void AppendValueExtra (uint32_t value, uint8_t *buffer);
321  inline void Reserve (uint32_t n);
322  void ReserveCopy (uint32_t n);
323  uint32_t GetTotalSize (void) const;
324  uint32_t ReadItems (uint16_t current,
325  struct PacketMetadata::SmallItem *item,
326  struct PacketMetadata::ExtraItem *extraItem) const;
327  void DoAddHeader (uint32_t uid, uint32_t size);
328  bool IsStateOk (void) const;
329  bool IsPointerOk (uint16_t pointer) const;
330  bool IsSharedPointerOk (uint16_t pointer) const;
331 
332 
333  static struct PacketMetadata::Data *Create (uint32_t size);
334  static void Recycle (struct PacketMetadata::Data *data);
335  static struct PacketMetadata::Data *Allocate (uint32_t n);
336  static void Deallocate (struct PacketMetadata::Data *data);
337 
338  static DataFreeList m_freeList;
339  static bool m_enable;
340  static bool m_enableChecking;
341 
342  // set to true when adding metadata to a packet is skipped because
343  // m_enable is false; used to detect enabling of metadata in the
344  // middle of a simulation, which isn't allowed.
345  static bool m_metadataSkipped;
346 
347  static uint32_t m_maxSize;
348  static uint16_t m_chunkUid;
349 
350  struct Data *m_data;
356  uint16_t m_head;
357  uint16_t m_tail;
358  uint16_t m_used;
359  uint64_t m_packetUid;
360 };
361 
362 } // namespace ns3
363 
364 namespace ns3 {
365 
366 PacketMetadata::PacketMetadata (uint64_t uid, uint32_t size)
367  : m_data (PacketMetadata::Create (10)),
368  m_head (0xffff),
369  m_tail (0xffff),
370  m_used (0),
371  m_packetUid (uid)
372 {
373  memset (m_data->m_data, 0xff, 4);
374  if (size > 0)
375  {
376  DoAddHeader (0, size);
377  }
378 }
379 PacketMetadata::PacketMetadata (PacketMetadata const &o)
380  : m_data (o.m_data),
381  m_head (o.m_head),
382  m_tail (o.m_tail),
383  m_used (o.m_used),
384  m_packetUid (o.m_packetUid)
385 {
386  NS_ASSERT (m_data != 0);
387  NS_ASSERT (m_data->m_count < std::numeric_limits<uint32_t>::max());
388  m_data->m_count++;
389 }
390 PacketMetadata &
391 PacketMetadata::operator = (PacketMetadata const& o)
392 {
393  if (m_data != o.m_data)
394  {
395  // not self assignment
396  NS_ASSERT (m_data != 0);
397  m_data->m_count--;
398  if (m_data->m_count == 0)
399  {
400  PacketMetadata::Recycle (m_data);
401  }
402  m_data = o.m_data;
403  NS_ASSERT (m_data != 0);
404  m_data->m_count++;
405  }
406  m_head = o.m_head;
407  m_tail = o.m_tail;
408  m_used = o.m_used;
409  m_packetUid = o.m_packetUid;
410  return *this;
411 }
412 PacketMetadata::~PacketMetadata ()
413 {
414  NS_ASSERT (m_data != 0);
415  m_data->m_count--;
416  if (m_data->m_count == 0)
417  {
418  PacketMetadata::Recycle (m_data);
419  }
420 }
421 
422 } // namespace ns3
423 
424 
425 #endif /* PACKET_METADATA_H */
Protocol header serialization and deserialization.
Definition: header.h:42
automatically resized byte buffer
Definition: buffer.h:92
#define NS_ASSERT(condition)
Definition: assert.h:64
iterator in a Buffer instance
Definition: buffer.h:98
PacketMetadata CreateFragment(uint32_t start, uint32_t end) const
Protocol trailer serialization and deserialization.
Definition: trailer.h:40
void ReplaceTail(PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem, uint32_t available)
a unique identifier for an interface.
Definition: type-id.h:44
uint32_t ReadItems(uint16_t current, struct PacketMetadata::SmallItem *item, struct PacketMetadata::ExtraItem *extraItem) const
handle packet metadata about packet headers and trailers