A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
byte-tag-list.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2008 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "byte-tag-list.h"
20
21#include "ns3/log.h"
22
23#include <cstring>
24#include <limits>
25#include <vector>
26
27#define USE_FREE_LIST 1
28#define FREE_LIST_SIZE 1000
29#define OFFSET_MAX (std::numeric_limits<int32_t>::max())
30
31namespace ns3
32{
33
34NS_LOG_COMPONENT_DEFINE("ByteTagList");
35
44{
48 uint8_t data[4];
49};
50
51#ifdef USE_FREE_LIST
59static class ByteTagListDataFreeList : public std::vector<ByteTagListData*>
60{
61 public:
64
65static uint32_t g_maxSize = 0;
66
68{
69 NS_LOG_FUNCTION(this);
70 for (auto i = begin(); i != end(); i++)
71 {
72 auto buffer = (uint8_t*)(*i);
73 delete[] buffer;
74 }
75}
76#endif /* USE_FREE_LIST */
77
79 : buf(buf_)
80{
81 NS_LOG_FUNCTION(this << &buf_);
82}
83
84bool
86{
87 NS_LOG_FUNCTION(this);
88 return m_current < m_end;
89}
90
93{
95 Item item = Item(TagBuffer(m_current + 16, m_end));
96 item.tid.SetUid(m_nextTid);
97 item.size = m_nextSize;
98 item.start = std::max(m_nextStart, m_offsetStart);
99 item.end = std::min(m_nextEnd, m_offsetEnd);
100 m_current += 4 + 4 + 4 + 4 + item.size;
103 return item;
104}
105
106void
108{
109 NS_LOG_FUNCTION(this);
110 while (m_current < m_end)
111 {
113 m_nextTid = buf.ReadU32();
114 m_nextSize = buf.ReadU32();
118 {
119 m_current += 4 + 4 + 4 + 4 + m_nextSize;
120 }
121 else
122 {
123 break;
124 }
125 }
126}
127
129 uint8_t* end,
130 int32_t offsetStart,
131 int32_t offsetEnd,
132 int32_t adjustment)
133 : m_current(start),
134 m_end(end),
135 m_offsetStart(offsetStart),
136 m_offsetEnd(offsetEnd),
137 m_adjustment(adjustment)
138{
139 NS_LOG_FUNCTION(this << &start << &end << offsetStart << offsetEnd << adjustment);
141}
142
145{
146 NS_LOG_FUNCTION(this);
147 return m_offsetStart;
148}
149
151 : m_minStart(INT32_MAX),
152 m_maxEnd(INT32_MIN),
153 m_adjustment(0),
154 m_used(0),
155 m_data(nullptr)
156{
157 NS_LOG_FUNCTION(this);
158}
159
161 : m_minStart(o.m_minStart),
162 m_maxEnd(o.m_maxEnd),
163 m_adjustment(o.m_adjustment),
164 m_used(o.m_used),
165 m_data(o.m_data)
166{
167 NS_LOG_FUNCTION(this << &o);
168 if (m_data != nullptr)
169 {
170 m_data->count++;
171 }
172}
173
176{
177 if (this == &o)
178 {
179 return *this;
180 }
181
184 m_maxEnd = o.m_maxEnd;
186 m_data = o.m_data;
187 m_used = o.m_used;
188 if (m_data != nullptr)
189 {
190 m_data->count++;
191 }
192 return *this;
193}
194
196{
197 NS_LOG_FUNCTION(this);
199 m_data = nullptr;
200 m_used = 0;
201}
202
204ByteTagList::Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
205{
206 NS_LOG_FUNCTION(this << tid << bufferSize << start << end);
207 uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
208 NS_ASSERT(m_used <= spaceNeeded);
209 if (m_data == nullptr)
210 {
211 m_data = Allocate(spaceNeeded);
212 m_used = 0;
213 }
214 else if (m_data->size < spaceNeeded || (m_data->count != 1 && m_data->dirty != m_used))
215 {
216 ByteTagListData* newData = Allocate(spaceNeeded);
217 std::memcpy(&newData->data, &m_data->data, m_used);
219 m_data = newData;
220 }
221 TagBuffer tag = TagBuffer(&m_data->data[m_used], &m_data->data[spaceNeeded]);
222 tag.WriteU32(tid.GetUid());
223 tag.WriteU32(bufferSize);
224 tag.WriteU32(start - m_adjustment);
225 tag.WriteU32(end - m_adjustment);
226 if (start - m_adjustment < m_minStart)
227 {
228 m_minStart = start - m_adjustment;
229 }
230 if (end - m_adjustment > m_maxEnd)
231 {
232 m_maxEnd = end - m_adjustment;
233 }
234 m_used = spaceNeeded;
236 return tag;
237}
238
239void
241{
242 NS_LOG_FUNCTION(this << &o);
244 while (i.HasNext())
245 {
247 TagBuffer buf = Add(item.tid, item.size, item.start, item.end);
248 buf.CopyFrom(item.buf);
249 }
250}
251
252void
254{
255 NS_LOG_FUNCTION(this);
257 m_minStart = INT32_MAX;
258 m_maxEnd = INT32_MIN;
259 m_adjustment = 0;
260 m_data = nullptr;
261 m_used = 0;
262}
263
266{
267 NS_LOG_FUNCTION(this);
268 // I am not totally sure but I might need to use
269 // INT32_MIN instead of zero below.
270 return Begin(0, OFFSET_MAX);
271}
272
274ByteTagList::Begin(int32_t offsetStart, int32_t offsetEnd) const
275{
276 NS_LOG_FUNCTION(this << offsetStart << offsetEnd);
277 if (m_data == nullptr)
278 {
279 return Iterator(nullptr, nullptr, offsetStart, offsetEnd, 0);
280 }
281 else
282 {
283 return Iterator(m_data->data, &m_data->data[m_used], offsetStart, offsetEnd, m_adjustment);
284 }
285}
286
287void
289{
290 NS_LOG_FUNCTION(this << appendOffset);
291 if (m_maxEnd <= appendOffset - m_adjustment)
292 {
293 return;
294 }
297 while (i.HasNext())
298 {
300
301 if (item.start >= appendOffset)
302 {
303 continue;
304 }
305 if (item.end > appendOffset)
306 {
307 item.end = appendOffset;
308 }
309 TagBuffer buf = list.Add(item.tid, item.size, item.start, item.end);
310 buf.CopyFrom(item.buf);
311 if (item.end > m_maxEnd)
312 {
313 m_maxEnd = item.end;
314 }
315 }
316 *this = list;
317}
318
319void
321{
322 NS_LOG_FUNCTION(this << prependOffset);
323 if (m_minStart >= prependOffset - m_adjustment)
324 {
325 return;
326 }
327 m_minStart = INT32_MAX;
330 while (i.HasNext())
331 {
333
334 if (item.end <= prependOffset)
335 {
336 continue;
337 }
338 if (item.start < prependOffset)
339 {
340 item.start = prependOffset;
341 }
342 TagBuffer buf = list.Add(item.tid, item.size, item.start, item.end);
343 buf.CopyFrom(item.buf);
344 if (item.start < m_minStart)
345 {
346 m_minStart = item.start;
347 }
348 }
349 *this = list;
350}
351
352#ifdef USE_FREE_LIST
353
356{
357 NS_LOG_FUNCTION(this << size);
358 while (!g_freeList.empty())
359 {
361 g_freeList.pop_back();
362 NS_ASSERT(data != nullptr);
363 if (data->size >= size)
364 {
365 data->count = 1;
366 data->dirty = 0;
367 return data;
368 }
369 auto buffer = (uint8_t*)data;
370 delete[] buffer;
371 }
372 auto buffer = new uint8_t[std::max(size, g_maxSize) + sizeof(ByteTagListData) - 4];
373 auto data = (ByteTagListData*)buffer;
374 data->count = 1;
375 data->size = size;
376 data->dirty = 0;
377 return data;
378}
379
380void
382{
383 NS_LOG_FUNCTION(this << data);
384 if (data == nullptr)
385 {
386 return;
387 }
388 g_maxSize = std::max(g_maxSize, data->size);
389 data->count--;
390 if (data->count == 0)
391 {
392 if (g_freeList.size() > FREE_LIST_SIZE || data->size < g_maxSize)
393 {
394 auto buffer = (uint8_t*)data;
395 delete[] buffer;
396 }
397 else
398 {
399 g_freeList.push_back(data);
400 }
401 }
402}
403
404#else /* USE_FREE_LIST */
405
408{
409 NS_LOG_FUNCTION(this << size);
410 uint8_t* buffer = new uint8_t[size + sizeof(ByteTagListData) - 4];
412 data->count = 1;
413 data->size = size;
414 data->dirty = 0;
415 return data;
416}
417
418void
419ByteTagList::Deallocate(ByteTagListData* data)
420{
421 NS_LOG_FUNCTION(this << data);
422 if (data == 0)
423 {
424 return;
425 }
426 data->count--;
427 if (data->count == 0)
428 {
429 uint8_t* buffer = (uint8_t*)data;
430 delete[] buffer;
431 }
432}
433
434#endif /* USE_FREE_LIST */
435
438{
440
441 uint32_t size = 0;
442
443 // Number of tags in list
444 size += 4; // numberOfTags
445
447 while (i.HasNext())
448 {
450
451 // TypeId hash; ensure size is multiple of 4 bytes
452 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
453 size += hashSize;
454
455 size += 3 * 4; // size, start, end
456
457 // tag data; ensure size is multiple of 4 bytes
458 uint32_t tagWordSize = (item.size + 3) & (~3);
459 size += tagWordSize;
460 }
461
462 return size;
463}
464
467{
468 NS_LOG_FUNCTION(this << buffer << maxSize);
469
470 uint32_t* p = buffer;
471 uint32_t size = 0;
472
473 size += 4;
474
475 if (size > maxSize)
476 {
477 return 0;
478 }
479
480 uint32_t* numberOfTags = p;
481 *p++ = 0;
482
484 while (i.HasNext())
485 {
487
488 NS_LOG_INFO("Serializing " << item.tid);
489
490 // ensure size is multiple of 4 bytes for 4 byte boundaries
491 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
492 size += hashSize;
493
494 if (size > maxSize)
495 {
496 return 0;
497 }
498
499 TypeId::hash_t tid = item.tid.GetHash();
500 memcpy(p, &tid, sizeof(TypeId::hash_t));
501 p += hashSize / 4;
502
503 size += 4;
504
505 if (size > maxSize)
506 {
507 return 0;
508 }
509
510 *p++ = item.size;
511
512 size += 4;
513
514 if (size > maxSize)
515 {
516 return 0;
517 }
518
519 *p++ = item.start;
520
521 size += 4;
522
523 if (size > maxSize)
524 {
525 return 0;
526 }
527
528 *p++ = item.end;
529
530 // ensure size is multiple of 4 bytes for 4 byte boundaries
531 uint32_t tagWordSize = (item.size + 3) & (~3);
532 size += tagWordSize;
533
534 if (size > maxSize)
535 {
536 return 0;
537 }
538
539 item.buf.Read(reinterpret_cast<uint8_t*>(p), item.size);
540 p += tagWordSize / 4;
541
542 (*numberOfTags)++;
543 }
544
545 // Serialized successfully
546 return 1;
547}
548
551{
552 NS_LOG_FUNCTION(this << buffer << size);
553 const uint32_t* p = buffer;
554 uint32_t sizeCheck = size - 4;
555
556 NS_ASSERT(sizeCheck >= 4);
557 uint32_t numberTagData = *p++;
558 sizeCheck -= 4;
559
560 NS_LOG_INFO("Deserializing number of tags " << numberTagData);
561
562 for (uint32_t i = 0; i < numberTagData; ++i)
563 {
564 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
565 NS_ASSERT(sizeCheck >= hashSize);
566 TypeId::hash_t hash;
567 memcpy(&hash, p, sizeof(TypeId::hash_t));
568 p += hashSize / 4;
569 sizeCheck -= hashSize;
570
571 TypeId tid = TypeId::LookupByHash(hash);
572
573 NS_ASSERT(sizeCheck >= 4);
574 uint32_t bufferSize = *p++;
575 sizeCheck -= 4;
576
577 NS_ASSERT(sizeCheck >= 4);
578 uint32_t start = *p++;
579 sizeCheck -= 4;
580
581 NS_ASSERT(sizeCheck >= 4);
582 uint32_t end = *p++;
583 sizeCheck -= 4;
584
585 NS_ASSERT(sizeCheck >= bufferSize);
586 TagBuffer buf = Add(tid, bufferSize, start, end);
587 buf.Write(reinterpret_cast<const uint8_t*>(p), bufferSize);
588
589 // ensure 4 byte boundary
590 uint32_t tagSizeBytes = (bufferSize + 3) & (~3);
591 sizeCheck -= tagSizeBytes;
592 p += tagSizeBytes / 4;
593 }
594
595 NS_ASSERT(sizeCheck == 0);
596
597 // return zero if buffer did not
598 // contain a complete message
599 return (sizeCheck != 0) ? 0 : 1;
600}
601
602} // namespace ns3
#define FREE_LIST_SIZE
#define OFFSET_MAX
An iterator for iterating through a byte tag list.
Definition: byte-tag-list.h:75
uint8_t * m_current
Current tag.
int32_t m_adjustment
Adjustment to byte tag offsets.
int32_t m_offsetEnd
Offset to the end of the tag from the virtual byte buffer.
ByteTagList::Iterator::Item Next()
Returns the next Item from the ByteTagList.
void PrepareForNext()
Prepare the iterator for the next tag.
int32_t m_nextEnd
End of the next tag.
uint32_t GetOffsetStart() const
Returns the offset from the start of the virtual byte buffer to the ByteTagList.
int32_t m_nextStart
Start of the next tag.
int32_t m_offsetStart
Offset to the start of the tag from the virtual byte buffer.
uint32_t m_nextSize
Size of the next tag.
Iterator(uint8_t *start, uint8_t *end, int32_t offsetStart, int32_t offsetEnd, int32_t adjustment)
Constructor.
bool HasNext() const
Used to determine if the iterator is at the end of the byteTagList.
uint32_t m_nextTid
TypeId of the next tag.
uint8_t * m_end
End tag.
Container class for struct ByteTagListData.
keep track of the byte tags stored in a packet.
Definition: byte-tag-list.h:66
uint32_t Deserialize(const uint32_t *buffer, uint32_t size)
Deserialize tag list from the provided buffer.
void AddAtEnd(int32_t appendOffset)
Make sure that all offsets are smaller than appendOffset which represents the location where new byte...
void Deallocate(ByteTagListData *data)
Deallocates a ByteTagListData.
ByteTagList & operator=(const ByteTagList &o)
Assignment operator, deallocates current data and assigns value of passed in ByteTagList.
ByteTagList::Iterator Begin(int32_t offsetStart, int32_t offsetEnd) const
int32_t m_minStart
minimal start offset
uint32_t m_used
the number of used bytes in the buffer
ByteTagListData * Allocate(uint32_t size)
Allocate the memory for the ByteTagListData.
ByteTagList::Iterator BeginAll() const
Returns an iterator pointing to the very first tag in this list.
void RemoveAll()
Removes all of the tags from the ByteTagList.
int32_t m_adjustment
adjustment to byte tag offsets
TagBuffer Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
uint32_t Serialize(uint32_t *buffer, uint32_t maxSize) const
Serialize the tag list into a byte buffer.
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
ByteTagListData * m_data
the ByteTagListData structure
uint32_t GetSerializedSize() const
Returns number of bytes required for packet serialization.
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE uint32_t ReadU32()
Definition: tag-buffer.h:217
void TrimAtEnd(uint32_t trim)
Trim some space from the end.
Definition: tag-buffer.cc:199
void Read(uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:183
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition: tag-buffer.h:187
void Write(const uint8_t *buffer, uint32_t size)
Definition: tag-buffer.cc:129
void CopyFrom(TagBuffer o)
Copy the nternal structure of another TagBuffer.
Definition: tag-buffer.cc:207
a unique identifier for an interface.
Definition: type-id.h:59
hash_t GetHash() const
Get the hash.
Definition: type-id.cc:1000
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1213
static TypeId LookupByHash(hash_t hash)
Get a TypeId by hash.
Definition: type-id.cc:858
uint32_t hash_t
Type of hash values.
Definition: type-id.h:120
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1206
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
ns3::ByteTagListDataFreeList g_freeList
Container for struct ByteTagListData.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
static uint32_t g_maxSize
maximum data size (used for allocation)
#define list
uint8_t data[writeSize]
An item specifies an individual tag within a byte buffer.
Definition: byte-tag-list.h:84
TypeId tid
type of the tag
Definition: byte-tag-list.h:85
TagBuffer buf
the data for the tag as generated by Tag::Serialize
Definition: byte-tag-list.h:89
uint32_t size
size of tag data
Definition: byte-tag-list.h:86
int32_t end
offset to the end of the tag from the virtual byte buffer
Definition: byte-tag-list.h:88
Item(TagBuffer buf)
Constructs an item with the given TagBuffer.
int32_t start
offset to the start of the tag from the virtual byte buffer
Definition: byte-tag-list.h:87
Internal representation of the byte tags stored in a packet.
uint32_t dirty
number of bytes actually in use
uint32_t size
size of the data
uint32_t count
use counter (for smart deallocation)
uint8_t data[4]
data