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;
31PacketMetadata::DataFreeList PacketMetadata::m_freeList;
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;
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;
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]));
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.
Iterator class for metadata items.
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.
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:48
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]
uint32_t m_size
size (in bytes) of m_data buffer below
uint8_t m_data[PACKET_METADATA_DATA_M_DATA_SIZE]
variable-sized buffer of bytes
uint32_t m_count
number of references to this struct Data instance.
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