A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
packet-metadata.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2006,2007 INRIA
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
7 */
8#include "packet-metadata.h"
9
10#include "buffer.h"
11#include "header.h"
12#include "trailer.h"
13
14#include "ns3/assert.h"
15#include "ns3/fatal-error.h"
16#include "ns3/log.h"
17
18#include <list>
19#include <utility>
20
21namespace ns3
22{
23
24NS_LOG_COMPONENT_DEFINE("PacketMetadata");
25
26bool PacketMetadata::m_enable = false;
29uint32_t PacketMetadata::m_maxSize = 0;
32
34{
35 NS_LOG_FUNCTION(this);
36 for (auto i = begin(); i != end(); i++)
37 {
39 }
41}
42
43void
45{
48 "Error: attempting to enable the packet metadata "
49 "subsystem too late in the simulation, which is not allowed.\n"
50 "A common cause for this problem is to enable ASCII tracing "
51 "after sending any packets. One way to fix this problem is "
52 "to call ns3::PacketMetadata::Enable () near the beginning of"
53 " the program, before any packets are sent.");
54 m_enable = true;
55}
56
57void
64
65void
67{
68 NS_LOG_FUNCTION(this << size);
70 memcpy(newData->m_data, m_data->m_data, m_used);
71 newData->m_dirtyEnd = m_used;
72 m_data->m_count--;
73 if (m_data->m_count == 0)
74 {
76 }
77 m_data = newData;
78 if (m_head != 0xffff)
79 {
80 uint8_t* start;
81 NS_ASSERT(m_tail != 0xffff);
82 // clear the next field of the tail
83 start = &m_data->m_data[m_tail];
84 Append16(0xffff, start);
85 // clear the prev field of the head
86 start = &m_data->m_data[m_head] + 2;
87 Append16(0xffff, start);
88 }
89}
90
91void
93{
94 NS_LOG_FUNCTION(this << size);
95 NS_ASSERT(m_data != nullptr);
96 if (m_data->m_size >= m_used + size &&
97 (m_head == 0xffff || m_data->m_count == 1 || m_data->m_dirtyEnd == m_used))
98 {
99 /* enough room, not dirty. */
100 }
101 else
102 {
103 /* (enough room and dirty) or (not enough room) */
104 ReserveCopy(size);
105 }
106}
107
108bool
110{
111 bool ok = pointer == 0xffff || pointer <= m_data->m_size;
112 return ok;
113}
114
115bool
116PacketMetadata::IsPointerOk(uint16_t pointer) const
117{
118 bool ok = pointer == 0xffff || pointer <= m_used;
119 return ok;
120}
121
122bool
124{
125 NS_LOG_FUNCTION(this);
126 bool ok = m_used <= m_data->m_size;
127 ok &= IsPointerOk(m_head);
128 ok &= IsPointerOk(m_tail);
129 uint16_t current = m_head;
130 while (ok && current != 0xffff)
131 {
134 ReadItems(current, &item, &extraItem);
135 ok &= IsSharedPointerOk(item.next);
136 ok &= IsSharedPointerOk(item.prev);
137 if (current != m_head)
138 {
139 ok &= IsPointerOk(item.prev);
140 }
141 if (current != m_tail)
142 {
143 ok &= IsPointerOk(item.next);
144 }
145 if (current == m_tail)
146 {
147 break;
148 }
149 current = item.next;
150 }
151 return ok;
152}
153
156{
157 NS_LOG_FUNCTION(this << value);
158 if (value < 0x80)
159 {
160 return 1;
161 }
162 if (value < 0x4000)
163 {
164 return 2;
165 }
166 if (value < 0x200000)
167 {
168 return 3;
169 }
170 if (value < 0x10000000)
171 {
172 return 4;
173 }
174 return 5;
175}
176
178PacketMetadata::ReadUleb128(const uint8_t** pBuffer) const
179{
180 NS_LOG_FUNCTION(this << &pBuffer);
181 const uint8_t* buffer = *pBuffer;
182 uint32_t result;
183 uint8_t byte;
184
185 byte = buffer[0];
186 result = (byte & (~0x80));
187 if (!(byte & 0x80))
188 {
189 *pBuffer = buffer + 1;
190 return result;
191 }
192 byte = buffer[1];
193 result |= (byte & (~0x80)) << 7;
194 if (!(byte & 0x80))
195 {
196 *pBuffer = buffer + 2;
197 return result;
198 }
199 byte = buffer[2];
200 result |= (byte & (~0x80)) << 14;
201 if (!(byte & 0x80))
202 {
203 *pBuffer = buffer + 3;
204 return result;
205 }
206 byte = buffer[3];
207 result |= (byte & (~0x80)) << 21;
208 if (!(byte & 0x80))
209 {
210 *pBuffer = buffer + 4;
211 return result;
212 }
213 byte = buffer[4];
214 result |= (byte & (~0x80)) << 28;
215 if (!(byte & 0x80))
216 {
217 *pBuffer = buffer + 5;
218 return result;
219 }
220 /* This means that the LEB128 number was not valid.
221 * ie: the last (5th) byte did not have the high-order bit zeroed.
222 */
223 NS_ASSERT(false);
224 return 0;
225}
226
227void
228PacketMetadata::Append16(uint16_t value, uint8_t* buffer)
229{
230 NS_LOG_FUNCTION(this << value << &buffer);
231 buffer[0] = value & 0xff;
232 value >>= 8;
233 buffer[1] = value;
234}
235
236void
237PacketMetadata::Append32(uint32_t value, uint8_t* buffer)
238{
239 NS_LOG_FUNCTION(this << value << &buffer);
240 buffer[0] = value & 0xff;
241 buffer[1] = (value >> 8) & 0xff;
242 buffer[2] = (value >> 16) & 0xff;
243 buffer[3] = (value >> 24) & 0xff;
244}
245
246void
248{
249 NS_LOG_FUNCTION(this << value << &buffer);
250 if (value < 0x200000)
251 {
252 uint8_t byte = value & (~0x80);
253 buffer[0] = 0x80 | byte;
254 value >>= 7;
255 byte = value & (~0x80);
256 buffer[1] = 0x80 | byte;
257 value >>= 7;
258 buffer[2] = value;
259 return;
260 }
261 if (value < 0x10000000)
262 {
263 uint8_t byte = value & (~0x80);
264 buffer[0] = 0x80 | byte;
265 value >>= 7;
266 byte = value & (~0x80);
267 buffer[1] = 0x80 | byte;
268 value >>= 7;
269 byte = value & (~0x80);
270 buffer[2] = 0x80 | byte;
271 value >>= 7;
272 buffer[3] = value;
273 return;
274 }
275 {
276 uint8_t byte = value & (~0x80);
277 buffer[0] = 0x80 | byte;
278 value >>= 7;
279 byte = value & (~0x80);
280 buffer[1] = 0x80 | byte;
281 value >>= 7;
282 byte = value & (~0x80);
283 buffer[2] = 0x80 | byte;
284 value >>= 7;
285 byte = value & (~0x80);
286 buffer[3] = 0x80 | byte;
287 value >>= 7;
288 buffer[4] = value;
289 }
290}
291
292void
294{
295 NS_LOG_FUNCTION(this << value << &buffer);
296 if (value < 0x80)
297 {
298 buffer[0] = value;
299 return;
300 }
301 if (value < 0x4000)
302 {
303 uint8_t byte = value & (~0x80);
304 buffer[0] = 0x80 | byte;
305 value >>= 7;
306 buffer[1] = value;
307 return;
308 }
309 AppendValueExtra(value, buffer);
310}
311
312void
314{
315 NS_LOG_FUNCTION(this << written);
316 if (m_head == 0xffff)
317 {
318 NS_ASSERT(m_tail == 0xffff);
319 m_head = m_used;
320 m_tail = m_used;
321 }
322 else
323 {
324 NS_ASSERT(m_tail != 0xffff);
325 // overwrite the next field of the previous tail of the list.
326 uint8_t* previousTail = &m_data->m_data[m_tail];
327 Append16(m_used, previousTail);
328 // update the tail of the list to the new node.
329 m_tail = m_used;
330 }
331 NS_ASSERT(m_tail != 0xffff);
332 NS_ASSERT(m_head != 0xffff);
333 NS_ASSERT(written >= 8);
334 m_used += written;
335 m_data->m_dirtyEnd = m_used;
336}
337
338void
340{
341 NS_LOG_FUNCTION(this << written);
342 if (m_head == 0xffff)
343 {
344 NS_ASSERT(m_tail == 0xffff);
345 m_head = m_used;
346 m_tail = m_used;
347 }
348 else
349 {
350 NS_ASSERT(m_head != 0xffff);
351 // overwrite the prev field of the previous head of the list.
352 uint8_t* previousHead = &m_data->m_data[m_head + 2];
353 Append16(m_used, previousHead);
354 // update the head of list to the new node.
355 m_head = m_used;
356 }
357 NS_ASSERT(m_tail != 0xffff);
358 NS_ASSERT(m_head != 0xffff);
359 NS_ASSERT(written >= 8);
360 m_used += written;
361 m_data->m_dirtyEnd = m_used;
362}
363
364uint16_t
366{
367 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
368 << item->chunkUid);
369 NS_ASSERT(m_data != nullptr);
370 NS_ASSERT(m_used != item->prev && m_used != item->next);
371 uint32_t typeUidSize = GetUleb128Size(item->typeUid);
372 uint32_t sizeSize = GetUleb128Size(item->size);
373 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
374 if (m_used + n > m_data->m_size ||
375 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
376 {
377 ReserveCopy(n);
378 }
379 uint8_t* buffer = &m_data->m_data[m_used];
380 Append16(item->next, buffer);
381 buffer += 2;
382 Append16(item->prev, buffer);
383 buffer += 2;
384 AppendValue(item->typeUid, buffer);
385 buffer += typeUidSize;
386 AppendValue(item->size, buffer);
387 buffer += sizeSize;
388 Append16(item->chunkUid, buffer);
389 return n;
390}
391
392uint16_t
395 const PacketMetadata::SmallItem* item,
396 const PacketMetadata::ExtraItem* extraItem)
397{
398 NS_LOG_FUNCTION(this << next << prev << item->next << item->prev << item->typeUid << item->size
399 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
400 << extraItem->packetUid);
401 NS_ASSERT(m_data != nullptr);
402 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
403 NS_ASSERT(m_used != prev && m_used != next);
404
405 uint32_t typeUidSize = GetUleb128Size(typeUid);
406 uint32_t sizeSize = GetUleb128Size(item->size);
407 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
408 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
409 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
410
411 if (m_used + n > m_data->m_size ||
412 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
413 {
414 ReserveCopy(n);
415 }
416
417 uint8_t* buffer = &m_data->m_data[m_used];
418
419 Append16(next, buffer);
420 buffer += 2;
421 Append16(prev, buffer);
422 buffer += 2;
423 AppendValue(typeUid, buffer);
424 buffer += typeUidSize;
425 AppendValue(item->size, buffer);
426 buffer += sizeSize;
427 Append16(item->chunkUid, buffer);
428 buffer += 2;
429 AppendValue(extraItem->fragmentStart, buffer);
430 buffer += fragStartSize;
431 AppendValue(extraItem->fragmentEnd, buffer);
432 buffer += fragEndSize;
433 Append32(extraItem->packetUid, buffer);
434
435 return n;
436}
437
438void
440 PacketMetadata::ExtraItem* extraItem,
441 uint32_t available)
442{
443 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
444 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
445 << extraItem->packetUid << available);
446
447 NS_ASSERT(m_data != nullptr);
448 /* If the tail we want to replace is located at the end of the data array,
449 * and if there is extra room at the end of this array, then,
450 * we can try to use that extra space to avoid falling in the slow
451 * path below.
452 */
453 if (m_tail + available == m_used && m_used == m_data->m_dirtyEnd)
454 {
455 available = m_data->m_size - m_tail;
456 }
457
458 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
459 uint32_t typeUidSize = GetUleb128Size(typeUid);
460 uint32_t sizeSize = GetUleb128Size(item->size);
461 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
462 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
463 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
464
465 if (available >= n && m_data->m_count == 1)
466 {
467 uint8_t* buffer = &m_data->m_data[m_tail];
468 Append16(item->next, buffer);
469 buffer += 2;
470 Append16(item->prev, buffer);
471 buffer += 2;
472 AppendValue(typeUid, buffer);
473 buffer += typeUidSize;
474 AppendValue(item->size, buffer);
475 buffer += sizeSize;
476 Append16(item->chunkUid, buffer);
477 buffer += 2;
478 AppendValue(extraItem->fragmentStart, buffer);
479 buffer += fragStartSize;
480 AppendValue(extraItem->fragmentEnd, buffer);
481 buffer += fragEndSize;
482 Append32(extraItem->packetUid, buffer);
483 m_used = std::max(m_used, static_cast<uint32_t>(buffer - &m_data->m_data[0]));
484 m_data->m_dirtyEnd = m_used;
485 return;
486 }
487
488 /* Below is the slow path which is hit if the new tail we want
489 * to append is bigger than the previous tail.
490 */
491
492 // create a copy of the packet without its tail.
494 uint16_t current = m_head;
495 while (current != 0xffff && current != m_tail)
496 {
498 PacketMetadata::ExtraItem tmpExtraItem;
499 ReadItems(current, &tmpItem, &tmpExtraItem);
500 uint16_t written = h.AddBig(0xffff, h.m_tail, &tmpItem, &tmpExtraItem);
501 h.UpdateTail(written);
502 current = tmpItem.next;
503 }
504 // append new tail.
505 uint16_t written = h.AddBig(0xffff, h.m_tail, item, extraItem);
506 h.UpdateTail(written);
507
508 *this = h;
509}
510
514 PacketMetadata::ExtraItem* extraItem) const
515{
516 NS_LOG_FUNCTION(this << current << item->chunkUid << item->prev << item->next << item->size
517 << item->typeUid << extraItem->fragmentEnd << extraItem->fragmentStart
518 << extraItem->packetUid);
519 NS_ASSERT(current <= m_data->m_size);
520 const uint8_t* buffer = &m_data->m_data[current];
521 item->next = buffer[0];
522 item->next |= (buffer[1]) << 8;
523 item->prev = buffer[2];
524 item->prev |= (buffer[3]) << 8;
525 buffer += 4;
526 item->typeUid = ReadUleb128(&buffer);
527 item->size = ReadUleb128(&buffer);
528 item->chunkUid = buffer[0];
529 item->chunkUid |= (buffer[1]) << 8;
530 buffer += 2;
531
532 bool isExtra = (item->typeUid & 0x1) == 0x1;
533 if (isExtra)
534 {
535 extraItem->fragmentStart = ReadUleb128(&buffer);
536 extraItem->fragmentEnd = ReadUleb128(&buffer);
537 extraItem->packetUid = buffer[0];
538 extraItem->packetUid |= buffer[1] << 8;
539 extraItem->packetUid |= buffer[2] << 16;
540 extraItem->packetUid |= buffer[3] << 24;
541 buffer += 4;
542 }
543 else
544 {
545 extraItem->fragmentStart = 0;
546 extraItem->fragmentEnd = item->size;
547 extraItem->packetUid = m_packetUid;
548 }
549 NS_ASSERT(buffer <= &m_data->m_data[m_data->m_size]);
550 return buffer - &m_data->m_data[current];
551}
552
555{
556 NS_LOG_FUNCTION(size);
557 NS_LOG_LOGIC("create size=" << size << ", max=" << m_maxSize);
558 if (size > m_maxSize)
559 {
560 m_maxSize = size;
561 }
562 while (!m_freeList.empty())
563 {
565 m_freeList.pop_back();
566 if (data->m_size >= size)
567 {
568 NS_LOG_LOGIC("create found size=" << data->m_size);
569 data->m_count = 1;
570 return data;
571 }
572 NS_LOG_LOGIC("create dealloc size=" << data->m_size);
574 }
575 NS_LOG_LOGIC("create alloc size=" << m_maxSize);
577}
578
579void
581{
583 if (!m_enable)
584 {
586 return;
587 }
588 NS_LOG_LOGIC("recycle size=" << data->m_size << ", list=" << m_freeList.size());
589 NS_ASSERT(data->m_count == 0);
590 if (m_freeList.size() > 1000 || data->m_size < m_maxSize)
591 {
593 }
594 else
595 {
596 m_freeList.push_back(data);
597 }
598}
599
602{
604 uint32_t size = sizeof(Data);
606 {
608 }
610 auto buf = new uint8_t[size];
611 auto data = (PacketMetadata::Data*)buf;
612 data->m_size = n;
613 data->m_count = 1;
614 data->m_dirtyEnd = 0;
615 return data;
616}
617
618void
620{
622 auto buf = (uint8_t*)data;
623 delete[] buf;
624}
625
628{
629 NS_LOG_FUNCTION(this << start << end);
630 PacketMetadata fragment = *this;
631 fragment.RemoveAtStart(start);
632 fragment.RemoveAtEnd(end);
633 return fragment;
634}
635
636void
638{
639 NS_LOG_FUNCTION(this << &header << size);
640 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
641 DoAddHeader(uid, size);
643}
644
645void
647{
648 NS_LOG_FUNCTION(this << uid << size);
649 if (!m_enable)
650 {
651 m_metadataSkipped = true;
652 return;
653 }
654
656 item.next = m_head;
657 item.prev = 0xffff;
658 item.typeUid = uid;
659 item.size = size;
660 item.chunkUid = m_chunkUid;
661 m_chunkUid++;
662 uint16_t written = AddSmall(&item);
663 UpdateHead(written);
664}
665
666void
668{
669 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
670 NS_LOG_FUNCTION(this << &header << size);
671 if (!m_enable)
672 {
673 m_metadataSkipped = true;
674 return;
675 }
678 uint32_t read = ReadItems(m_head, &item, &extraItem);
679 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
680 {
682 {
683 NS_FATAL_ERROR("Removing unexpected header.");
684 }
685 return;
686 }
687 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
688 {
690 {
691 NS_FATAL_ERROR("Removing incomplete header.");
692 }
693 return;
694 }
695 if (m_head + read == m_used)
696 {
697 m_used = m_head;
698 }
699 if (m_head == m_tail)
700 {
701 m_head = 0xffff;
702 m_tail = 0xffff;
703 }
704 else
705 {
706 m_head = item.next;
707 }
709}
710
711void
713{
714 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
715 NS_LOG_FUNCTION(this << &trailer << size);
716 if (!m_enable)
717 {
718 m_metadataSkipped = true;
719 return;
720 }
722 item.next = 0xffff;
723 item.prev = m_tail;
724 item.typeUid = uid;
725 item.size = size;
726 item.chunkUid = m_chunkUid;
727 m_chunkUid++;
728 uint16_t written = AddSmall(&item);
729 UpdateTail(written);
731}
732
733void
735{
736 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
737 NS_LOG_FUNCTION(this << &trailer << size);
738 if (!m_enable)
739 {
740 m_metadataSkipped = true;
741 return;
742 }
745 uint32_t read = ReadItems(m_tail, &item, &extraItem);
746 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
747 {
749 {
750 NS_FATAL_ERROR("Removing unexpected trailer.");
751 }
752 return;
753 }
754 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
755 {
757 {
758 NS_FATAL_ERROR("Removing incomplete trailer.");
759 }
760 return;
761 }
762 if (m_tail + read == m_used)
763 {
764 m_used = m_tail;
765 }
766 if (m_head == m_tail)
767 {
768 m_head = 0xffff;
769 m_tail = 0xffff;
770 }
771 else
772 {
773 m_tail = item.prev;
774 }
776}
777
778void
780{
781 NS_LOG_FUNCTION(this << &o);
782 if (!m_enable)
783 {
784 m_metadataSkipped = true;
785 return;
786 }
787 if (m_tail == 0xffff)
788 {
789 // We have no items so 'AddAtEnd' is
790 // equivalent to self-assignment.
791 *this = o;
793 return;
794 }
795 if (o.m_head == 0xffff)
796 {
797 NS_ASSERT(o.m_tail == 0xffff);
798 // we have nothing to append.
799 return;
800 }
801 NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
802
803 // We read the current tail because we are going to append
804 // after this item.
806 PacketMetadata::ExtraItem tailExtraItem;
807 uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
808
809 uint16_t current;
812 o.ReadItems(o.m_head, &item, &extraItem);
813 if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
814 item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
815 extraItem.fragmentStart == tailExtraItem.fragmentEnd)
816 {
817 /* If the previous tail came from the same header as
818 * the next item we want to append to our array, then,
819 * we merge them and attempt to reuse the previous tail's
820 * location.
821 */
822 tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
823 ReplaceTail(&tailItem, &tailExtraItem, tailSize);
824 if (o.m_head == o.m_tail)
825 {
826 // there is only one item to append to self from other.
827 return;
828 }
829 current = item.next;
830 }
831 else
832 {
833 current = o.m_head;
834 }
835
836 /* Now that we have merged our current tail with the head of the
837 * next packet, we just append all items from the next packet
838 * to the current packet.
839 */
840 while (current != 0xffff)
841 {
842 o.ReadItems(current, &item, &extraItem);
843 uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
844 UpdateTail(written);
845 if (current == o.m_tail)
846 {
847 break;
848 }
849 current = item.next;
850 }
852}
853
854void
856{
857 NS_LOG_FUNCTION(this << end);
858 if (!m_enable)
859 {
860 m_metadataSkipped = true;
861 return;
862 }
863}
864
865void
867{
868 NS_LOG_FUNCTION(this << start);
869 if (!m_enable)
870 {
871 m_metadataSkipped = true;
872 return;
873 }
874 NS_ASSERT(m_data != nullptr);
875 uint32_t leftToRemove = start;
876 uint16_t current = m_head;
877 while (current != 0xffff && leftToRemove > 0)
878 {
881 ReadItems(current, &item, &extraItem);
882 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
883 if (itemRealSize <= leftToRemove)
884 {
885 // remove from list.
886 if (m_head == m_tail)
887 {
888 m_head = 0xffff;
889 m_tail = 0xffff;
890 }
891 else
892 {
893 m_head = item.next;
894 }
895 leftToRemove -= itemRealSize;
896 }
897 else
898 {
899 // fragment the list item.
900 PacketMetadata fragment(m_packetUid, 0);
901 extraItem.fragmentStart += leftToRemove;
902 leftToRemove = 0;
903 uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
904 fragment.UpdateTail(written);
905 while (current != 0xffff && current != m_tail)
906 {
907 current = item.next;
908 ReadItems(current, &item, &extraItem);
909 written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
910 fragment.UpdateTail(written);
911 }
912 *this = fragment;
913 }
914 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
915 extraItem.fragmentStart <= extraItem.fragmentEnd);
916 if (current == m_tail)
917 {
918 break;
919 }
920 current = item.next;
921 }
922 NS_ASSERT(leftToRemove == 0);
924}
925
926void
928{
929 NS_LOG_FUNCTION(this << end);
930 if (!m_enable)
931 {
932 m_metadataSkipped = true;
933 return;
934 }
935 NS_ASSERT(m_data != nullptr);
936
937 uint32_t leftToRemove = end;
938 uint16_t current = m_tail;
939 while (current != 0xffff && leftToRemove > 0)
940 {
943 ReadItems(current, &item, &extraItem);
944 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
945 if (itemRealSize <= leftToRemove)
946 {
947 // remove from list.
948 if (m_head == m_tail)
949 {
950 m_head = 0xffff;
951 m_tail = 0xffff;
952 }
953 else
954 {
955 m_tail = item.prev;
956 }
957 leftToRemove -= itemRealSize;
958 }
959 else
960 {
961 // fragment the list item.
962 PacketMetadata fragment(m_packetUid, 0);
963 NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
964 extraItem.fragmentEnd -= leftToRemove;
965 leftToRemove = 0;
966 uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
967 fragment.UpdateHead(written);
968 while (current != 0xffff && current != m_head)
969 {
970 current = item.prev;
971 ReadItems(current, &item, &extraItem);
972 written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
973 fragment.UpdateHead(written);
974 }
975 *this = fragment;
976 }
977 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
978 extraItem.fragmentStart <= extraItem.fragmentEnd);
979 if (current == m_head)
980 {
981 break;
982 }
983 current = item.prev;
984 }
985 NS_ASSERT(leftToRemove == 0);
987}
988
991{
992 NS_LOG_FUNCTION(this);
993 uint32_t totalSize = 0;
994 uint16_t current = m_head;
995 uint16_t tail = m_tail;
996 while (current != 0xffff)
997 {
1000 ReadItems(current, &item, &extraItem);
1001 totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1002 if (current == tail)
1003 {
1004 break;
1005 }
1006 NS_ASSERT(current != item.next);
1007 current = item.next;
1008 }
1009 return totalSize;
1010}
1011
1012uint64_t
1014{
1015 NS_LOG_FUNCTION(this);
1016 return m_packetUid;
1017}
1018
1021{
1022 NS_LOG_FUNCTION(this << &buffer);
1023 return ItemIterator(this, buffer);
1024}
1025
1027 : m_metadata(metadata),
1028 m_buffer(buffer),
1029 m_current(metadata->m_head),
1030 m_offset(0),
1031 m_hasReadTail(false)
1032{
1033 NS_LOG_FUNCTION(this << metadata << &buffer);
1034}
1035
1036bool
1038{
1039 NS_LOG_FUNCTION(this);
1040 if (m_current == 0xffff)
1041 {
1042 return false;
1043 }
1044 if (m_hasReadTail)
1045 {
1046 return false;
1047 }
1048 return true;
1049}
1050
1053{
1054 NS_LOG_FUNCTION(this);
1056 PacketMetadata::SmallItem smallItem;
1057 PacketMetadata::ExtraItem extraItem;
1058 m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1059 if (m_current == m_metadata->m_tail)
1060 {
1061 m_hasReadTail = true;
1062 }
1063 m_current = smallItem.next;
1064 uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1065 item.tid.SetUid(uid);
1066 item.currentTrimmedFromStart = extraItem.fragmentStart;
1067 item.currentTrimmedFromEnd = extraItem.fragmentEnd - smallItem.size;
1068 item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1069 item.isFragment = (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size);
1070 TypeId tid;
1071 tid.SetUid(uid);
1072 if (uid == 0)
1073 {
1075 }
1076 else if (tid.IsChildOf(Header::GetTypeId()))
1077 {
1079 if (!item.isFragment)
1080 {
1081 item.current = m_buffer.Begin();
1082 item.current.Next(m_offset);
1083 }
1084 }
1085 else if (tid.IsChildOf(Trailer::GetTypeId()))
1086 {
1088 if (!item.isFragment)
1089 {
1090 item.current = m_buffer.End();
1091 item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1092 }
1093 }
1094 else
1095 {
1096 NS_ASSERT(false);
1097 }
1098 m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1099 return item;
1100}
1101
1104{
1105 NS_LOG_FUNCTION(this);
1106 uint32_t totalSize = 0;
1107
1108 // add 8 bytes for the packet uid
1109 totalSize += 8;
1110
1111 // if packet-metadata not enabled, total size
1112 // is simply 4-bytes for itself plus 8-bytes
1113 // for packet uid
1114 if (!m_enable)
1115 {
1116 return totalSize;
1117 }
1118
1120 PacketMetadata::ExtraItem extraItem;
1121 uint32_t current = m_head;
1122 while (current != 0xffff)
1123 {
1124 ReadItems(current, &item, &extraItem);
1125 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1126 if (uid == 0)
1127 {
1128 totalSize += 4;
1129 }
1130 else
1131 {
1132 TypeId tid;
1133 tid.SetUid(uid);
1134 totalSize += 4 + tid.GetName().size();
1135 }
1136 totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1137 if (current == m_tail)
1138 {
1139 break;
1140 }
1141 NS_ASSERT(current != item.next);
1142 current = item.next;
1143 }
1144 return totalSize;
1145}
1146
1148PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1149{
1150 NS_LOG_FUNCTION(this << &buffer << maxSize);
1151 uint8_t* start = buffer;
1152
1153 buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1154 if (buffer == nullptr)
1155 {
1156 return 0;
1157 }
1158
1160 PacketMetadata::ExtraItem extraItem;
1161 uint32_t current = m_head;
1162 while (current != 0xffff)
1163 {
1164 ReadItems(current, &item, &extraItem);
1165 NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1166 << ", typeUid=" << item.typeUid << ", size=" << item.size
1167 << ", chunkUid=" << item.chunkUid
1168 << ", fragmentStart=" << extraItem.fragmentStart
1169 << ", fragmentEnd=" << extraItem.fragmentEnd
1170 << ", packetUid=" << extraItem.packetUid);
1171
1172 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1173 if (uid != 0)
1174 {
1175 TypeId tid;
1176 tid.SetUid(uid);
1177 std::string uidString = tid.GetName();
1178 uint32_t uidStringSize = uidString.size();
1179 buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1180 if (buffer == nullptr)
1181 {
1182 return 0;
1183 }
1184 buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1185 uidStringSize,
1186 start,
1187 buffer,
1188 maxSize);
1189 if (buffer == nullptr)
1190 {
1191 return 0;
1192 }
1193 }
1194 else
1195 {
1196 buffer = AddToRawU32(0, start, buffer, maxSize);
1197 if (buffer == nullptr)
1198 {
1199 return 0;
1200 }
1201 }
1202
1203 uint8_t isBig = item.typeUid & 0x1;
1204 buffer = AddToRawU8(isBig, start, buffer, maxSize);
1205 if (buffer == nullptr)
1206 {
1207 return 0;
1208 }
1209
1210 buffer = AddToRawU32(item.size, start, buffer, maxSize);
1211 if (buffer == nullptr)
1212 {
1213 return 0;
1214 }
1215
1216 buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1217 if (buffer == nullptr)
1218 {
1219 return 0;
1220 }
1221
1222 buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1223 if (buffer == nullptr)
1224 {
1225 return 0;
1226 }
1227
1228 buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1229 if (buffer == nullptr)
1230 {
1231 return 0;
1232 }
1233
1234 buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1235 if (buffer == nullptr)
1236 {
1237 return 0;
1238 }
1239
1240 if (current == m_tail)
1241 {
1242 break;
1243 }
1244
1245 NS_ASSERT(current != item.next);
1246 current = item.next;
1247 }
1248
1249 NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1250 return 1;
1251}
1252
1254PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1255{
1256 NS_LOG_FUNCTION(this << &buffer << size);
1257 const uint8_t* start = buffer;
1258 uint32_t desSize = size - 4;
1259
1260 buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1261 desSize -= 8;
1262
1263 PacketMetadata::SmallItem item = {0};
1264 PacketMetadata::ExtraItem extraItem = {0};
1265 while (desSize > 0)
1266 {
1267 uint32_t uidStringSize = 0;
1268 buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1269 desSize -= 4;
1270 uint32_t uid;
1271 if (uidStringSize == 0)
1272 {
1273 // uid zero for payload.
1274 uid = 0;
1275 }
1276 else
1277 {
1278 std::string uidString;
1279 for (uint32_t j = 0; j < uidStringSize; j++)
1280 {
1281 uint8_t ch = 0;
1282 buffer = ReadFromRawU8(ch, start, buffer, size);
1283 uidString.push_back(ch);
1284 desSize--;
1285 }
1286 TypeId tid = TypeId::LookupByName(uidString);
1287 uid = tid.GetUid();
1288 }
1289 uint8_t isBig = 0;
1290 buffer = ReadFromRawU8(isBig, start, buffer, size);
1291 desSize--;
1292 item.typeUid = (uid << 1) | isBig;
1293 buffer = ReadFromRawU32(item.size, start, buffer, size);
1294 desSize -= 4;
1295 buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1296 desSize -= 2;
1297 buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1298 desSize -= 4;
1299 buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1300 desSize -= 4;
1301 buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1302 desSize -= 8;
1303 NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1304 << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1305 << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1306 << ", packetUid=" << extraItem.packetUid);
1307 uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1308 UpdateTail(tmp);
1309 }
1310 NS_ASSERT(desSize == 0);
1311 return (desSize != 0) ? 0 : 1;
1312}
1313
1314uint8_t*
1315PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1316{
1317 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1318 // First check buffer overflow
1319 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1320 {
1321 return nullptr;
1322 }
1323 memcpy(current, &data, sizeof(uint8_t));
1324 return current + sizeof(uint8_t);
1325}
1326
1327uint8_t*
1329 uint8_t* start,
1330 uint8_t* current,
1331 uint32_t maxSize)
1332{
1333 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1334 // First check buffer overflow
1335 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1336 {
1337 return nullptr;
1338 }
1339 memcpy(current, &data, sizeof(uint16_t));
1340 return current + sizeof(uint16_t);
1341}
1342
1343uint8_t*
1345 uint8_t* start,
1346 uint8_t* current,
1347 uint32_t maxSize)
1348{
1349 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1350 // First check buffer overflow
1351 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1352 {
1353 return nullptr;
1354 }
1355 memcpy(current, &data, sizeof(uint32_t));
1356 return current + sizeof(uint32_t);
1357}
1358
1359uint8_t*
1361 uint8_t* start,
1362 uint8_t* current,
1363 uint32_t maxSize)
1364{
1365 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1366 // First check buffer overflow
1367 if (static_cast<uint32_t>(current + sizeof(uint64_t) - start) > maxSize)
1368 {
1369 return nullptr;
1370 }
1371 memcpy(current, &data, sizeof(uint64_t));
1372 return current + sizeof(uint64_t);
1373}
1374
1375uint8_t*
1377 uint32_t dataSize,
1378 uint8_t* start,
1379 uint8_t* current,
1380 uint32_t maxSize)
1381{
1382 NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1383 // First check buffer overflow
1384 if (static_cast<uint32_t>(current + dataSize - start) > maxSize)
1385 {
1386 return nullptr;
1387 }
1388 memcpy(current, data, dataSize);
1389 return current + dataSize;
1390}
1391
1392uint8_t*
1394 const uint8_t* start,
1395 const uint8_t* current,
1396 uint32_t maxSize)
1397{
1398 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1399 // First check buffer underflow
1400 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1401 {
1402 return nullptr;
1403 }
1404 memcpy(&data, current, sizeof(uint8_t));
1405 return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1406}
1407
1408uint8_t*
1410 const uint8_t* start,
1411 const uint8_t* current,
1412 uint32_t maxSize)
1413{
1414 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1415 // First check buffer underflow
1416 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1417 {
1418 return nullptr;
1419 }
1420 memcpy(&data, current, sizeof(uint16_t));
1421 return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1422}
1423
1424uint8_t*
1426 const uint8_t* start,
1427 const uint8_t* current,
1428 uint32_t maxSize)
1429{
1430 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1431 // First check buffer underflow
1432 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1433 {
1434 return nullptr;
1435 }
1436 memcpy(&data, current, sizeof(uint32_t));
1437 return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1438}
1439
1440uint8_t*
1442 const uint8_t* start,
1443 const uint8_t* current,
1444 uint32_t maxSize)
1445{
1446 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1447 // First check buffer underflow
1448 if ((uint32_t)(current + sizeof(uint64_t) - start) > maxSize)
1449 {
1450 return nullptr;
1451 }
1452 memcpy(&data, current, sizeof(uint64_t));
1453 return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1454}
1455
1456} // namespace ns3
void Prev()
go backward by one byte
Definition buffer.h:849
void Next()
go forward by one byte
Definition buffer.h:842
automatically resized byte buffer
Definition buffer.h:83
Protocol header serialization and deserialization.
Definition header.h:33
static TypeId GetTypeId()
Get the type ID.
Definition header.cc:26
virtual TypeId GetInstanceTypeId() const =0
Get the most derived TypeId for this Object.
Class to hold all the metadata.
Iterator class for metadata items.
uint16_t m_current
current position
Buffer m_buffer
buffer the metadata refers to
const PacketMetadata * m_metadata
pointer to the metadata
bool m_hasReadTail
true if the metadata tail has been read
bool HasNext() const
Checks if there is another metadata item.
Item Next()
Retrieve the next metadata item.
ItemIterator(const PacketMetadata *metadata, Buffer buffer)
Constructor.
Handle packet metadata about packet headers and trailers.
uint32_t m_used
used portion
static uint8_t * ReadFromRawU64(uint64_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
uint32_t GetSerializedSize() const
Get the metadata serialized size.
void ReplaceTail(PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem, uint32_t available)
Replace the tail.
PacketMetadata CreateFragment(uint32_t start, uint32_t end) const
Creates a fragment.
Data * m_data
Metadata storage.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
void AddHeader(const Header &header, uint32_t size)
Add an header.
uint32_t ReadItems(uint16_t current, PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem) const
Read items.
static void Deallocate(PacketMetadata::Data *data)
Deallocate the buffer memory.
void AppendValueExtra(uint32_t value, uint8_t *buffer)
Append a value to the buffer - extra.
static PacketMetadata::Data * Create(uint32_t size)
Create a buffer data storage.
void Append32(uint32_t value, uint8_t *buffer)
Append a 32-bit value to the buffer.
friend class ItemIterator
Friend class.
static uint32_t m_maxSize
maximum metadata size
static bool m_enableChecking
Enable the packet metadata checking.
void UpdateHead(uint16_t written)
Update the head.
PacketMetadata(uint64_t uid, uint32_t size)
Constructor.
uint64_t GetUid() const
Get the packet Uid.
uint16_t m_head
list head
void AppendValue(uint32_t value, uint8_t *buffer)
Append a value to the buffer.
static void Recycle(PacketMetadata::Data *data)
Recycle the buffer memory.
static uint8_t * ReadFromRawU32(uint32_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static uint8_t * AddToRawU32(const uint32_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static bool m_enable
Enable the packet metadata.
void AddAtEnd(const PacketMetadata &o)
Add a metadata at the metadata start.
void Reserve(uint32_t n)
Reserve space.
uint32_t ReadUleb128(const uint8_t **pBuffer) const
Read a ULEB128 (Unsigned Little Endian Base 128) coded number.
ItemIterator BeginItem(Buffer buffer) const
Initialize the item iterator to the buffer begin.
static void EnableChecking()
Enable the packet metadata checking.
void RemoveAtEnd(uint32_t end)
Remove a chunk of metadata at the metadata end.
void RemoveHeader(const Header &header, uint32_t size)
Remove an header.
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Deserialization from raw uint8_t*.
void AddPaddingAtEnd(uint32_t end)
Add some padding at the end.
static uint8_t * ReadFromRawU16(uint16_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static uint16_t m_chunkUid
Chunk Uid.
static PacketMetadata::Data * Allocate(uint32_t n)
Allocate a buffer data storage.
void RemoveAtStart(uint32_t start)
Remove a chunk of metadata at the metadata start.
uint16_t AddSmall(const PacketMetadata::SmallItem *item)
Add a SmallItem.
static DataFreeList m_freeList
the metadata data storage
uint32_t GetUleb128Size(uint32_t value) const
Get the ULEB128 (Unsigned Little Endian Base 128) size.
uint32_t GetTotalSize() const
Get the total size used by the metadata.
void Append16(uint16_t value, uint8_t *buffer)
Append a 16-bit value to the buffer.
void RemoveTrailer(const Trailer &trailer, uint32_t size)
Remove a trailer.
static bool m_metadataSkipped
Set to true when adding metadata to a packet is skipped because m_enable is false; used to detect ena...
bool IsPointerOk(uint16_t pointer) const
Check if the position is valid.
bool IsStateOk() const
Check if the metadata state is ok.
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialization to raw uint8_t*.
bool IsSharedPointerOk(uint16_t pointer) const
Check if the position is valid.
static uint8_t * AddToRawU8(const uint8_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
uint16_t m_tail
list tail
void UpdateTail(uint16_t written)
Update the tail.
uint64_t m_packetUid
packet Uid
static uint8_t * AddToRaw(const uint8_t *data, uint32_t dataSize, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
void DoAddHeader(uint32_t uid, uint32_t size)
Add an header.
uint16_t AddBig(uint32_t head, uint32_t tail, const PacketMetadata::SmallItem *item, const PacketMetadata::ExtraItem *extraItem)
Add a "Big" Item (a SmallItem plus an ExtraItem)
static uint8_t * ReadFromRawU8(uint8_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
void AddTrailer(const Trailer &trailer, uint32_t size)
Add a trailer.
static uint8_t * AddToRawU16(const uint16_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static uint8_t * AddToRawU64(const uint64_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static void Enable()
Enable the packet metadata.
Protocol trailer serialization and deserialization.
Definition trailer.h:30
static TypeId GetTypeId()
Get the type ID.
Definition trailer.cc:26
a unique identifier for an interface.
Definition type-id.h:49
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition type-id.cc:1041
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition type-id.cc:1282
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition type-id.cc:1275
std::string GetName() const
Get the name.
Definition type-id.cc:1061
#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_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#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 ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
#define PACKET_METADATA_DATA_M_DATA_SIZE
the size of PacketMetadata::Data::m_data such that the total size of PacketMetadata::Data is 16 bytes
uint8_t data[writeSize]
uint8_t m_data[PACKET_METADATA_DATA_M_DATA_SIZE]
variable-sized buffer of bytes
uint16_t m_dirtyEnd
max of the m_used field over all objects which reference this struct Data instance
uint32_t fragmentEnd
offset (in bytes) from start of original header to the end of the fragment still present.
uint64_t packetUid
the packetUid of the packet in which this header or trailer was first added.
uint32_t fragmentStart
offset (in bytes) from start of original header to the start of the fragment still present.
structure describing a packet metadata item
ItemType type
metadata type
TypeId tid
TypeId of Header or Trailer.
bool isFragment
true: this is a fragmented header, trailer, or, payload.
uint32_t currentTrimmedFromEnd
how many bytes were trimmed from the end of a fragment.
Buffer::Iterator current
an iterator which can be fed to Deserialize.
uint32_t currentTrimmedFromStart
how many bytes were trimmed from the start of a fragment.
uint32_t currentSize
size of item.
uint16_t next
offset (in bytes) from start of m_data buffer to next element in linked list.
uint16_t chunkUid
this field tries to uniquely identify each header or trailer instance while the typeUid field uniquel...
uint32_t typeUid
the high 31 bits of this field identify the type of the header or trailer represented by this item: t...
uint32_t size
the size (in bytes) of the header or trailer represented by this element.
uint16_t prev
offset (in bytes) from start of m_data buffer to previous element in linked list.
uint32_t prev