A Discrete-Event Network Simulator
API
byte-tag-list.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 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 "byte-tag-list.h"
21 #include "ns3/log.h"
22 #include <vector>
23 #include <cstring>
24 
25 #define USE_FREE_LIST 1
26 #define FREE_LIST_SIZE 1000
27 #define OFFSET_MAX (2147483647)
28 
29 namespace ns3 {
30 
31 NS_LOG_COMPONENT_DEFINE ("ByteTagList");
32 
41  uint32_t size;
42  uint32_t count;
43  uint32_t dirty;
44  uint8_t data[4];
45 };
46 
47 #ifdef USE_FREE_LIST
48 
55 static class ByteTagListDataFreeList : public std::vector<struct ByteTagListData *>
56 {
57 public:
59 } g_freeList;
60 static uint32_t g_maxSize = 0;
61 
63 {
64  NS_LOG_FUNCTION (this);
65  for (ByteTagListDataFreeList::iterator i = begin ();
66  i != end (); i++)
67  {
68  uint8_t *buffer = (uint8_t *)(*i);
69  delete [] buffer;
70  }
71 }
72 #endif /* USE_FREE_LIST */
73 
75  : buf (buf_)
76 {
77  NS_LOG_FUNCTION (this << &buf_);
78 }
79 
80 bool
82 {
83  NS_LOG_FUNCTION (this);
84  return m_current < m_end;
85 }
88 {
89  NS_ASSERT (HasNext ());
90  struct Item item = Item (TagBuffer (m_current+16, m_end));
91  item.tid.SetUid (m_nextTid);
92  item.size = m_nextSize;
95  m_current += 4 + 4 + 4 + 4 + item.size;
96  item.buf.TrimAtEnd (m_end - m_current);
97  PrepareForNext ();
98  return item;
99 }
100 void
102 {
103  NS_LOG_FUNCTION (this);
104  while (m_current < m_end)
105  {
107  m_nextTid = buf.ReadU32 ();
108  m_nextSize = buf.ReadU32 ();
109  m_nextStart = buf.ReadU32 () + m_adjustment;
110  m_nextEnd = buf.ReadU32 () + m_adjustment;
112  {
113  m_current += 4 + 4 + 4 + 4 + m_nextSize;
114  }
115  else
116  {
117  break;
118  }
119  }
120 }
121 ByteTagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd, int32_t adjustment)
122  : m_current (start),
123  m_end (end),
124  m_offsetStart (offsetStart),
125  m_offsetEnd (offsetEnd),
126  m_adjustment (adjustment)
127 {
128  NS_LOG_FUNCTION (this << &start << &end << offsetStart << offsetEnd << adjustment);
129  PrepareForNext ();
130 }
131 
132 uint32_t
134 {
135  NS_LOG_FUNCTION (this);
136  return m_offsetStart;
137 }
138 
139 
141  : m_minStart (INT32_MAX),
142  m_maxEnd (INT32_MIN),
143  m_adjustment (0),
144  m_used (0),
145  m_data (0)
146 {
147  NS_LOG_FUNCTION (this);
148 }
150  : m_minStart (o.m_minStart),
151  m_maxEnd (o.m_maxEnd),
152  m_adjustment (o.m_adjustment),
153  m_used (o.m_used),
154  m_data (o.m_data)
155 {
156  NS_LOG_FUNCTION (this << &o);
157  if (m_data != 0)
158  {
159  m_data->count++;
160  }
161 }
162 ByteTagList &
164 {
165  if (this == &o)
166  {
167  return *this;
168  }
169 
170  Deallocate (m_data);
172  m_maxEnd = o.m_maxEnd;
174  m_data = o.m_data;
175  m_used = o.m_used;
176  if (m_data != 0)
177  {
178  m_data->count++;
179  }
180  return *this;
181 }
183 {
184  NS_LOG_FUNCTION (this);
185  Deallocate (m_data);
186  m_data = 0;
187  m_used = 0;
188 }
189 
190 TagBuffer
191 ByteTagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
192 {
193  NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
194  uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
195  NS_ASSERT (m_used <= spaceNeeded);
196  if (m_data == 0)
197  {
198  m_data = Allocate (spaceNeeded);
199  m_used = 0;
200  }
201  else if (m_data->size < spaceNeeded ||
202  (m_data->count != 1 && m_data->dirty != m_used))
203  {
204  struct ByteTagListData *newData = Allocate (spaceNeeded);
205  std::memcpy (&newData->data, &m_data->data, m_used);
206  Deallocate (m_data);
207  m_data = newData;
208  }
209  TagBuffer tag = TagBuffer (&m_data->data[m_used],
210  &m_data->data[spaceNeeded]);
211  tag.WriteU32 (tid.GetUid ());
212  tag.WriteU32 (bufferSize);
213  tag.WriteU32 (start - m_adjustment);
214  tag.WriteU32 (end - m_adjustment);
215  if (start - m_adjustment < m_minStart)
216  {
217  m_minStart = start - m_adjustment;
218  }
219  if (end - m_adjustment > m_maxEnd)
220  {
221  m_maxEnd = end - m_adjustment;
222  }
223  m_used = spaceNeeded;
224  m_data->dirty = m_used;
225  return tag;
226 }
227 
228 void
230 {
231  NS_LOG_FUNCTION (this << &o);
233  while (i.HasNext ())
234  {
235  ByteTagList::Iterator::Item item = i.Next ();
236  TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
237  buf.CopyFrom (item.buf);
238  }
239 }
240 
241 void
243 {
244  NS_LOG_FUNCTION (this);
245  Deallocate (m_data);
246  m_minStart = INT32_MAX;
247  m_maxEnd = INT32_MIN;
248  m_adjustment = 0;
249  m_data = 0;
250  m_used = 0;
251 }
252 
255 {
256  NS_LOG_FUNCTION (this);
257  // I am not totally sure but I might need to use
258  // INT32_MIN instead of zero below.
259  return Begin (0, OFFSET_MAX);
260 }
261 
263 ByteTagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
264 {
265  NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
266  if (m_data == 0)
267  {
268  return Iterator (0, 0, offsetStart, offsetEnd, 0);
269  }
270  else
271  {
272  return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd, m_adjustment);
273  }
274 }
275 
276 void
277 ByteTagList::AddAtEnd (int32_t appendOffset)
278 {
279  NS_LOG_FUNCTION (this << appendOffset);
280  if (m_maxEnd <= appendOffset - m_adjustment)
281  {
282  return;
283  }
286  while (i.HasNext ())
287  {
288  ByteTagList::Iterator::Item item = i.Next ();
289 
290  if (item.start >= appendOffset)
291  {
292  continue;
293  }
294  if (item.end > appendOffset)
295  {
296  item.end = appendOffset;
297  }
298  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
299  buf.CopyFrom (item.buf);
300  if (item.end > m_maxEnd)
301  {
302  m_maxEnd = item.end;
303  }
304  }
305  *this = list;
306 }
307 
308 void
309 ByteTagList::AddAtStart (int32_t prependOffset)
310 {
311  NS_LOG_FUNCTION (this << prependOffset);
312  if (m_minStart >= prependOffset - m_adjustment)
313  {
314  return;
315  }
316  m_minStart = INT32_MAX;
319  while (i.HasNext ())
320  {
321  ByteTagList::Iterator::Item item = i.Next ();
322 
323  if (item.end <= prependOffset)
324  {
325  continue;
326  }
327  if (item.start < prependOffset)
328  {
329  item.start = prependOffset;
330  }
331  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
332  buf.CopyFrom (item.buf);
333  if (item.start < m_minStart)
334  {
335  m_minStart = item.start;
336  }
337  }
338  *this = list;
339 }
340 
341 #ifdef USE_FREE_LIST
342 
343 struct ByteTagListData *
344 ByteTagList::Allocate (uint32_t size)
345 {
346  NS_LOG_FUNCTION (this << size);
347  while (!g_freeList.empty ())
348  {
349  struct ByteTagListData *data = g_freeList.back ();
350  g_freeList.pop_back ();
351  NS_ASSERT (data != 0);
352  if (data->size >= size)
353  {
354  data->count = 1;
355  data->dirty = 0;
356  return data;
357  }
358  uint8_t *buffer = (uint8_t *)data;
359  delete [] buffer;
360  }
361  uint8_t *buffer = new uint8_t [std::max (size, g_maxSize) + sizeof (struct ByteTagListData) - 4];
362  struct ByteTagListData *data = (struct ByteTagListData *)buffer;
363  data->count = 1;
364  data->size = size;
365  data->dirty = 0;
366  return data;
367 }
368 
369 void
371 {
372  NS_LOG_FUNCTION (this << data);
373  if (data == 0)
374  {
375  return;
376  }
377  g_maxSize = std::max (g_maxSize, data->size);
378  data->count--;
379  if (data->count == 0)
380  {
381  if (g_freeList.size () > FREE_LIST_SIZE ||
382  data->size < g_maxSize)
383  {
384  uint8_t *buffer = (uint8_t *)data;
385  delete [] buffer;
386  }
387  else
388  {
389  g_freeList.push_back (data);
390  }
391  }
392 }
393 
394 #else /* USE_FREE_LIST */
395 
396 struct ByteTagListData *
397 ByteTagList::Allocate (uint32_t size)
398 {
399  NS_LOG_FUNCTION (this << size);
400  uint8_t *buffer = new uint8_t [size + sizeof (struct ByteTagListData) - 4];
401  struct ByteTagListData *data = (struct ByteTagListData *)buffer;
402  data->count = 1;
403  data->size = size;
404  data->dirty = 0;
405  return data;
406 }
407 
408 void
409 ByteTagList::Deallocate (struct ByteTagListData *data)
410 {
411  NS_LOG_FUNCTION (this << data);
412  if (data == 0)
413  {
414  return;
415  }
416  data->count--;
417  if (data->count == 0)
418  {
419  uint8_t *buffer = (uint8_t *)data;
420  delete [] buffer;
421  }
422 }
423 
424 #endif /* USE_FREE_LIST */
425 
426 
427 } // namespace ns3
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t dirty
number of bytes actually in use
ByteTagList & operator=(const ByteTagList &o)
Assignment operator, deallocates current data and assigns value of passed in ByteTagList.
#define min(a, b)
Definition: 80211b.c:44
struct ByteTagListData * m_data
the ByteTagListData structure
uint32_t count
use counter (for smart deallocation)
def start()
Definition: core.py:1482
keep track of the byte tags stored in a packet.
Definition: byte-tag-list.h:63
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:67
bool HasNext(void) const
Used to determine if the iterator is at the end of the byteTagList.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
TagBuffer Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
void TrimAtEnd(uint32_t trim)
Trim some space from the end.
Definition: tag-buffer.cc:192
uint32_t m_nextTid
TypeId of the next tag.
TAG_BUFFER_INLINE uint32_t ReadU32(void)
Definition: tag-buffer.h:215
ns3::ByteTagListDataFreeList g_freeList
Container for struct ByteTagListData.
void Deallocate(struct ByteTagListData *data)
Deallocates a ByteTagListData.
uint8_t * m_current
Current tag.
#define FREE_LIST_SIZE
int32_t m_offsetEnd
Offset to the end of the tag from the virtual byte buffer.
void AddAtEnd(int32_t appendOffset)
Make sure that all offsets are smaller than appendOffset which represents the location where new byte...
void PrepareForNext(void)
Prepare the iterator for the next tag.
void RemoveAll(void)
Removes all of the tags from the ByteTagList.
#define max(a, b)
Definition: 80211b.c:45
Internal representation of the byte tags stored in a packet.
uint32_t m_nextSize
Size of the next tag.
uint8_t data[writeSize]
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:186
#define OFFSET_MAX
int32_t start
offset to the start of the tag from the virtual byte buffer
Definition: byte-tag-list.h:85
struct ByteTagList::Iterator::Item Next(void)
Returns the next Item from the ByteTagList.
#define list
struct ByteTagListData * Allocate(uint32_t size)
Allocate the memory for the ByteTagListData.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Iterator(uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd, int32_t adjustment)
Constructor.
int32_t m_minStart
minimal start offset
int32_t m_nextStart
Start of the next tag.
uint32_t GetOffsetStart(void) const
Returns the offset from the start of the virtual byte buffer to the ByteTagList.
int32_t end
offset to the end of the tag from the virtual byte buffer
Definition: byte-tag-list.h:86
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1172
uint32_t m_used
the number of used bytes in the buffer
ByteTagList::Iterator BeginAll(void) const
Returns an iterator pointing to the very first tag in this list.
int32_t m_offsetStart
Offset to the start of the tag from the virtual byte buffer.
Container class for struct ByteTagListData.
TypeId tid
type of the tag
Definition: byte-tag-list.h:83
uint32_t size
size of tag data
Definition: byte-tag-list.h:84
uint32_t size
size of the data
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1178
int32_t m_adjustment
adjustment to byte tag offsets
ByteTagList::Iterator Begin(int32_t offsetStart, int32_t offsetEnd) const
TagBuffer buf
the data for the tag as generated by Tag::Serialize
Definition: byte-tag-list.h:87
An iterator for iterating through a byte tag list.
Definition: byte-tag-list.h:72
read and write tag data
Definition: tag-buffer.h:51
int32_t m_nextEnd
End of the next tag.
void AddAtStart(int32_t prependOffset)
Make sure that all offsets are bigger than prependOffset which represents the location where new byte...
int32_t m_maxEnd
maximal end offset
Item(TagBuffer buf)
constructs an item with the given TagBuffer
uint8_t data[4]
data
static uint32_t g_maxSize
maximum data size (used for allocation)
a unique identifier for an interface.
Definition: type-id.h:58
int32_t m_adjustment
Adjustment to byte tag offsets.
void CopyFrom(TagBuffer o)
Copy the nternal structure of another TagBuffer.
Definition: tag-buffer.cc:200
uint8_t * m_end
End tag.
An item specifies an individual tag within a byte buffer.
Definition: byte-tag-list.h:81