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 NS_LOG_FUNCTION(this << pointer);
112 bool ok = pointer == 0xffff || pointer <= m_data->m_size;
113 return ok;
114}
115
116bool
117PacketMetadata::IsPointerOk(uint16_t pointer) const
118{
119 NS_LOG_FUNCTION(this << pointer);
120 bool ok = pointer == 0xffff || pointer <= m_used;
121 return ok;
122}
123
124bool
126{
127 NS_LOG_FUNCTION(this);
128 bool ok = m_used <= m_data->m_size;
129 ok &= IsPointerOk(m_head);
130 ok &= IsPointerOk(m_tail);
131 uint16_t current = m_head;
132 while (ok && current != 0xffff)
133 {
136 ReadItems(current, &item, &extraItem);
137 ok &= IsSharedPointerOk(item.next);
138 ok &= IsSharedPointerOk(item.prev);
139 if (current != m_head)
140 {
141 ok &= IsPointerOk(item.prev);
142 }
143 if (current != m_tail)
144 {
145 ok &= IsPointerOk(item.next);
146 }
147 if (current == m_tail)
148 {
149 break;
150 }
151 current = item.next;
152 }
153 return ok;
154}
155
158{
159 NS_LOG_FUNCTION(this << value);
160 if (value < 0x80)
161 {
162 return 1;
163 }
164 if (value < 0x4000)
165 {
166 return 2;
167 }
168 if (value < 0x200000)
169 {
170 return 3;
171 }
172 if (value < 0x10000000)
173 {
174 return 4;
175 }
176 return 5;
177}
178
180PacketMetadata::ReadUleb128(const uint8_t** pBuffer) const
181{
182 NS_LOG_FUNCTION(this << &pBuffer);
183 const uint8_t* buffer = *pBuffer;
184 uint32_t result;
185 uint8_t byte;
186
187 byte = buffer[0];
188 result = (byte & (~0x80));
189 if (!(byte & 0x80))
190 {
191 *pBuffer = buffer + 1;
192 return result;
193 }
194 byte = buffer[1];
195 result |= (byte & (~0x80)) << 7;
196 if (!(byte & 0x80))
197 {
198 *pBuffer = buffer + 2;
199 return result;
200 }
201 byte = buffer[2];
202 result |= (byte & (~0x80)) << 14;
203 if (!(byte & 0x80))
204 {
205 *pBuffer = buffer + 3;
206 return result;
207 }
208 byte = buffer[3];
209 result |= (byte & (~0x80)) << 21;
210 if (!(byte & 0x80))
211 {
212 *pBuffer = buffer + 4;
213 return result;
214 }
215 byte = buffer[4];
216 result |= (byte & (~0x80)) << 28;
217 if (!(byte & 0x80))
218 {
219 *pBuffer = buffer + 5;
220 return result;
221 }
222 /* This means that the LEB128 number was not valid.
223 * ie: the last (5th) byte did not have the high-order bit zeroed.
224 */
225 NS_ASSERT(false);
226 return 0;
227}
228
229void
230PacketMetadata::Append16(uint16_t value, uint8_t* buffer)
231{
232 NS_LOG_FUNCTION(this << value << &buffer);
233 buffer[0] = value & 0xff;
234 value >>= 8;
235 buffer[1] = value;
236}
237
238void
239PacketMetadata::Append32(uint32_t value, uint8_t* buffer)
240{
241 NS_LOG_FUNCTION(this << value << &buffer);
242 buffer[0] = value & 0xff;
243 buffer[1] = (value >> 8) & 0xff;
244 buffer[2] = (value >> 16) & 0xff;
245 buffer[3] = (value >> 24) & 0xff;
246}
247
248void
250{
251 NS_LOG_FUNCTION(this << value << &buffer);
252 if (value < 0x200000)
253 {
254 uint8_t byte = value & (~0x80);
255 buffer[0] = 0x80 | byte;
256 value >>= 7;
257 byte = value & (~0x80);
258 buffer[1] = 0x80 | byte;
259 value >>= 7;
260 buffer[2] = value;
261 return;
262 }
263 if (value < 0x10000000)
264 {
265 uint8_t byte = value & (~0x80);
266 buffer[0] = 0x80 | byte;
267 value >>= 7;
268 byte = value & (~0x80);
269 buffer[1] = 0x80 | byte;
270 value >>= 7;
271 byte = value & (~0x80);
272 buffer[2] = 0x80 | byte;
273 value >>= 7;
274 buffer[3] = value;
275 return;
276 }
277 {
278 uint8_t byte = value & (~0x80);
279 buffer[0] = 0x80 | byte;
280 value >>= 7;
281 byte = value & (~0x80);
282 buffer[1] = 0x80 | byte;
283 value >>= 7;
284 byte = value & (~0x80);
285 buffer[2] = 0x80 | byte;
286 value >>= 7;
287 byte = value & (~0x80);
288 buffer[3] = 0x80 | byte;
289 value >>= 7;
290 buffer[4] = value;
291 }
292}
293
294void
296{
297 NS_LOG_FUNCTION(this << value << &buffer);
298 if (value < 0x80)
299 {
300 buffer[0] = value;
301 return;
302 }
303 if (value < 0x4000)
304 {
305 uint8_t byte = value & (~0x80);
306 buffer[0] = 0x80 | byte;
307 value >>= 7;
308 buffer[1] = value;
309 return;
310 }
311 AppendValueExtra(value, buffer);
312}
313
314void
316{
317 NS_LOG_FUNCTION(this << written);
318 if (m_head == 0xffff)
319 {
320 NS_ASSERT(m_tail == 0xffff);
321 m_head = m_used;
322 m_tail = m_used;
323 }
324 else
325 {
326 NS_ASSERT(m_tail != 0xffff);
327 // overwrite the next field of the previous tail of the list.
328 uint8_t* previousTail = &m_data->m_data[m_tail];
329 Append16(m_used, previousTail);
330 // update the tail of the list to the new node.
331 m_tail = m_used;
332 }
333 NS_ASSERT(m_tail != 0xffff);
334 NS_ASSERT(m_head != 0xffff);
335 NS_ASSERT(written >= 8);
336 m_used += written;
337 m_data->m_dirtyEnd = m_used;
338}
339
340void
342{
343 NS_LOG_FUNCTION(this << written);
344 if (m_head == 0xffff)
345 {
346 NS_ASSERT(m_tail == 0xffff);
347 m_head = m_used;
348 m_tail = m_used;
349 }
350 else
351 {
352 NS_ASSERT(m_head != 0xffff);
353 // overwrite the prev field of the previous head of the list.
354 uint8_t* previousHead = &m_data->m_data[m_head + 2];
355 Append16(m_used, previousHead);
356 // update the head of list to the new node.
357 m_head = m_used;
358 }
359 NS_ASSERT(m_tail != 0xffff);
360 NS_ASSERT(m_head != 0xffff);
361 NS_ASSERT(written >= 8);
362 m_used += written;
363 m_data->m_dirtyEnd = m_used;
364}
365
366uint16_t
368{
369 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
370 << item->chunkUid);
371 NS_ASSERT(m_data != nullptr);
372 NS_ASSERT(m_used != item->prev && m_used != item->next);
373 uint32_t typeUidSize = GetUleb128Size(item->typeUid);
374 uint32_t sizeSize = GetUleb128Size(item->size);
375 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
376 if (m_used + n > m_data->m_size ||
377 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
378 {
379 ReserveCopy(n);
380 }
381 uint8_t* buffer = &m_data->m_data[m_used];
382 Append16(item->next, buffer);
383 buffer += 2;
384 Append16(item->prev, buffer);
385 buffer += 2;
386 AppendValue(item->typeUid, buffer);
387 buffer += typeUidSize;
388 AppendValue(item->size, buffer);
389 buffer += sizeSize;
390 Append16(item->chunkUid, buffer);
391 return n;
392}
393
394uint16_t
397 const PacketMetadata::SmallItem* item,
398 const PacketMetadata::ExtraItem* extraItem)
399{
400 NS_LOG_FUNCTION(this << next << prev << item->next << item->prev << item->typeUid << item->size
401 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
402 << extraItem->packetUid);
403 NS_ASSERT(m_data != nullptr);
404 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
405 NS_ASSERT(m_used != prev && m_used != next);
406
407 uint32_t typeUidSize = GetUleb128Size(typeUid);
408 uint32_t sizeSize = GetUleb128Size(item->size);
409 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
410 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
411 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
412
413 if (m_used + n > m_data->m_size ||
414 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
415 {
416 ReserveCopy(n);
417 }
418
419 uint8_t* buffer = &m_data->m_data[m_used];
420
421 Append16(next, buffer);
422 buffer += 2;
423 Append16(prev, buffer);
424 buffer += 2;
425 AppendValue(typeUid, buffer);
426 buffer += typeUidSize;
427 AppendValue(item->size, buffer);
428 buffer += sizeSize;
429 Append16(item->chunkUid, buffer);
430 buffer += 2;
431 AppendValue(extraItem->fragmentStart, buffer);
432 buffer += fragStartSize;
433 AppendValue(extraItem->fragmentEnd, buffer);
434 buffer += fragEndSize;
435 Append32(extraItem->packetUid, buffer);
436
437 return n;
438}
439
440void
442 PacketMetadata::ExtraItem* extraItem,
443 uint32_t available)
444{
445 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
446 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
447 << extraItem->packetUid << available);
448
449 NS_ASSERT(m_data != nullptr);
450 /* If the tail we want to replace is located at the end of the data array,
451 * and if there is extra room at the end of this array, then,
452 * we can try to use that extra space to avoid falling in the slow
453 * path below.
454 */
455 if (m_tail + available == m_used && m_used == m_data->m_dirtyEnd)
456 {
457 available = m_data->m_size - m_tail;
458 }
459
460 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
461 uint32_t typeUidSize = GetUleb128Size(typeUid);
462 uint32_t sizeSize = GetUleb128Size(item->size);
463 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
464 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
465 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
466
467 if (available >= n && m_data->m_count == 1)
468 {
469 uint8_t* buffer = &m_data->m_data[m_tail];
470 Append16(item->next, buffer);
471 buffer += 2;
472 Append16(item->prev, buffer);
473 buffer += 2;
474 AppendValue(typeUid, buffer);
475 buffer += typeUidSize;
476 AppendValue(item->size, buffer);
477 buffer += sizeSize;
478 Append16(item->chunkUid, buffer);
479 buffer += 2;
480 AppendValue(extraItem->fragmentStart, buffer);
481 buffer += fragStartSize;
482 AppendValue(extraItem->fragmentEnd, buffer);
483 buffer += fragEndSize;
484 Append32(extraItem->packetUid, buffer);
485 m_used = std::max(m_used, static_cast<uint32_t>(buffer - &m_data->m_data[0]));
486 m_data->m_dirtyEnd = m_used;
487 return;
488 }
489
490 /* Below is the slow path which is hit if the new tail we want
491 * to append is bigger than the previous tail.
492 */
493
494 // create a copy of the packet without its tail.
496 uint16_t current = m_head;
497 while (current != 0xffff && current != m_tail)
498 {
500 PacketMetadata::ExtraItem tmpExtraItem;
501 ReadItems(current, &tmpItem, &tmpExtraItem);
502 uint16_t written = h.AddBig(0xffff, h.m_tail, &tmpItem, &tmpExtraItem);
503 h.UpdateTail(written);
504 current = tmpItem.next;
505 }
506 // append new tail.
507 uint16_t written = h.AddBig(0xffff, h.m_tail, item, extraItem);
508 h.UpdateTail(written);
509
510 *this = h;
511}
512
516 PacketMetadata::ExtraItem* extraItem) const
517{
518 NS_LOG_FUNCTION(this << current << item->chunkUid << item->prev << item->next << item->size
519 << item->typeUid << extraItem->fragmentEnd << extraItem->fragmentStart
520 << extraItem->packetUid);
521 NS_ASSERT(current <= m_data->m_size);
522 const uint8_t* buffer = &m_data->m_data[current];
523 item->next = buffer[0];
524 item->next |= (buffer[1]) << 8;
525 item->prev = buffer[2];
526 item->prev |= (buffer[3]) << 8;
527 buffer += 4;
528 item->typeUid = ReadUleb128(&buffer);
529 item->size = ReadUleb128(&buffer);
530 item->chunkUid = buffer[0];
531 item->chunkUid |= (buffer[1]) << 8;
532 buffer += 2;
533
534 bool isExtra = (item->typeUid & 0x1) == 0x1;
535 if (isExtra)
536 {
537 extraItem->fragmentStart = ReadUleb128(&buffer);
538 extraItem->fragmentEnd = ReadUleb128(&buffer);
539 extraItem->packetUid = buffer[0];
540 extraItem->packetUid |= buffer[1] << 8;
541 extraItem->packetUid |= buffer[2] << 16;
542 extraItem->packetUid |= buffer[3] << 24;
543 buffer += 4;
544 }
545 else
546 {
547 extraItem->fragmentStart = 0;
548 extraItem->fragmentEnd = item->size;
549 extraItem->packetUid = m_packetUid;
550 }
551 NS_ASSERT(buffer <= &m_data->m_data[m_data->m_size]);
552 return buffer - &m_data->m_data[current];
553}
554
557{
558 NS_LOG_FUNCTION(size);
559 NS_LOG_LOGIC("create size=" << size << ", max=" << m_maxSize);
560 if (size > m_maxSize)
561 {
562 m_maxSize = size;
563 }
564 while (!m_freeList.empty())
565 {
567 m_freeList.pop_back();
568 if (data->m_size >= size)
569 {
570 NS_LOG_LOGIC("create found size=" << data->m_size);
571 data->m_count = 1;
572 return data;
573 }
574 NS_LOG_LOGIC("create dealloc size=" << data->m_size);
576 }
577 NS_LOG_LOGIC("create alloc size=" << m_maxSize);
579}
580
581void
583{
585 if (!m_enable)
586 {
588 return;
589 }
590 NS_LOG_LOGIC("recycle size=" << data->m_size << ", list=" << m_freeList.size());
591 NS_ASSERT(data->m_count == 0);
592 if (m_freeList.size() > 1000 || data->m_size < m_maxSize)
593 {
595 }
596 else
597 {
598 m_freeList.push_back(data);
599 }
600}
601
604{
606 uint32_t size = sizeof(Data);
608 {
610 }
612 auto buf = new uint8_t[size];
613 auto data = (PacketMetadata::Data*)buf;
614 data->m_size = n;
615 data->m_count = 1;
616 data->m_dirtyEnd = 0;
617 return data;
618}
619
620void
622{
624 auto buf = (uint8_t*)data;
625 delete[] buf;
626}
627
630{
631 NS_LOG_FUNCTION(this << start << end);
632 PacketMetadata fragment = *this;
633 fragment.RemoveAtStart(start);
634 fragment.RemoveAtEnd(end);
635 return fragment;
636}
637
638void
640{
641 NS_LOG_FUNCTION(this << &header << size);
642 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
643 DoAddHeader(uid, size);
645}
646
647void
649{
650 NS_LOG_FUNCTION(this << uid << size);
651 if (!m_enable)
652 {
653 m_metadataSkipped = true;
654 return;
655 }
656
658 item.next = m_head;
659 item.prev = 0xffff;
660 item.typeUid = uid;
661 item.size = size;
662 item.chunkUid = m_chunkUid;
663 m_chunkUid++;
664 uint16_t written = AddSmall(&item);
665 UpdateHead(written);
666}
667
668void
670{
671 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
672 NS_LOG_FUNCTION(this << &header << size);
673 if (!m_enable)
674 {
675 m_metadataSkipped = true;
676 return;
677 }
680 uint32_t read = ReadItems(m_head, &item, &extraItem);
681 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
682 {
684 {
685 NS_FATAL_ERROR("Removing unexpected header.");
686 }
687 return;
688 }
689 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
690 {
692 {
693 NS_FATAL_ERROR("Removing incomplete header.");
694 }
695 return;
696 }
697 if (m_head + read == m_used)
698 {
699 m_used = m_head;
700 }
701 if (m_head == m_tail)
702 {
703 m_head = 0xffff;
704 m_tail = 0xffff;
705 }
706 else
707 {
708 m_head = item.next;
709 }
711}
712
713void
715{
716 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
717 NS_LOG_FUNCTION(this << &trailer << size);
718 if (!m_enable)
719 {
720 m_metadataSkipped = true;
721 return;
722 }
724 item.next = 0xffff;
725 item.prev = m_tail;
726 item.typeUid = uid;
727 item.size = size;
728 item.chunkUid = m_chunkUid;
729 m_chunkUid++;
730 uint16_t written = AddSmall(&item);
731 UpdateTail(written);
733}
734
735void
737{
738 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
739 NS_LOG_FUNCTION(this << &trailer << size);
740 if (!m_enable)
741 {
742 m_metadataSkipped = true;
743 return;
744 }
747 uint32_t read = ReadItems(m_tail, &item, &extraItem);
748 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
749 {
751 {
752 NS_FATAL_ERROR("Removing unexpected trailer.");
753 }
754 return;
755 }
756 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
757 {
759 {
760 NS_FATAL_ERROR("Removing incomplete trailer.");
761 }
762 return;
763 }
764 if (m_tail + read == m_used)
765 {
766 m_used = m_tail;
767 }
768 if (m_head == m_tail)
769 {
770 m_head = 0xffff;
771 m_tail = 0xffff;
772 }
773 else
774 {
775 m_tail = item.prev;
776 }
778}
779
780void
782{
783 NS_LOG_FUNCTION(this << &o);
784 if (!m_enable)
785 {
786 m_metadataSkipped = true;
787 return;
788 }
789 if (m_tail == 0xffff)
790 {
791 // We have no items so 'AddAtEnd' is
792 // equivalent to self-assignment.
793 *this = o;
795 return;
796 }
797 if (o.m_head == 0xffff)
798 {
799 NS_ASSERT(o.m_tail == 0xffff);
800 // we have nothing to append.
801 return;
802 }
803 NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
804
805 // We read the current tail because we are going to append
806 // after this item.
808 PacketMetadata::ExtraItem tailExtraItem;
809 uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
810
811 uint16_t current;
814 o.ReadItems(o.m_head, &item, &extraItem);
815 if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
816 item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
817 extraItem.fragmentStart == tailExtraItem.fragmentEnd)
818 {
819 /* If the previous tail came from the same header as
820 * the next item we want to append to our array, then,
821 * we merge them and attempt to reuse the previous tail's
822 * location.
823 */
824 tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
825 ReplaceTail(&tailItem, &tailExtraItem, tailSize);
826 if (o.m_head == o.m_tail)
827 {
828 // there is only one item to append to self from other.
829 return;
830 }
831 current = item.next;
832 }
833 else
834 {
835 current = o.m_head;
836 }
837
838 /* Now that we have merged our current tail with the head of the
839 * next packet, we just append all items from the next packet
840 * to the current packet.
841 */
842 while (current != 0xffff)
843 {
844 o.ReadItems(current, &item, &extraItem);
845 uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
846 UpdateTail(written);
847 if (current == o.m_tail)
848 {
849 break;
850 }
851 current = item.next;
852 }
854}
855
856void
858{
859 NS_LOG_FUNCTION(this << end);
860 if (!m_enable)
861 {
862 m_metadataSkipped = true;
863 return;
864 }
865}
866
867void
869{
870 NS_LOG_FUNCTION(this << start);
871 if (!m_enable)
872 {
873 m_metadataSkipped = true;
874 return;
875 }
876 NS_ASSERT(m_data != nullptr);
877 uint32_t leftToRemove = start;
878 uint16_t current = m_head;
879 while (current != 0xffff && leftToRemove > 0)
880 {
883 ReadItems(current, &item, &extraItem);
884 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
885 if (itemRealSize <= leftToRemove)
886 {
887 // remove from list.
888 if (m_head == m_tail)
889 {
890 m_head = 0xffff;
891 m_tail = 0xffff;
892 }
893 else
894 {
895 m_head = item.next;
896 }
897 leftToRemove -= itemRealSize;
898 }
899 else
900 {
901 // fragment the list item.
902 PacketMetadata fragment(m_packetUid, 0);
903 extraItem.fragmentStart += leftToRemove;
904 leftToRemove = 0;
905 uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
906 fragment.UpdateTail(written);
907 while (current != 0xffff && current != m_tail)
908 {
909 current = item.next;
910 ReadItems(current, &item, &extraItem);
911 written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
912 fragment.UpdateTail(written);
913 }
914 *this = fragment;
915 }
916 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
917 extraItem.fragmentStart <= extraItem.fragmentEnd);
918 if (current == m_tail)
919 {
920 break;
921 }
922 current = item.next;
923 }
924 NS_ASSERT(leftToRemove == 0);
926}
927
928void
930{
931 NS_LOG_FUNCTION(this << end);
932 if (!m_enable)
933 {
934 m_metadataSkipped = true;
935 return;
936 }
937 NS_ASSERT(m_data != nullptr);
938
939 uint32_t leftToRemove = end;
940 uint16_t current = m_tail;
941 while (current != 0xffff && leftToRemove > 0)
942 {
945 ReadItems(current, &item, &extraItem);
946 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
947 if (itemRealSize <= leftToRemove)
948 {
949 // remove from list.
950 if (m_head == m_tail)
951 {
952 m_head = 0xffff;
953 m_tail = 0xffff;
954 }
955 else
956 {
957 m_tail = item.prev;
958 }
959 leftToRemove -= itemRealSize;
960 }
961 else
962 {
963 // fragment the list item.
964 PacketMetadata fragment(m_packetUid, 0);
965 NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
966 extraItem.fragmentEnd -= leftToRemove;
967 leftToRemove = 0;
968 uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
969 fragment.UpdateHead(written);
970 while (current != 0xffff && current != m_head)
971 {
972 current = item.prev;
973 ReadItems(current, &item, &extraItem);
974 written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
975 fragment.UpdateHead(written);
976 }
977 *this = fragment;
978 }
979 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
980 extraItem.fragmentStart <= extraItem.fragmentEnd);
981 if (current == m_head)
982 {
983 break;
984 }
985 current = item.prev;
986 }
987 NS_ASSERT(leftToRemove == 0);
989}
990
993{
994 NS_LOG_FUNCTION(this);
995 uint32_t totalSize = 0;
996 uint16_t current = m_head;
997 uint16_t tail = m_tail;
998 while (current != 0xffff)
999 {
1001 PacketMetadata::ExtraItem extraItem;
1002 ReadItems(current, &item, &extraItem);
1003 totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1004 if (current == tail)
1005 {
1006 break;
1007 }
1008 NS_ASSERT(current != item.next);
1009 current = item.next;
1010 }
1011 return totalSize;
1012}
1013
1014uint64_t
1016{
1017 NS_LOG_FUNCTION(this);
1018 return m_packetUid;
1019}
1020
1023{
1024 NS_LOG_FUNCTION(this << &buffer);
1025 return ItemIterator(this, buffer);
1026}
1027
1029 : m_metadata(metadata),
1030 m_buffer(buffer),
1031 m_current(metadata->m_head),
1032 m_offset(0),
1033 m_hasReadTail(false)
1034{
1035 NS_LOG_FUNCTION(this << metadata << &buffer);
1036}
1037
1038bool
1040{
1041 NS_LOG_FUNCTION(this);
1042 if (m_current == 0xffff)
1043 {
1044 return false;
1045 }
1046 if (m_hasReadTail)
1047 {
1048 return false;
1049 }
1050 return true;
1051}
1052
1055{
1056 NS_LOG_FUNCTION(this);
1058 PacketMetadata::SmallItem smallItem;
1059 PacketMetadata::ExtraItem extraItem;
1060 m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1061 if (m_current == m_metadata->m_tail)
1062 {
1063 m_hasReadTail = true;
1064 }
1065 m_current = smallItem.next;
1066 uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1067 item.tid.SetUid(uid);
1068 item.currentTrimmedFromStart = extraItem.fragmentStart;
1069 item.currentTrimmedFromEnd = extraItem.fragmentEnd - smallItem.size;
1070 item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1071 item.isFragment = (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size);
1072 TypeId tid;
1073 tid.SetUid(uid);
1074 if (uid == 0)
1075 {
1077 }
1078 else if (tid.IsChildOf(Header::GetTypeId()))
1079 {
1081 if (!item.isFragment)
1082 {
1083 item.current = m_buffer.Begin();
1084 item.current.Next(m_offset);
1085 }
1086 }
1087 else if (tid.IsChildOf(Trailer::GetTypeId()))
1088 {
1090 if (!item.isFragment)
1091 {
1092 item.current = m_buffer.End();
1093 item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1094 }
1095 }
1096 else
1097 {
1098 NS_ASSERT(false);
1099 }
1100 m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1101 return item;
1102}
1103
1106{
1107 NS_LOG_FUNCTION(this);
1108 uint32_t totalSize = 0;
1109
1110 // add 8 bytes for the packet uid
1111 totalSize += 8;
1112
1113 // if packet-metadata not enabled, total size
1114 // is simply 4-bytes for itself plus 8-bytes
1115 // for packet uid
1116 if (!m_enable)
1117 {
1118 return totalSize;
1119 }
1120
1122 PacketMetadata::ExtraItem extraItem;
1123 uint32_t current = m_head;
1124 while (current != 0xffff)
1125 {
1126 ReadItems(current, &item, &extraItem);
1127 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1128 if (uid == 0)
1129 {
1130 totalSize += 4;
1131 }
1132 else
1133 {
1134 TypeId tid;
1135 tid.SetUid(uid);
1136 totalSize += 4 + tid.GetName().size();
1137 }
1138 totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1139 if (current == m_tail)
1140 {
1141 break;
1142 }
1143 NS_ASSERT(current != item.next);
1144 current = item.next;
1145 }
1146 return totalSize;
1147}
1148
1150PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1151{
1152 NS_LOG_FUNCTION(this << &buffer << maxSize);
1153 uint8_t* start = buffer;
1154
1155 buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1156 if (buffer == nullptr)
1157 {
1158 return 0;
1159 }
1160
1162 PacketMetadata::ExtraItem extraItem;
1163 uint32_t current = m_head;
1164 while (current != 0xffff)
1165 {
1166 ReadItems(current, &item, &extraItem);
1167 NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1168 << ", typeUid=" << item.typeUid << ", size=" << item.size
1169 << ", chunkUid=" << item.chunkUid
1170 << ", fragmentStart=" << extraItem.fragmentStart
1171 << ", fragmentEnd=" << extraItem.fragmentEnd
1172 << ", packetUid=" << extraItem.packetUid);
1173
1174 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1175 if (uid != 0)
1176 {
1177 TypeId tid;
1178 tid.SetUid(uid);
1179 std::string uidString = tid.GetName();
1180 uint32_t uidStringSize = uidString.size();
1181 buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1182 if (buffer == nullptr)
1183 {
1184 return 0;
1185 }
1186 buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1187 uidStringSize,
1188 start,
1189 buffer,
1190 maxSize);
1191 if (buffer == nullptr)
1192 {
1193 return 0;
1194 }
1195 }
1196 else
1197 {
1198 buffer = AddToRawU32(0, start, buffer, maxSize);
1199 if (buffer == nullptr)
1200 {
1201 return 0;
1202 }
1203 }
1204
1205 uint8_t isBig = item.typeUid & 0x1;
1206 buffer = AddToRawU8(isBig, start, buffer, maxSize);
1207 if (buffer == nullptr)
1208 {
1209 return 0;
1210 }
1211
1212 buffer = AddToRawU32(item.size, start, buffer, maxSize);
1213 if (buffer == nullptr)
1214 {
1215 return 0;
1216 }
1217
1218 buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1219 if (buffer == nullptr)
1220 {
1221 return 0;
1222 }
1223
1224 buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1225 if (buffer == nullptr)
1226 {
1227 return 0;
1228 }
1229
1230 buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1231 if (buffer == nullptr)
1232 {
1233 return 0;
1234 }
1235
1236 buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1237 if (buffer == nullptr)
1238 {
1239 return 0;
1240 }
1241
1242 if (current == m_tail)
1243 {
1244 break;
1245 }
1246
1247 NS_ASSERT(current != item.next);
1248 current = item.next;
1249 }
1250
1251 NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1252 return 1;
1253}
1254
1256PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1257{
1258 NS_LOG_FUNCTION(this << &buffer << size);
1259 const uint8_t* start = buffer;
1260 uint32_t desSize = size - 4;
1261
1262 buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1263 desSize -= 8;
1264
1265 PacketMetadata::SmallItem item = {0};
1266 PacketMetadata::ExtraItem extraItem = {0};
1267 while (desSize > 0)
1268 {
1269 uint32_t uidStringSize = 0;
1270 buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1271 desSize -= 4;
1272 uint32_t uid;
1273 if (uidStringSize == 0)
1274 {
1275 // uid zero for payload.
1276 uid = 0;
1277 }
1278 else
1279 {
1280 std::string uidString;
1281 for (uint32_t j = 0; j < uidStringSize; j++)
1282 {
1283 uint8_t ch = 0;
1284 buffer = ReadFromRawU8(ch, start, buffer, size);
1285 uidString.push_back(ch);
1286 desSize--;
1287 }
1288 TypeId tid = TypeId::LookupByName(uidString);
1289 uid = tid.GetUid();
1290 }
1291 uint8_t isBig = 0;
1292 buffer = ReadFromRawU8(isBig, start, buffer, size);
1293 desSize--;
1294 item.typeUid = (uid << 1) | isBig;
1295 buffer = ReadFromRawU32(item.size, start, buffer, size);
1296 desSize -= 4;
1297 buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1298 desSize -= 2;
1299 buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1300 desSize -= 4;
1301 buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1302 desSize -= 4;
1303 buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1304 desSize -= 8;
1305 NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1306 << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1307 << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1308 << ", packetUid=" << extraItem.packetUid);
1309 uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1310 UpdateTail(tmp);
1311 }
1312 NS_ASSERT(desSize == 0);
1313 return (desSize != 0) ? 0 : 1;
1314}
1315
1316uint8_t*
1317PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1318{
1319 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1320 // First check buffer overflow
1321 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1322 {
1323 return nullptr;
1324 }
1325 memcpy(current, &data, sizeof(uint8_t));
1326 return current + sizeof(uint8_t);
1327}
1328
1329uint8_t*
1331 uint8_t* start,
1332 uint8_t* current,
1333 uint32_t maxSize)
1334{
1335 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1336 // First check buffer overflow
1337 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1338 {
1339 return nullptr;
1340 }
1341 memcpy(current, &data, sizeof(uint16_t));
1342 return current + sizeof(uint16_t);
1343}
1344
1345uint8_t*
1347 uint8_t* start,
1348 uint8_t* current,
1349 uint32_t maxSize)
1350{
1351 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1352 // First check buffer overflow
1353 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1354 {
1355 return nullptr;
1356 }
1357 memcpy(current, &data, sizeof(uint32_t));
1358 return current + sizeof(uint32_t);
1359}
1360
1361uint8_t*
1363 uint8_t* start,
1364 uint8_t* current,
1365 uint32_t maxSize)
1366{
1367 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1368 // First check buffer overflow
1369 if (static_cast<uint32_t>(current + sizeof(uint64_t) - start) > maxSize)
1370 {
1371 return nullptr;
1372 }
1373 memcpy(current, &data, sizeof(uint64_t));
1374 return current + sizeof(uint64_t);
1375}
1376
1377uint8_t*
1379 uint32_t dataSize,
1380 uint8_t* start,
1381 uint8_t* current,
1382 uint32_t maxSize)
1383{
1384 NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1385 // First check buffer overflow
1386 if (static_cast<uint32_t>(current + dataSize - start) > maxSize)
1387 {
1388 return nullptr;
1389 }
1390 memcpy(current, data, dataSize);
1391 return current + dataSize;
1392}
1393
1394uint8_t*
1396 const uint8_t* start,
1397 const uint8_t* current,
1398 uint32_t maxSize)
1399{
1400 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1401 // First check buffer underflow
1402 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1403 {
1404 return nullptr;
1405 }
1406 memcpy(&data, current, sizeof(uint8_t));
1407 return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1408}
1409
1410uint8_t*
1412 const uint8_t* start,
1413 const uint8_t* current,
1414 uint32_t maxSize)
1415{
1416 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1417 // First check buffer underflow
1418 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1419 {
1420 return nullptr;
1421 }
1422 memcpy(&data, current, sizeof(uint16_t));
1423 return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1424}
1425
1426uint8_t*
1428 const uint8_t* start,
1429 const uint8_t* current,
1430 uint32_t maxSize)
1431{
1432 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1433 // First check buffer underflow
1434 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1435 {
1436 return nullptr;
1437 }
1438 memcpy(&data, current, sizeof(uint32_t));
1439 return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1440}
1441
1442uint8_t*
1444 const uint8_t* start,
1445 const uint8_t* current,
1446 uint32_t maxSize)
1447{
1448 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1449 // First check buffer underflow
1450 if ((uint32_t)(current + sizeof(uint64_t) - start) > maxSize)
1451 {
1452 return nullptr;
1453 }
1454 memcpy(&data, current, sizeof(uint64_t));
1455 return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1456}
1457
1458} // 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