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 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "packet-metadata.h"
20
21#include "buffer.h"
22#include "header.h"
23#include "trailer.h"
24
25#include "ns3/assert.h"
26#include "ns3/fatal-error.h"
27#include "ns3/log.h"
28
29#include <list>
30#include <utility>
31
32namespace ns3
33{
34
35NS_LOG_COMPONENT_DEFINE("PacketMetadata");
36
37bool PacketMetadata::m_enable = false;
42PacketMetadata::DataFreeList PacketMetadata::m_freeList;
43
45{
46 NS_LOG_FUNCTION(this);
47 for (auto i = begin(); i != end(); i++)
48 {
50 }
52}
53
54void
56{
59 "Error: attempting to enable the packet metadata "
60 "subsystem too late in the simulation, which is not allowed.\n"
61 "A common cause for this problem is to enable ASCII tracing "
62 "after sending any packets. One way to fix this problem is "
63 "to call ns3::PacketMetadata::Enable () near the beginning of"
64 " the program, before any packets are sent.");
65 m_enable = true;
66}
67
68void
70{
72 Enable();
73 m_enableChecking = true;
74}
75
76void
78{
79 NS_LOG_FUNCTION(this << size);
81 memcpy(newData->m_data, m_data->m_data, m_used);
82 newData->m_dirtyEnd = m_used;
83 m_data->m_count--;
84 if (m_data->m_count == 0)
85 {
87 }
88 m_data = newData;
89 if (m_head != 0xffff)
90 {
91 uint8_t* start;
92 NS_ASSERT(m_tail != 0xffff);
93 // clear the next field of the tail
94 start = &m_data->m_data[m_tail];
95 Append16(0xffff, start);
96 // clear the prev field of the head
97 start = &m_data->m_data[m_head] + 2;
98 Append16(0xffff, start);
99 }
100}
101
102void
104{
105 NS_LOG_FUNCTION(this << size);
106 NS_ASSERT(m_data != nullptr);
107 if (m_data->m_size >= m_used + size &&
108 (m_head == 0xffff || m_data->m_count == 1 || m_data->m_dirtyEnd == m_used))
109 {
110 /* enough room, not dirty. */
111 }
112 else
113 {
114 /* (enough room and dirty) or (not enough room) */
115 ReserveCopy(size);
116 }
117}
118
119bool
121{
122 NS_LOG_FUNCTION(this << pointer);
123 bool ok = pointer == 0xffff || pointer <= m_data->m_size;
124 return ok;
125}
126
127bool
128PacketMetadata::IsPointerOk(uint16_t pointer) const
129{
130 NS_LOG_FUNCTION(this << pointer);
131 bool ok = pointer == 0xffff || pointer <= m_used;
132 return ok;
133}
134
135bool
137{
138 NS_LOG_FUNCTION(this);
139 bool ok = m_used <= m_data->m_size;
140 ok &= IsPointerOk(m_head);
141 ok &= IsPointerOk(m_tail);
142 uint16_t current = m_head;
143 while (ok && current != 0xffff)
144 {
147 ReadItems(current, &item, &extraItem);
148 ok &= IsSharedPointerOk(item.next);
149 ok &= IsSharedPointerOk(item.prev);
150 if (current != m_head)
151 {
152 ok &= IsPointerOk(item.prev);
153 }
154 if (current != m_tail)
155 {
156 ok &= IsPointerOk(item.next);
157 }
158 if (current == m_tail)
159 {
160 break;
161 }
162 current = item.next;
163 }
164 return ok;
165}
166
169{
170 NS_LOG_FUNCTION(this << value);
171 if (value < 0x80)
172 {
173 return 1;
174 }
175 if (value < 0x4000)
176 {
177 return 2;
178 }
179 if (value < 0x200000)
180 {
181 return 3;
182 }
183 if (value < 0x10000000)
184 {
185 return 4;
186 }
187 return 5;
188}
189
191PacketMetadata::ReadUleb128(const uint8_t** pBuffer) const
192{
193 NS_LOG_FUNCTION(this << &pBuffer);
194 const uint8_t* buffer = *pBuffer;
195 uint32_t result;
196 uint8_t byte;
197
198 byte = buffer[0];
199 result = (byte & (~0x80));
200 if (!(byte & 0x80))
201 {
202 *pBuffer = buffer + 1;
203 return result;
204 }
205 byte = buffer[1];
206 result |= (byte & (~0x80)) << 7;
207 if (!(byte & 0x80))
208 {
209 *pBuffer = buffer + 2;
210 return result;
211 }
212 byte = buffer[2];
213 result |= (byte & (~0x80)) << 14;
214 if (!(byte & 0x80))
215 {
216 *pBuffer = buffer + 3;
217 return result;
218 }
219 byte = buffer[3];
220 result |= (byte & (~0x80)) << 21;
221 if (!(byte & 0x80))
222 {
223 *pBuffer = buffer + 4;
224 return result;
225 }
226 byte = buffer[4];
227 result |= (byte & (~0x80)) << 28;
228 if (!(byte & 0x80))
229 {
230 *pBuffer = buffer + 5;
231 return result;
232 }
233 /* This means that the LEB128 number was not valid.
234 * ie: the last (5th) byte did not have the high-order bit zeroed.
235 */
236 NS_ASSERT(false);
237 return 0;
238}
239
240void
241PacketMetadata::Append16(uint16_t value, uint8_t* buffer)
242{
243 NS_LOG_FUNCTION(this << value << &buffer);
244 buffer[0] = value & 0xff;
245 value >>= 8;
246 buffer[1] = value;
247}
248
249void
250PacketMetadata::Append32(uint32_t value, uint8_t* buffer)
251{
252 NS_LOG_FUNCTION(this << value << &buffer);
253 buffer[0] = value & 0xff;
254 buffer[1] = (value >> 8) & 0xff;
255 buffer[2] = (value >> 16) & 0xff;
256 buffer[3] = (value >> 24) & 0xff;
257}
258
259void
261{
262 NS_LOG_FUNCTION(this << value << &buffer);
263 if (value < 0x200000)
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 buffer[2] = value;
272 return;
273 }
274 if (value < 0x10000000)
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 buffer[3] = value;
286 return;
287 }
288 {
289 uint8_t byte = value & (~0x80);
290 buffer[0] = 0x80 | byte;
291 value >>= 7;
292 byte = value & (~0x80);
293 buffer[1] = 0x80 | byte;
294 value >>= 7;
295 byte = value & (~0x80);
296 buffer[2] = 0x80 | byte;
297 value >>= 7;
298 byte = value & (~0x80);
299 buffer[3] = 0x80 | byte;
300 value >>= 7;
301 buffer[4] = value;
302 }
303}
304
305void
307{
308 NS_LOG_FUNCTION(this << value << &buffer);
309 if (value < 0x80)
310 {
311 buffer[0] = value;
312 return;
313 }
314 if (value < 0x4000)
315 {
316 uint8_t byte = value & (~0x80);
317 buffer[0] = 0x80 | byte;
318 value >>= 7;
319 buffer[1] = value;
320 return;
321 }
322 AppendValueExtra(value, buffer);
323}
324
325void
327{
328 NS_LOG_FUNCTION(this << written);
329 if (m_head == 0xffff)
330 {
331 NS_ASSERT(m_tail == 0xffff);
332 m_head = m_used;
333 m_tail = m_used;
334 }
335 else
336 {
337 NS_ASSERT(m_tail != 0xffff);
338 // overwrite the next field of the previous tail of the list.
339 uint8_t* previousTail = &m_data->m_data[m_tail];
340 Append16(m_used, previousTail);
341 // update the tail of the list to the new node.
342 m_tail = m_used;
343 }
344 NS_ASSERT(m_tail != 0xffff);
345 NS_ASSERT(m_head != 0xffff);
346 NS_ASSERT(written >= 8);
347 m_used += written;
349}
350
351void
353{
354 NS_LOG_FUNCTION(this << written);
355 if (m_head == 0xffff)
356 {
357 NS_ASSERT(m_tail == 0xffff);
358 m_head = m_used;
359 m_tail = m_used;
360 }
361 else
362 {
363 NS_ASSERT(m_head != 0xffff);
364 // overwrite the prev field of the previous head of the list.
365 uint8_t* previousHead = &m_data->m_data[m_head + 2];
366 Append16(m_used, previousHead);
367 // update the head of list to the new node.
368 m_head = m_used;
369 }
370 NS_ASSERT(m_tail != 0xffff);
371 NS_ASSERT(m_head != 0xffff);
372 NS_ASSERT(written >= 8);
373 m_used += written;
375}
376
377uint16_t
379{
380 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
381 << item->chunkUid);
382 NS_ASSERT(m_data != nullptr);
383 NS_ASSERT(m_used != item->prev && m_used != item->next);
384 uint32_t typeUidSize = GetUleb128Size(item->typeUid);
385 uint32_t sizeSize = GetUleb128Size(item->size);
386 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
387 if (m_used + n > m_data->m_size ||
388 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
389 {
390 ReserveCopy(n);
391 }
392 uint8_t* buffer = &m_data->m_data[m_used];
393 Append16(item->next, buffer);
394 buffer += 2;
395 Append16(item->prev, buffer);
396 buffer += 2;
397 AppendValue(item->typeUid, buffer);
398 buffer += typeUidSize;
399 AppendValue(item->size, buffer);
400 buffer += sizeSize;
401 Append16(item->chunkUid, buffer);
402 return n;
403}
404
405uint16_t
408 const PacketMetadata::SmallItem* item,
409 const PacketMetadata::ExtraItem* extraItem)
410{
411 NS_LOG_FUNCTION(this << next << prev << item->next << item->prev << item->typeUid << item->size
412 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
413 << extraItem->packetUid);
414 NS_ASSERT(m_data != nullptr);
415 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
416 NS_ASSERT(m_used != prev && m_used != next);
417
418 uint32_t typeUidSize = GetUleb128Size(typeUid);
419 uint32_t sizeSize = GetUleb128Size(item->size);
420 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
421 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
422 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
423
424 if (m_used + n > m_data->m_size ||
425 (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
426 {
427 ReserveCopy(n);
428 }
429
430 uint8_t* buffer = &m_data->m_data[m_used];
431
432 Append16(next, buffer);
433 buffer += 2;
434 Append16(prev, buffer);
435 buffer += 2;
436 AppendValue(typeUid, buffer);
437 buffer += typeUidSize;
438 AppendValue(item->size, buffer);
439 buffer += sizeSize;
440 Append16(item->chunkUid, buffer);
441 buffer += 2;
442 AppendValue(extraItem->fragmentStart, buffer);
443 buffer += fragStartSize;
444 AppendValue(extraItem->fragmentEnd, buffer);
445 buffer += fragEndSize;
446 Append32(extraItem->packetUid, buffer);
447
448 return n;
449}
450
451void
453 PacketMetadata::ExtraItem* extraItem,
454 uint32_t available)
455{
456 NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
457 << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
458 << extraItem->packetUid << available);
459
460 NS_ASSERT(m_data != nullptr);
461 /* If the tail we want to replace is located at the end of the data array,
462 * and if there is extra room at the end of this array, then,
463 * we can try to use that extra space to avoid falling in the slow
464 * path below.
465 */
466 if (m_tail + available == m_used && m_used == m_data->m_dirtyEnd)
467 {
468 available = m_data->m_size - m_tail;
469 }
470
471 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
472 uint32_t typeUidSize = GetUleb128Size(typeUid);
473 uint32_t sizeSize = GetUleb128Size(item->size);
474 uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
475 uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
476 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
477
478 if (available >= n && m_data->m_count == 1)
479 {
480 uint8_t* buffer = &m_data->m_data[m_tail];
481 Append16(item->next, buffer);
482 buffer += 2;
483 Append16(item->prev, buffer);
484 buffer += 2;
485 AppendValue(typeUid, buffer);
486 buffer += typeUidSize;
487 AppendValue(item->size, buffer);
488 buffer += sizeSize;
489 Append16(item->chunkUid, buffer);
490 buffer += 2;
491 AppendValue(extraItem->fragmentStart, buffer);
492 buffer += fragStartSize;
493 AppendValue(extraItem->fragmentEnd, buffer);
494 buffer += fragEndSize;
495 Append32(extraItem->packetUid, buffer);
496 m_used = std::max(m_used, static_cast<uint32_t>(buffer - &m_data->m_data[0]));
498 return;
499 }
500
501 /* Below is the slow path which is hit if the new tail we want
502 * to append is bigger than the previous tail.
503 */
504
505 // create a copy of the packet without its tail.
507 uint16_t current = m_head;
508 while (current != 0xffff && current != m_tail)
509 {
511 PacketMetadata::ExtraItem tmpExtraItem;
512 ReadItems(current, &tmpItem, &tmpExtraItem);
513 uint16_t written = h.AddBig(0xffff, h.m_tail, &tmpItem, &tmpExtraItem);
514 h.UpdateTail(written);
515 current = tmpItem.next;
516 }
517 // append new tail.
518 uint16_t written = h.AddBig(0xffff, h.m_tail, item, extraItem);
519 h.UpdateTail(written);
520
521 *this = h;
522}
523
527 PacketMetadata::ExtraItem* extraItem) const
528{
529 NS_LOG_FUNCTION(this << current << item->chunkUid << item->prev << item->next << item->size
530 << item->typeUid << extraItem->fragmentEnd << extraItem->fragmentStart
531 << extraItem->packetUid);
532 NS_ASSERT(current <= m_data->m_size);
533 const uint8_t* buffer = &m_data->m_data[current];
534 item->next = buffer[0];
535 item->next |= (buffer[1]) << 8;
536 item->prev = buffer[2];
537 item->prev |= (buffer[3]) << 8;
538 buffer += 4;
539 item->typeUid = ReadUleb128(&buffer);
540 item->size = ReadUleb128(&buffer);
541 item->chunkUid = buffer[0];
542 item->chunkUid |= (buffer[1]) << 8;
543 buffer += 2;
544
545 bool isExtra = (item->typeUid & 0x1) == 0x1;
546 if (isExtra)
547 {
548 extraItem->fragmentStart = ReadUleb128(&buffer);
549 extraItem->fragmentEnd = ReadUleb128(&buffer);
550 extraItem->packetUid = buffer[0];
551 extraItem->packetUid |= buffer[1] << 8;
552 extraItem->packetUid |= buffer[2] << 16;
553 extraItem->packetUid |= buffer[3] << 24;
554 buffer += 4;
555 }
556 else
557 {
558 extraItem->fragmentStart = 0;
559 extraItem->fragmentEnd = item->size;
560 extraItem->packetUid = m_packetUid;
561 }
562 NS_ASSERT(buffer <= &m_data->m_data[m_data->m_size]);
563 return buffer - &m_data->m_data[current];
564}
565
568{
569 NS_LOG_FUNCTION(size);
570 NS_LOG_LOGIC("create size=" << size << ", max=" << m_maxSize);
571 if (size > m_maxSize)
572 {
573 m_maxSize = size;
574 }
575 while (!m_freeList.empty())
576 {
578 m_freeList.pop_back();
579 if (data->m_size >= size)
580 {
581 NS_LOG_LOGIC("create found size=" << data->m_size);
582 data->m_count = 1;
583 return data;
584 }
585 NS_LOG_LOGIC("create dealloc size=" << data->m_size);
587 }
588 NS_LOG_LOGIC("create alloc size=" << m_maxSize);
590}
591
592void
594{
596 if (!m_enable)
597 {
599 return;
600 }
601 NS_LOG_LOGIC("recycle size=" << data->m_size << ", list=" << m_freeList.size());
602 NS_ASSERT(data->m_count == 0);
603 if (m_freeList.size() > 1000 || data->m_size < m_maxSize)
604 {
606 }
607 else
608 {
609 m_freeList.push_back(data);
610 }
611}
612
615{
617 uint32_t size = sizeof(Data);
619 {
621 }
623 auto buf = new uint8_t[size];
624 auto data = (PacketMetadata::Data*)buf;
625 data->m_size = n;
626 data->m_count = 1;
627 data->m_dirtyEnd = 0;
628 return data;
629}
630
631void
633{
635 auto buf = (uint8_t*)data;
636 delete[] buf;
637}
638
641{
642 NS_LOG_FUNCTION(this << start << end);
643 PacketMetadata fragment = *this;
644 fragment.RemoveAtStart(start);
645 fragment.RemoveAtEnd(end);
646 return fragment;
647}
648
649void
651{
652 NS_LOG_FUNCTION(this << &header << size);
653 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
654 DoAddHeader(uid, size);
656}
657
658void
660{
661 NS_LOG_FUNCTION(this << uid << size);
662 if (!m_enable)
663 {
664 m_metadataSkipped = true;
665 return;
666 }
667
669 item.next = m_head;
670 item.prev = 0xffff;
671 item.typeUid = uid;
672 item.size = size;
673 item.chunkUid = m_chunkUid;
674 m_chunkUid++;
675 uint16_t written = AddSmall(&item);
676 UpdateHead(written);
677}
678
679void
681{
682 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
683 NS_LOG_FUNCTION(this << &header << size);
684 if (!m_enable)
685 {
686 m_metadataSkipped = true;
687 return;
688 }
691 uint32_t read = ReadItems(m_head, &item, &extraItem);
692 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
693 {
695 {
696 NS_FATAL_ERROR("Removing unexpected header.");
697 }
698 return;
699 }
700 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
701 {
703 {
704 NS_FATAL_ERROR("Removing incomplete header.");
705 }
706 return;
707 }
708 if (m_head + read == m_used)
709 {
710 m_used = m_head;
711 }
712 if (m_head == m_tail)
713 {
714 m_head = 0xffff;
715 m_tail = 0xffff;
716 }
717 else
718 {
719 m_head = item.next;
720 }
722}
723
724void
726{
727 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
728 NS_LOG_FUNCTION(this << &trailer << size);
729 if (!m_enable)
730 {
731 m_metadataSkipped = true;
732 return;
733 }
735 item.next = 0xffff;
736 item.prev = m_tail;
737 item.typeUid = uid;
738 item.size = size;
739 item.chunkUid = m_chunkUid;
740 m_chunkUid++;
741 uint16_t written = AddSmall(&item);
742 UpdateTail(written);
744}
745
746void
748{
749 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
750 NS_LOG_FUNCTION(this << &trailer << size);
751 if (!m_enable)
752 {
753 m_metadataSkipped = true;
754 return;
755 }
758 uint32_t read = ReadItems(m_tail, &item, &extraItem);
759 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
760 {
762 {
763 NS_FATAL_ERROR("Removing unexpected trailer.");
764 }
765 return;
766 }
767 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
768 {
770 {
771 NS_FATAL_ERROR("Removing incomplete trailer.");
772 }
773 return;
774 }
775 if (m_tail + read == m_used)
776 {
777 m_used = m_tail;
778 }
779 if (m_head == m_tail)
780 {
781 m_head = 0xffff;
782 m_tail = 0xffff;
783 }
784 else
785 {
786 m_tail = item.prev;
787 }
789}
790
791void
793{
794 NS_LOG_FUNCTION(this << &o);
795 if (!m_enable)
796 {
797 m_metadataSkipped = true;
798 return;
799 }
800 if (m_tail == 0xffff)
801 {
802 // We have no items so 'AddAtEnd' is
803 // equivalent to self-assignment.
804 *this = o;
806 return;
807 }
808 if (o.m_head == 0xffff)
809 {
810 NS_ASSERT(o.m_tail == 0xffff);
811 // we have nothing to append.
812 return;
813 }
814 NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
815
816 // We read the current tail because we are going to append
817 // after this item.
819 PacketMetadata::ExtraItem tailExtraItem;
820 uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
821
822 uint16_t current;
825 o.ReadItems(o.m_head, &item, &extraItem);
826 if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
827 item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
828 extraItem.fragmentStart == tailExtraItem.fragmentEnd)
829 {
830 /* If the previous tail came from the same header as
831 * the next item we want to append to our array, then,
832 * we merge them and attempt to reuse the previous tail's
833 * location.
834 */
835 tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
836 ReplaceTail(&tailItem, &tailExtraItem, tailSize);
837 if (o.m_head == o.m_tail)
838 {
839 // there is only one item to append to self from other.
840 return;
841 }
842 current = item.next;
843 }
844 else
845 {
846 current = o.m_head;
847 }
848
849 /* Now that we have merged our current tail with the head of the
850 * next packet, we just append all items from the next packet
851 * to the current packet.
852 */
853 while (current != 0xffff)
854 {
855 o.ReadItems(current, &item, &extraItem);
856 uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
857 UpdateTail(written);
858 if (current == o.m_tail)
859 {
860 break;
861 }
862 current = item.next;
863 }
865}
866
867void
869{
870 NS_LOG_FUNCTION(this << end);
871 if (!m_enable)
872 {
873 m_metadataSkipped = true;
874 return;
875 }
876}
877
878void
880{
881 NS_LOG_FUNCTION(this << start);
882 if (!m_enable)
883 {
884 m_metadataSkipped = true;
885 return;
886 }
887 NS_ASSERT(m_data != nullptr);
888 uint32_t leftToRemove = start;
889 uint16_t current = m_head;
890 while (current != 0xffff && leftToRemove > 0)
891 {
894 ReadItems(current, &item, &extraItem);
895 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
896 if (itemRealSize <= leftToRemove)
897 {
898 // remove from list.
899 if (m_head == m_tail)
900 {
901 m_head = 0xffff;
902 m_tail = 0xffff;
903 }
904 else
905 {
906 m_head = item.next;
907 }
908 leftToRemove -= itemRealSize;
909 }
910 else
911 {
912 // fragment the list item.
913 PacketMetadata fragment(m_packetUid, 0);
914 extraItem.fragmentStart += leftToRemove;
915 leftToRemove = 0;
916 uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
917 fragment.UpdateTail(written);
918 while (current != 0xffff && current != m_tail)
919 {
920 current = item.next;
921 ReadItems(current, &item, &extraItem);
922 written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
923 fragment.UpdateTail(written);
924 }
925 *this = fragment;
926 }
927 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
928 extraItem.fragmentStart <= extraItem.fragmentEnd);
929 if (current == m_tail)
930 {
931 break;
932 }
933 current = item.next;
934 }
935 NS_ASSERT(leftToRemove == 0);
937}
938
939void
941{
942 NS_LOG_FUNCTION(this << end);
943 if (!m_enable)
944 {
945 m_metadataSkipped = true;
946 return;
947 }
948 NS_ASSERT(m_data != nullptr);
949
950 uint32_t leftToRemove = end;
951 uint16_t current = m_tail;
952 while (current != 0xffff && leftToRemove > 0)
953 {
956 ReadItems(current, &item, &extraItem);
957 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
958 if (itemRealSize <= leftToRemove)
959 {
960 // remove from list.
961 if (m_head == m_tail)
962 {
963 m_head = 0xffff;
964 m_tail = 0xffff;
965 }
966 else
967 {
968 m_tail = item.prev;
969 }
970 leftToRemove -= itemRealSize;
971 }
972 else
973 {
974 // fragment the list item.
975 PacketMetadata fragment(m_packetUid, 0);
976 NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
977 extraItem.fragmentEnd -= leftToRemove;
978 leftToRemove = 0;
979 uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
980 fragment.UpdateHead(written);
981 while (current != 0xffff && current != m_head)
982 {
983 current = item.prev;
984 ReadItems(current, &item, &extraItem);
985 written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
986 fragment.UpdateHead(written);
987 }
988 *this = fragment;
989 }
990 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
991 extraItem.fragmentStart <= extraItem.fragmentEnd);
992 if (current == m_head)
993 {
994 break;
995 }
996 current = item.prev;
997 }
998 NS_ASSERT(leftToRemove == 0);
1000}
1001
1004{
1005 NS_LOG_FUNCTION(this);
1006 uint32_t totalSize = 0;
1007 uint16_t current = m_head;
1008 uint16_t tail = m_tail;
1009 while (current != 0xffff)
1010 {
1012 PacketMetadata::ExtraItem extraItem;
1013 ReadItems(current, &item, &extraItem);
1014 totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1015 if (current == tail)
1016 {
1017 break;
1018 }
1019 NS_ASSERT(current != item.next);
1020 current = item.next;
1021 }
1022 return totalSize;
1023}
1024
1025uint64_t
1027{
1028 NS_LOG_FUNCTION(this);
1029 return m_packetUid;
1030}
1031
1034{
1035 NS_LOG_FUNCTION(this << &buffer);
1036 return ItemIterator(this, buffer);
1037}
1038
1040 : m_metadata(metadata),
1041 m_buffer(buffer),
1042 m_current(metadata->m_head),
1043 m_offset(0),
1044 m_hasReadTail(false)
1045{
1046 NS_LOG_FUNCTION(this << metadata << &buffer);
1047}
1048
1049bool
1051{
1052 NS_LOG_FUNCTION(this);
1053 if (m_current == 0xffff)
1054 {
1055 return false;
1056 }
1057 if (m_hasReadTail)
1058 {
1059 return false;
1060 }
1061 return true;
1062}
1063
1066{
1067 NS_LOG_FUNCTION(this);
1069 PacketMetadata::SmallItem smallItem;
1070 PacketMetadata::ExtraItem extraItem;
1071 m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1072 if (m_current == m_metadata->m_tail)
1073 {
1074 m_hasReadTail = true;
1075 }
1076 m_current = smallItem.next;
1077 uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1078 item.tid.SetUid(uid);
1079 item.currentTrimmedFromStart = extraItem.fragmentStart;
1080 item.currentTrimmedFromEnd = extraItem.fragmentEnd - smallItem.size;
1081 item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1082 item.isFragment = (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size);
1083 TypeId tid;
1084 tid.SetUid(uid);
1085 if (uid == 0)
1086 {
1088 }
1089 else if (tid.IsChildOf(Header::GetTypeId()))
1090 {
1092 if (!item.isFragment)
1093 {
1094 item.current = m_buffer.Begin();
1095 item.current.Next(m_offset);
1096 }
1097 }
1098 else if (tid.IsChildOf(Trailer::GetTypeId()))
1099 {
1101 if (!item.isFragment)
1102 {
1103 item.current = m_buffer.End();
1104 item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1105 }
1106 }
1107 else
1108 {
1109 NS_ASSERT(false);
1110 }
1111 m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1112 return item;
1113}
1114
1117{
1118 NS_LOG_FUNCTION(this);
1119 uint32_t totalSize = 0;
1120
1121 // add 8 bytes for the packet uid
1122 totalSize += 8;
1123
1124 // if packet-metadata not enabled, total size
1125 // is simply 4-bytes for itself plus 8-bytes
1126 // for packet uid
1127 if (!m_enable)
1128 {
1129 return totalSize;
1130 }
1131
1133 PacketMetadata::ExtraItem extraItem;
1134 uint32_t current = m_head;
1135 while (current != 0xffff)
1136 {
1137 ReadItems(current, &item, &extraItem);
1138 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1139 if (uid == 0)
1140 {
1141 totalSize += 4;
1142 }
1143 else
1144 {
1145 TypeId tid;
1146 tid.SetUid(uid);
1147 totalSize += 4 + tid.GetName().size();
1148 }
1149 totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1150 if (current == m_tail)
1151 {
1152 break;
1153 }
1154 NS_ASSERT(current != item.next);
1155 current = item.next;
1156 }
1157 return totalSize;
1158}
1159
1161PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1162{
1163 NS_LOG_FUNCTION(this << &buffer << maxSize);
1164 uint8_t* start = buffer;
1165
1166 buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1167 if (buffer == nullptr)
1168 {
1169 return 0;
1170 }
1171
1173 PacketMetadata::ExtraItem extraItem;
1174 uint32_t current = m_head;
1175 while (current != 0xffff)
1176 {
1177 ReadItems(current, &item, &extraItem);
1178 NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1179 << ", typeUid=" << item.typeUid << ", size=" << item.size
1180 << ", chunkUid=" << item.chunkUid
1181 << ", fragmentStart=" << extraItem.fragmentStart
1182 << ", fragmentEnd=" << extraItem.fragmentEnd
1183 << ", packetUid=" << extraItem.packetUid);
1184
1185 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1186 if (uid != 0)
1187 {
1188 TypeId tid;
1189 tid.SetUid(uid);
1190 std::string uidString = tid.GetName();
1191 uint32_t uidStringSize = uidString.size();
1192 buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1193 if (buffer == nullptr)
1194 {
1195 return 0;
1196 }
1197 buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1198 uidStringSize,
1199 start,
1200 buffer,
1201 maxSize);
1202 if (buffer == nullptr)
1203 {
1204 return 0;
1205 }
1206 }
1207 else
1208 {
1209 buffer = AddToRawU32(0, start, buffer, maxSize);
1210 if (buffer == nullptr)
1211 {
1212 return 0;
1213 }
1214 }
1215
1216 uint8_t isBig = item.typeUid & 0x1;
1217 buffer = AddToRawU8(isBig, start, buffer, maxSize);
1218 if (buffer == nullptr)
1219 {
1220 return 0;
1221 }
1222
1223 buffer = AddToRawU32(item.size, start, buffer, maxSize);
1224 if (buffer == nullptr)
1225 {
1226 return 0;
1227 }
1228
1229 buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1230 if (buffer == nullptr)
1231 {
1232 return 0;
1233 }
1234
1235 buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1236 if (buffer == nullptr)
1237 {
1238 return 0;
1239 }
1240
1241 buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1242 if (buffer == nullptr)
1243 {
1244 return 0;
1245 }
1246
1247 buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1248 if (buffer == nullptr)
1249 {
1250 return 0;
1251 }
1252
1253 if (current == m_tail)
1254 {
1255 break;
1256 }
1257
1258 NS_ASSERT(current != item.next);
1259 current = item.next;
1260 }
1261
1262 NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1263 return 1;
1264}
1265
1267PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1268{
1269 NS_LOG_FUNCTION(this << &buffer << size);
1270 const uint8_t* start = buffer;
1271 uint32_t desSize = size - 4;
1272
1273 buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1274 desSize -= 8;
1275
1276 PacketMetadata::SmallItem item = {0};
1277 PacketMetadata::ExtraItem extraItem = {0};
1278 while (desSize > 0)
1279 {
1280 uint32_t uidStringSize = 0;
1281 buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1282 desSize -= 4;
1283 uint32_t uid;
1284 if (uidStringSize == 0)
1285 {
1286 // uid zero for payload.
1287 uid = 0;
1288 }
1289 else
1290 {
1291 std::string uidString;
1292 for (uint32_t j = 0; j < uidStringSize; j++)
1293 {
1294 uint8_t ch = 0;
1295 buffer = ReadFromRawU8(ch, start, buffer, size);
1296 uidString.push_back(ch);
1297 desSize--;
1298 }
1299 TypeId tid = TypeId::LookupByName(uidString);
1300 uid = tid.GetUid();
1301 }
1302 uint8_t isBig = 0;
1303 buffer = ReadFromRawU8(isBig, start, buffer, size);
1304 desSize--;
1305 item.typeUid = (uid << 1) | isBig;
1306 buffer = ReadFromRawU32(item.size, start, buffer, size);
1307 desSize -= 4;
1308 buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1309 desSize -= 2;
1310 buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1311 desSize -= 4;
1312 buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1313 desSize -= 4;
1314 buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1315 desSize -= 8;
1316 NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1317 << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1318 << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1319 << ", packetUid=" << extraItem.packetUid);
1320 uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1321 UpdateTail(tmp);
1322 }
1323 NS_ASSERT(desSize == 0);
1324 return (desSize != 0) ? 0 : 1;
1325}
1326
1327uint8_t*
1328PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1329{
1330 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1331 // First check buffer overflow
1332 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1333 {
1334 return nullptr;
1335 }
1336 memcpy(current, &data, sizeof(uint8_t));
1337 return current + sizeof(uint8_t);
1338}
1339
1340uint8_t*
1342 uint8_t* start,
1343 uint8_t* current,
1344 uint32_t maxSize)
1345{
1346 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1347 // First check buffer overflow
1348 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1349 {
1350 return nullptr;
1351 }
1352 memcpy(current, &data, sizeof(uint16_t));
1353 return current + sizeof(uint16_t);
1354}
1355
1356uint8_t*
1358 uint8_t* start,
1359 uint8_t* current,
1360 uint32_t maxSize)
1361{
1362 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1363 // First check buffer overflow
1364 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1365 {
1366 return nullptr;
1367 }
1368 memcpy(current, &data, sizeof(uint32_t));
1369 return current + sizeof(uint32_t);
1370}
1371
1372uint8_t*
1374 uint8_t* start,
1375 uint8_t* current,
1376 uint32_t maxSize)
1377{
1378 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1379 // First check buffer overflow
1380 if (static_cast<uint32_t>(current + sizeof(uint64_t) - start) > maxSize)
1381 {
1382 return nullptr;
1383 }
1384 memcpy(current, &data, sizeof(uint64_t));
1385 return current + sizeof(uint64_t);
1386}
1387
1388uint8_t*
1390 uint32_t dataSize,
1391 uint8_t* start,
1392 uint8_t* current,
1393 uint32_t maxSize)
1394{
1395 NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1396 // First check buffer overflow
1397 if (static_cast<uint32_t>(current + dataSize - start) > maxSize)
1398 {
1399 return nullptr;
1400 }
1401 memcpy(current, data, dataSize);
1402 return current + dataSize;
1403}
1404
1405uint8_t*
1407 const uint8_t* start,
1408 const uint8_t* current,
1409 uint32_t maxSize)
1410{
1411 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1412 // First check buffer underflow
1413 if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1414 {
1415 return nullptr;
1416 }
1417 memcpy(&data, current, sizeof(uint8_t));
1418 return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1419}
1420
1421uint8_t*
1423 const uint8_t* start,
1424 const uint8_t* current,
1425 uint32_t maxSize)
1426{
1427 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1428 // First check buffer underflow
1429 if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1430 {
1431 return nullptr;
1432 }
1433 memcpy(&data, current, sizeof(uint16_t));
1434 return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1435}
1436
1437uint8_t*
1439 const uint8_t* start,
1440 const uint8_t* current,
1441 uint32_t maxSize)
1442{
1443 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1444 // First check buffer underflow
1445 if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1446 {
1447 return nullptr;
1448 }
1449 memcpy(&data, current, sizeof(uint32_t));
1450 return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1451}
1452
1453uint8_t*
1455 const uint8_t* start,
1456 const uint8_t* current,
1457 uint32_t maxSize)
1458{
1459 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1460 // First check buffer underflow
1461 if ((uint32_t)(current + sizeof(uint64_t) - start) > maxSize)
1462 {
1463 return nullptr;
1464 }
1465 memcpy(&data, current, sizeof(uint64_t));
1466 return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1467}
1468
1469} // namespace ns3
void Prev()
go backward by one byte
Definition: buffer.h:860
void Next()
go forward by one byte
Definition: buffer.h:853
automatically resized byte buffer
Definition: buffer.h:94
Protocol header serialization and deserialization.
Definition: header.h:44
static TypeId GetTypeId()
Get the type ID.
Definition: header.cc:37
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.
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:41
static TypeId GetTypeId()
Get the type ID.
Definition: trailer.cc:37
a unique identifier for an interface.
Definition: type-id.h:59
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition: type-id.cc:972
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:836
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1213
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1206
std::string GetName() const
Get the name.
Definition: type-id.cc:992
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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