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 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#include "byte-tag-list.h"
9
10#include "ns3/log.h"
11
12#include <cstring>
13#include <limits>
14#include <vector>
15
16#define USE_FREE_LIST 1
17#define FREE_LIST_SIZE 1000
18#define OFFSET_MAX (std::numeric_limits<int32_t>::max())
19
20namespace ns3
21{
22
23NS_LOG_COMPONENT_DEFINE("ByteTagList");
24
25/**
26 * @ingroup packet
27 *
28 * @brief Internal representation of the byte tags stored in a packet.
29 *
30 * This structure is only used by ByteTagList and should not be accessed directly.
31 */
33{
34 uint32_t size; //!< size of the data
35 uint32_t count; //!< use counter (for smart deallocation)
36 uint32_t dirty; //!< number of bytes actually in use
37 uint8_t data[4]; //!< data
38};
39
40#ifdef USE_FREE_LIST
41/**
42 * @ingroup packet
43 *
44 * @brief Container class for struct ByteTagListData
45 *
46 * Internal use only.
47 */
48static class ByteTagListDataFreeList : public std::vector<ByteTagListData*>
49{
50 public:
52} g_freeList; //!< Container for struct ByteTagListData
53
54static uint32_t g_maxSize = 0; //!< maximum data size (used for allocation)
55
57{
58 NS_LOG_FUNCTION(this);
59 for (auto i = begin(); i != end(); i++)
60 {
61 auto buffer = (uint8_t*)(*i);
62 delete[] buffer;
63 }
64}
65#endif /* USE_FREE_LIST */
66
68 : buf(buf_)
69{
70 NS_LOG_FUNCTION(this << &buf_);
71}
72
73bool
75{
76 NS_LOG_FUNCTION(this);
77 return m_current < m_end;
78}
79
82{
84 Item item = Item(TagBuffer(m_current + 16, m_end));
85 item.tid.SetUid(m_nextTid);
86 item.size = m_nextSize;
87 item.start = std::max(m_nextStart, m_offsetStart);
88 item.end = std::min(m_nextEnd, m_offsetEnd);
89 m_current += 4 + 4 + 4 + 4 + item.size;
92 return item;
93}
94
95void
97{
98 NS_LOG_FUNCTION(this);
99 while (m_current < m_end)
100 {
102 m_nextTid = buf.ReadU32();
103 m_nextSize = buf.ReadU32();
107 {
108 m_current += 4 + 4 + 4 + 4 + m_nextSize;
109 }
110 else
111 {
112 break;
113 }
114 }
115}
116
118 uint8_t* end,
119 int32_t offsetStart,
120 int32_t offsetEnd,
121 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);
130}
131
134{
135 NS_LOG_FUNCTION(this);
136 return m_offsetStart;
137}
138
140 : m_minStart(INT32_MAX),
141 m_maxEnd(INT32_MIN),
142 m_adjustment(0),
143 m_used(0),
144 m_data(nullptr)
145{
146 NS_LOG_FUNCTION(this);
147}
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 != nullptr)
158 {
159 m_data->count++;
160 }
161}
162
165{
166 if (this == &o)
167 {
168 return *this;
169 }
170
173 m_maxEnd = o.m_maxEnd;
175 m_data = o.m_data;
176 m_used = o.m_used;
177 if (m_data != nullptr)
178 {
179 m_data->count++;
180 }
181 return *this;
182}
183
185{
186 NS_LOG_FUNCTION(this);
188 m_data = nullptr;
189 m_used = 0;
190}
191
193ByteTagList::Add(TypeId tid, uint32_t bufferSize, int32_t start, int32_t end)
194{
195 NS_LOG_FUNCTION(this << tid << bufferSize << start << end);
196 uint32_t spaceNeeded = m_used + bufferSize + 4 + 4 + 4 + 4;
197 NS_ASSERT(m_used <= spaceNeeded);
198 if (m_data == nullptr)
199 {
200 m_data = Allocate(spaceNeeded);
201 m_used = 0;
202 }
203 else if (m_data->size < spaceNeeded || (m_data->count != 1 && m_data->dirty != m_used))
204 {
205 ByteTagListData* newData = Allocate(spaceNeeded);
206 std::memcpy(&newData->data, &m_data->data, m_used);
208 m_data = newData;
209 }
210 TagBuffer tag = TagBuffer(&m_data->data[m_used], &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;
225 return tag;
226}
227
228void
230{
231 NS_LOG_FUNCTION(this << &o);
233 while (i.HasNext())
234 {
236 TagBuffer buf = Add(item.tid, item.size, item.start, item.end);
237 buf.CopyFrom(item.buf);
238 }
239}
240
241void
243{
244 NS_LOG_FUNCTION(this);
246 m_minStart = INT32_MAX;
247 m_maxEnd = INT32_MIN;
248 m_adjustment = 0;
249 m_data = nullptr;
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
263ByteTagList::Begin(int32_t offsetStart, int32_t offsetEnd) const
264{
265 NS_LOG_FUNCTION(this << offsetStart << offsetEnd);
266 if (m_data == nullptr)
267 {
268 return Iterator(nullptr, nullptr, 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
276void
278{
279 NS_LOG_FUNCTION(this << appendOffset);
280 if (m_maxEnd <= appendOffset - m_adjustment)
281 {
282 return;
283 }
286 while (i.HasNext())
287 {
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
308void
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 {
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
345{
346 NS_LOG_FUNCTION(this << size);
347 while (!g_freeList.empty())
348 {
350 g_freeList.pop_back();
351 NS_ASSERT(data != nullptr);
352 if (data->size >= size)
353 {
354 data->count = 1;
355 data->dirty = 0;
356 return data;
357 }
358 auto buffer = (uint8_t*)data;
359 delete[] buffer;
360 }
361 auto buffer = new uint8_t[std::max(size, g_maxSize) + sizeof(ByteTagListData) - 4];
362 auto data = (ByteTagListData*)buffer;
363 data->count = 1;
364 data->size = size;
365 data->dirty = 0;
366 return data;
367}
368
369void
371{
372 NS_LOG_FUNCTION(this << data);
373 if (data == nullptr)
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 || data->size < g_maxSize)
382 {
383 auto buffer = (uint8_t*)data;
384 delete[] buffer;
385 }
386 else
387 {
388 g_freeList.push_back(data);
389 }
390 }
391}
392
393#else /* USE_FREE_LIST */
394
397{
398 NS_LOG_FUNCTION(this << size);
399 uint8_t* buffer = new uint8_t[size + sizeof(ByteTagListData) - 4];
401 data->count = 1;
402 data->size = size;
403 data->dirty = 0;
404 return data;
405}
406
407void
408ByteTagList::Deallocate(ByteTagListData* data)
409{
410 NS_LOG_FUNCTION(this << data);
411 if (data == 0)
412 {
413 return;
414 }
415 data->count--;
416 if (data->count == 0)
417 {
418 uint8_t* buffer = (uint8_t*)data;
419 delete[] buffer;
420 }
421}
422
423#endif /* USE_FREE_LIST */
424
427{
429
430 uint32_t size = 0;
431
432 // Number of tags in list
433 size += 4; // numberOfTags
434
436 while (i.HasNext())
437 {
439
440 // TypeId hash; ensure size is multiple of 4 bytes
441 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
442 size += hashSize;
443
444 size += 3 * 4; // size, start, end
445
446 // tag data; ensure size is multiple of 4 bytes
447 uint32_t tagWordSize = (item.size + 3) & (~3);
448 size += tagWordSize;
449 }
450
451 return size;
452}
453
456{
457 NS_LOG_FUNCTION(this << buffer << maxSize);
458
459 uint32_t* p = buffer;
460 uint32_t size = 0;
461
462 size += 4;
463
464 if (size > maxSize)
465 {
466 return 0;
467 }
468
469 uint32_t* numberOfTags = p;
470 *p++ = 0;
471
473 while (i.HasNext())
474 {
476
477 NS_LOG_INFO("Serializing " << item.tid);
478
479 // ensure size is multiple of 4 bytes for 4 byte boundaries
480 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
481 size += hashSize;
482
483 if (size > maxSize)
484 {
485 return 0;
486 }
487
488 TypeId::hash_t tid = item.tid.GetHash();
489 memcpy(p, &tid, sizeof(TypeId::hash_t));
490 p += hashSize / 4;
491
492 size += 4;
493
494 if (size > maxSize)
495 {
496 return 0;
497 }
498
499 *p++ = item.size;
500
501 size += 4;
502
503 if (size > maxSize)
504 {
505 return 0;
506 }
507
508 *p++ = item.start;
509
510 size += 4;
511
512 if (size > maxSize)
513 {
514 return 0;
515 }
516
517 *p++ = item.end;
518
519 // ensure size is multiple of 4 bytes for 4 byte boundaries
520 uint32_t tagWordSize = (item.size + 3) & (~3);
521 size += tagWordSize;
522
523 if (size > maxSize)
524 {
525 return 0;
526 }
527
528 item.buf.Read(reinterpret_cast<uint8_t*>(p), item.size);
529 p += tagWordSize / 4;
530
531 (*numberOfTags)++;
532 }
533
534 // Serialized successfully
535 return 1;
536}
537
540{
541 NS_LOG_FUNCTION(this << buffer << size);
542 const uint32_t* p = buffer;
543 uint32_t sizeCheck = size - 4;
544
545 NS_ASSERT(sizeCheck >= 4);
546 uint32_t numberTagData = *p++;
547 sizeCheck -= 4;
548
549 NS_LOG_INFO("Deserializing number of tags " << numberTagData);
550
551 for (uint32_t i = 0; i < numberTagData; ++i)
552 {
553 uint32_t hashSize = (sizeof(TypeId::hash_t) + 3) & (~3);
554 NS_ASSERT(sizeCheck >= hashSize);
555 TypeId::hash_t hash;
556 memcpy(&hash, p, sizeof(TypeId::hash_t));
557 p += hashSize / 4;
558 sizeCheck -= hashSize;
559
560 TypeId tid = TypeId::LookupByHash(hash);
561
562 NS_ASSERT(sizeCheck >= 4);
563 uint32_t bufferSize = *p++;
564 sizeCheck -= 4;
565
566 NS_ASSERT(sizeCheck >= 4);
567 uint32_t start = *p++;
568 sizeCheck -= 4;
569
570 NS_ASSERT(sizeCheck >= 4);
571 uint32_t end = *p++;
572 sizeCheck -= 4;
573
574 NS_ASSERT(sizeCheck >= bufferSize);
575 TagBuffer buf = Add(tid, bufferSize, start, end);
576 buf.Write(reinterpret_cast<const uint8_t*>(p), bufferSize);
577
578 // ensure 4 byte boundary
579 uint32_t tagSizeBytes = (bufferSize + 3) & (~3);
580 sizeCheck -= tagSizeBytes;
581 p += tagSizeBytes / 4;
582 }
583
584 NS_ASSERT(sizeCheck == 0);
585
586 // return zero if buffer did not
587 // contain a complete message
588 return (sizeCheck != 0) ? 0 : 1;
589}
590
591} // namespace ns3
#define FREE_LIST_SIZE
#define OFFSET_MAX
An iterator for iterating through a byte tag list.
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.
Container class for struct ByteTagListData.
keep track of the byte tags stored in a packet.
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:41
TAG_BUFFER_INLINE uint32_t ReadU32()
Definition tag-buffer.h:206
void TrimAtEnd(uint32_t trim)
Trim some space from the end.
void Read(uint8_t *buffer, uint32_t size)
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition tag-buffer.h:176
void Write(const uint8_t *buffer, uint32_t size)
void CopyFrom(TagBuffer o)
Copy the nternal structure of another TagBuffer.
a unique identifier for an interface.
Definition type-id.h:48
hash_t GetHash() const
Get the hash.
Definition type-id.cc:1069
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition type-id.cc:1282
static TypeId LookupByHash(hash_t hash)
Get a TypeId by hash.
Definition type-id.cc:904
uint32_t hash_t
Type of hash values.
Definition type-id.h:109
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition type-id.cc:1275
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#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:264
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.
TagBuffer buf
the data for the tag as generated by Tag::Serialize
uint32_t size
size of tag data
int32_t end
offset to the end of the tag from the virtual byte buffer
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
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