A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("ByteTagList");
26 
27 #define USE_FREE_LIST 1
28 #define FREE_LIST_SIZE 1000
29 #define OFFSET_MAX (2147483647)
30 
31 namespace ns3 {
32 
34  uint32_t size;
35  uint32_t count;
36  uint32_t dirty;
37  uint8_t data[4];
38 };
39 
40 #ifdef USE_FREE_LIST
41 static class ByteTagListDataFreeList : public std::vector<struct ByteTagListData *>
42 {
43 public:
45 } g_freeList;
46 static uint32_t g_maxSize = 0;
47 
49 {
50  NS_LOG_FUNCTION (this);
51  for (ByteTagListDataFreeList::iterator i = begin ();
52  i != end (); i++)
53  {
54  uint8_t *buffer = (uint8_t *)(*i);
55  delete [] buffer;
56  }
57 }
58 #endif /* USE_FREE_LIST */
59 
61  : buf (buf_)
62 {
63  NS_LOG_FUNCTION (this << &buf_);
64 }
65 
66 bool
68 {
69  NS_LOG_FUNCTION (this);
70  return m_current < m_end;
71 }
74 {
75  NS_ASSERT (HasNext ());
76  struct Item item = Item (TagBuffer (m_current+16, m_end));
77  item.tid.SetUid (m_nextTid);
78  item.size = m_nextSize;
79  item.start = std::max (m_nextStart, m_offsetStart);
80  item.end = std::min (m_nextEnd, m_offsetEnd);
81  m_current += 4 + 4 + 4 + 4 + item.size;
82  item.buf.TrimAtEnd (m_end - m_current);
83  PrepareForNext ();
84  return item;
85 }
86 void
88 {
89  NS_LOG_FUNCTION (this);
90  while (m_current < m_end)
91  {
93  m_nextTid = buf.ReadU32 ();
94  m_nextSize = buf.ReadU32 ();
95  m_nextStart = buf.ReadU32 ();
96  m_nextEnd = buf.ReadU32 ();
98  {
99  m_current += 4 + 4 + 4 + 4 + m_nextSize;
100  }
101  else
102  {
103  break;
104  }
105  }
106 }
107 ByteTagList::Iterator::Iterator (uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
108  : m_current (start),
109  m_end (end),
110  m_offsetStart (offsetStart),
111  m_offsetEnd (offsetEnd)
112 {
113  NS_LOG_FUNCTION (this << &start << &end << offsetStart << offsetEnd);
114  PrepareForNext ();
115 }
116 
117 uint32_t
119 {
120  NS_LOG_FUNCTION (this);
121  return m_offsetStart;
122 }
123 
124 
126  : m_used (0),
127  m_data (0)
128 {
129  NS_LOG_FUNCTION (this);
130 }
132  : m_used (o.m_used),
133  m_data (o.m_data)
134 {
135  NS_LOG_FUNCTION (this << &o);
136  if (m_data != 0)
137  {
138  m_data->count++;
139  }
140 }
141 ByteTagList &
143 {
144  if (this == &o)
145  {
146  return *this;
147  }
148 
149  Deallocate (m_data);
150  m_data = o.m_data;
151  m_used = o.m_used;
152  if (m_data != 0)
153  {
154  m_data->count++;
155  }
156  return *this;
157 }
159 {
160  NS_LOG_FUNCTION (this);
161  Deallocate (m_data);
162  m_data = 0;
163  m_used = 0;
164 }
165 
166 TagBuffer
167 ByteTagList::Add (TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
168 {
169  NS_LOG_FUNCTION (this << tid << bufferSize << start << end);
170  uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
171  NS_ASSERT (m_used <= spaceNeeded);
172  if (m_data == 0)
173  {
174  m_data = Allocate (spaceNeeded);
175  m_used = 0;
176  }
177  else if (m_data->size < spaceNeeded ||
178  (m_data->count != 1 && m_data->dirty != m_used))
179  {
180  struct ByteTagListData *newData = Allocate (spaceNeeded);
181  std::memcpy (&newData->data, &m_data->data, m_used);
182  Deallocate (m_data);
183  m_data = newData;
184  }
185  TagBuffer tag = TagBuffer (&m_data->data[m_used],
186  &m_data->data[spaceNeeded]);
187  tag.WriteU32 (tid.GetUid ());
188  tag.WriteU32 (bufferSize);
189  tag.WriteU32 (start);
190  tag.WriteU32 (end);
191  m_used = spaceNeeded;
192  m_data->dirty = m_used;
193  return tag;
194 }
195 
196 void
198 {
199  NS_LOG_FUNCTION (this << &o);
201  while (i.HasNext ())
202  {
203  ByteTagList::Iterator::Item item = i.Next ();
204  TagBuffer buf = Add (item.tid, item.size, item.start, item.end);
205  buf.CopyFrom (item.buf);
206  }
207 }
208 
209 void
211 {
212  NS_LOG_FUNCTION (this);
213  Deallocate (m_data);
214  m_data = 0;
215  m_used = 0;
216 }
217 
220 {
221  NS_LOG_FUNCTION (this);
222  // I am not totally sure but I might need to use
223  // INT32_MIN instead of zero below.
224  return Begin (0, OFFSET_MAX);
225 }
226 
228 ByteTagList::Begin (int32_t offsetStart, int32_t offsetEnd) const
229 {
230  NS_LOG_FUNCTION (this << offsetStart << offsetEnd);
231  if (m_data == 0)
232  {
233  return Iterator (0, 0, offsetStart, offsetEnd);
234  }
235  else
236  {
237  return Iterator (m_data->data, &m_data->data[m_used], offsetStart, offsetEnd);
238  }
239 }
240 
241 bool
242 ByteTagList::IsDirtyAtEnd (int32_t appendOffset)
243 {
244  NS_LOG_FUNCTION (this << appendOffset);
246  while (i.HasNext ())
247  {
248  ByteTagList::Iterator::Item item = i.Next ();
249  if (item.end > appendOffset)
250  {
251  return true;
252  }
253  }
254  return false;
255 }
256 
257 bool
258 ByteTagList::IsDirtyAtStart (int32_t prependOffset)
259 {
260  NS_LOG_FUNCTION (this << prependOffset);
262  while (i.HasNext ())
263  {
264  ByteTagList::Iterator::Item item = i.Next ();
265  if (item.start < prependOffset)
266  {
267  return true;
268  }
269  }
270  return false;
271 }
272 
273 void
274 ByteTagList::AddAtEnd (int32_t adjustment, int32_t appendOffset)
275 {
276  NS_LOG_FUNCTION (this << adjustment << appendOffset);
277  if (adjustment == 0 && !IsDirtyAtEnd (appendOffset))
278  {
279  return;
280  }
283  while (i.HasNext ())
284  {
285  ByteTagList::Iterator::Item item = i.Next ();
286  item.start += adjustment;
287  item.end += adjustment;
288 
289  if (item.start >= appendOffset)
290  {
291  continue;
292  }
293  else if (item.start < appendOffset && item.end > appendOffset)
294  {
295  item.end = appendOffset;
296  }
297  else
298  {
299  // nothing to do.
300  }
301  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
302  buf.CopyFrom (item.buf);
303  }
304  *this = list;
305 }
306 
307 void
308 ByteTagList::AddAtStart (int32_t adjustment, int32_t prependOffset)
309 {
310  NS_LOG_FUNCTION (this << adjustment << prependOffset);
311  if (adjustment == 0 && !IsDirtyAtStart (prependOffset))
312  {
313  return;
314  }
317  while (i.HasNext ())
318  {
319  ByteTagList::Iterator::Item item = i.Next ();
320  item.start += adjustment;
321  item.end += adjustment;
322 
323  if (item.end <= prependOffset)
324  {
325  continue;
326  }
327  else if (item.end > prependOffset && item.start < prependOffset)
328  {
329  item.start = prependOffset;
330  }
331  else
332  {
333  // nothing to do.
334  }
335  TagBuffer buf = list.Add (item.tid, item.size, item.start, item.end);
336  buf.CopyFrom (item.buf);
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)
Definition: log.h:345
ByteTagList & operator=(const ByteTagList &o)
Assignment operator, deallocates current data and assigns value of passed in ByteTagList.
Iterator(uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd)
struct ByteTagListData * m_data
NS_LOG_COMPONENT_DEFINE("ByteTagList")
keep track of the byte tags stored in a packet.
Definition: byte-tag-list.h:68
#define NS_ASSERT(condition)
Definition: assert.h:64
bool HasNext(void) const
TagBuffer Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
void TrimAtEnd(uint32_t trim)
Definition: tag-buffer.cc:192
TAG_BUFFER_INLINE uint32_t ReadU32(void)
Definition: tag-buffer.h:199
void Deallocate(struct ByteTagListData *data)
#define FREE_LIST_SIZE
void RemoveAll(void)
Removes all of the tags from the ByteTagList.
uint8_t data[writeSize]
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:170
#define OFFSET_MAX
int32_t start
size of tag data
Definition: byte-tag-list.h:90
void AddAtEnd(int32_t adjustment, int32_t appendOffset)
Adjust the offsets stored internally by the adjustment delta and make sure that all offsets are small...
struct ByteTagList::Iterator::Item Next(void)
#define list
struct ByteTagListData * Allocate(uint32_t size)
void SetUid(uint16_t tid)
Definition: type-id.cc:819
uint32_t GetOffsetStart(void) const
int32_t end
offset to the start of the tag from the virtual byte buffer
Definition: byte-tag-list.h:91
uint16_t GetUid(void) const
Definition: type-id.cc:813
ByteTagList::Iterator BeginAll(void) const
uint32_t size
type of the tag
Definition: byte-tag-list.h:89
bool IsDirtyAtStart(int32_t prependOffset)
ByteTagList::Iterator Begin(int32_t offsetStart, int32_t offsetEnd) const
TagBuffer buf
offset to the end of the tag from the virtual byte buffer
Definition: byte-tag-list.h:92
read and write tag data
Definition: tag-buffer.h:51
ns3::ByteTagListDataFreeList g_freeList
Item(TagBuffer buf)
the data for the tag as generated by Tag::Serialize
bool IsDirtyAtEnd(int32_t appendOffset)
static uint32_t g_maxSize
a unique identifier for an interface.
Definition: type-id.h:49
void CopyFrom(TagBuffer o)
Definition: tag-buffer.cc:200
void AddAtStart(int32_t adjustment, int32_t prependOffset)
Adjust the offsets stored internally by the adjustment delta and make sure that all offsets are bigge...