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 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;
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;
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]));
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.
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: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]
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