A Discrete-Event Network Simulator
API
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 (iterator 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);
80 struct PacketMetadata::Data* newData = PacketMetadata::Create(m_used + 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
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 {
145 struct PacketMetadata::SmallItem item;
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
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, (uint16_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 {
510 struct PacketMetadata::SmallItem tmpItem;
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
526 struct PacketMetadata::SmallItem* item,
527 struct 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 {
577 struct PacketMetadata::Data* data = m_freeList.back();
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(struct Data);
619 {
621 }
623 uint8_t* buf = new uint8_t[size];
624 struct PacketMetadata::Data* data = (struct 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 uint8_t* 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);
654 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
655 DoAddHeader(uid, size);
657}
658
659void
661{
662 NS_LOG_FUNCTION(this << uid << size);
663 if (!m_enable)
664 {
665 m_metadataSkipped = true;
666 return;
667 }
668
669 struct PacketMetadata::SmallItem item;
670 item.next = m_head;
671 item.prev = 0xffff;
672 item.typeUid = uid;
673 item.size = size;
674 item.chunkUid = m_chunkUid;
675 m_chunkUid++;
676 uint16_t written = AddSmall(&item);
677 UpdateHead(written);
678}
679
680void
682{
683 uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
684 NS_LOG_FUNCTION(this << &header << size);
686 if (!m_enable)
687 {
688 m_metadataSkipped = true;
689 return;
690 }
691 struct PacketMetadata::SmallItem item;
692 struct PacketMetadata::ExtraItem extraItem;
693 uint32_t read = ReadItems(m_head, &item, &extraItem);
694 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
695 {
697 {
698 NS_FATAL_ERROR("Removing unexpected header.");
699 }
700 return;
701 }
702 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
703 {
705 {
706 NS_FATAL_ERROR("Removing incomplete header.");
707 }
708 return;
709 }
710 if (m_head + read == m_used)
711 {
712 m_used = m_head;
713 }
714 if (m_head == m_tail)
715 {
716 m_head = 0xffff;
717 m_tail = 0xffff;
718 }
719 else
720 {
721 m_head = item.next;
722 }
724}
725
726void
728{
729 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
730 NS_LOG_FUNCTION(this << &trailer << size);
732 if (!m_enable)
733 {
734 m_metadataSkipped = true;
735 return;
736 }
737 struct PacketMetadata::SmallItem item;
738 item.next = 0xffff;
739 item.prev = m_tail;
740 item.typeUid = uid;
741 item.size = size;
742 item.chunkUid = m_chunkUid;
743 m_chunkUid++;
744 uint16_t written = AddSmall(&item);
745 UpdateTail(written);
747}
748
749void
751{
752 uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
753 NS_LOG_FUNCTION(this << &trailer << size);
755 if (!m_enable)
756 {
757 m_metadataSkipped = true;
758 return;
759 }
760 struct PacketMetadata::SmallItem item;
761 struct PacketMetadata::ExtraItem extraItem;
762 uint32_t read = ReadItems(m_tail, &item, &extraItem);
763 if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
764 {
766 {
767 NS_FATAL_ERROR("Removing unexpected trailer.");
768 }
769 return;
770 }
771 else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
772 {
774 {
775 NS_FATAL_ERROR("Removing incomplete trailer.");
776 }
777 return;
778 }
779 if (m_tail + read == m_used)
780 {
781 m_used = m_tail;
782 }
783 if (m_head == m_tail)
784 {
785 m_head = 0xffff;
786 m_tail = 0xffff;
787 }
788 else
789 {
790 m_tail = item.prev;
791 }
793}
794
795void
797{
798 NS_LOG_FUNCTION(this << &o);
800 if (!m_enable)
801 {
802 m_metadataSkipped = true;
803 return;
804 }
805 if (m_tail == 0xffff)
806 {
807 // We have no items so 'AddAtEnd' is
808 // equivalent to self-assignment.
809 *this = o;
811 return;
812 }
813 if (o.m_head == 0xffff)
814 {
815 NS_ASSERT(o.m_tail == 0xffff);
816 // we have nothing to append.
817 return;
818 }
819 NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
820
821 // We read the current tail because we are going to append
822 // after this item.
823 struct PacketMetadata::SmallItem tailItem;
824 PacketMetadata::ExtraItem tailExtraItem;
825 uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
826
827 uint16_t current;
828 struct PacketMetadata::SmallItem item;
830 o.ReadItems(o.m_head, &item, &extraItem);
831 if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
832 item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
833 extraItem.fragmentStart == tailExtraItem.fragmentEnd)
834 {
835 /* If the previous tail came from the same header as
836 * the next item we want to append to our array, then,
837 * we merge them and attempt to reuse the previous tail's
838 * location.
839 */
840 tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
841 ReplaceTail(&tailItem, &tailExtraItem, tailSize);
842 if (o.m_head == o.m_tail)
843 {
844 // there is only one item to append to self from other.
845 return;
846 }
847 current = item.next;
848 }
849 else
850 {
851 current = o.m_head;
852 }
853
854 /* Now that we have merged our current tail with the head of the
855 * next packet, we just append all items from the next packet
856 * to the current packet.
857 */
858 while (current != 0xffff)
859 {
860 o.ReadItems(current, &item, &extraItem);
861 uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
862 UpdateTail(written);
863 if (current == o.m_tail)
864 {
865 break;
866 }
867 current = item.next;
868 }
870}
871
872void
874{
875 NS_LOG_FUNCTION(this << end);
876 if (!m_enable)
877 {
878 m_metadataSkipped = true;
879 return;
880 }
881}
882
883void
885{
886 NS_LOG_FUNCTION(this << start);
888 if (!m_enable)
889 {
890 m_metadataSkipped = true;
891 return;
892 }
893 NS_ASSERT(m_data != nullptr);
894 uint32_t leftToRemove = start;
895 uint16_t current = m_head;
896 while (current != 0xffff && leftToRemove > 0)
897 {
898 struct PacketMetadata::SmallItem item;
900 ReadItems(current, &item, &extraItem);
901 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
902 if (itemRealSize <= leftToRemove)
903 {
904 // remove from list.
905 if (m_head == m_tail)
906 {
907 m_head = 0xffff;
908 m_tail = 0xffff;
909 }
910 else
911 {
912 m_head = item.next;
913 }
914 leftToRemove -= itemRealSize;
915 }
916 else
917 {
918 // fragment the list item.
919 PacketMetadata fragment(m_packetUid, 0);
920 extraItem.fragmentStart += leftToRemove;
921 leftToRemove = 0;
922 uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
923 fragment.UpdateTail(written);
924 while (current != 0xffff && current != m_tail)
925 {
926 current = item.next;
927 ReadItems(current, &item, &extraItem);
928 written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
929 fragment.UpdateTail(written);
930 }
931 *this = fragment;
932 }
933 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
934 extraItem.fragmentStart <= extraItem.fragmentEnd);
935 if (current == m_tail)
936 {
937 break;
938 }
939 current = item.next;
940 }
941 NS_ASSERT(leftToRemove == 0);
943}
944
945void
947{
948 NS_LOG_FUNCTION(this << end);
950 if (!m_enable)
951 {
952 m_metadataSkipped = true;
953 return;
954 }
955 NS_ASSERT(m_data != nullptr);
956
957 uint32_t leftToRemove = end;
958 uint16_t current = m_tail;
959 while (current != 0xffff && leftToRemove > 0)
960 {
961 struct PacketMetadata::SmallItem item;
963 ReadItems(current, &item, &extraItem);
964 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
965 if (itemRealSize <= leftToRemove)
966 {
967 // remove from list.
968 if (m_head == m_tail)
969 {
970 m_head = 0xffff;
971 m_tail = 0xffff;
972 }
973 else
974 {
975 m_tail = item.prev;
976 }
977 leftToRemove -= itemRealSize;
978 }
979 else
980 {
981 // fragment the list item.
982 PacketMetadata fragment(m_packetUid, 0);
983 NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
984 extraItem.fragmentEnd -= leftToRemove;
985 leftToRemove = 0;
986 uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
987 fragment.UpdateHead(written);
988 while (current != 0xffff && current != m_head)
989 {
990 current = item.prev;
991 ReadItems(current, &item, &extraItem);
992 written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
993 fragment.UpdateHead(written);
994 }
995 *this = fragment;
996 }
997 NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
998 extraItem.fragmentStart <= extraItem.fragmentEnd);
999 if (current == m_head)
1000 {
1001 break;
1002 }
1003 current = item.prev;
1004 }
1005 NS_ASSERT(leftToRemove == 0);
1007}
1008
1011{
1012 NS_LOG_FUNCTION(this);
1013 uint32_t totalSize = 0;
1014 uint16_t current = m_head;
1015 uint16_t tail = m_tail;
1016 while (current != 0xffff)
1017 {
1018 struct PacketMetadata::SmallItem item;
1019 PacketMetadata::ExtraItem extraItem;
1020 ReadItems(current, &item, &extraItem);
1021 totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1022 if (current == tail)
1023 {
1024 break;
1025 }
1026 NS_ASSERT(current != item.next);
1027 current = item.next;
1028 }
1029 return totalSize;
1030}
1031
1032uint64_t
1034{
1035 NS_LOG_FUNCTION(this);
1036 return m_packetUid;
1037}
1038
1041{
1042 NS_LOG_FUNCTION(this << &buffer);
1043 return ItemIterator(this, buffer);
1044}
1045
1047 : m_metadata(metadata),
1048 m_buffer(buffer),
1049 m_current(metadata->m_head),
1050 m_offset(0),
1051 m_hasReadTail(false)
1052{
1053 NS_LOG_FUNCTION(this << metadata << &buffer);
1054}
1055
1056bool
1058{
1059 NS_LOG_FUNCTION(this);
1060 if (m_current == 0xffff)
1061 {
1062 return false;
1063 }
1064 if (m_hasReadTail)
1065 {
1066 return false;
1067 }
1068 return true;
1069}
1070
1073{
1074 NS_LOG_FUNCTION(this);
1075 struct PacketMetadata::Item item;
1076 struct PacketMetadata::SmallItem smallItem;
1077 struct PacketMetadata::ExtraItem extraItem;
1078 m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1079 if (m_current == m_metadata->m_tail)
1080 {
1081 m_hasReadTail = true;
1082 }
1083 m_current = smallItem.next;
1084 uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1085 item.tid.SetUid(uid);
1086 item.currentTrimedFromStart = extraItem.fragmentStart;
1087 item.currentTrimedFromEnd = extraItem.fragmentEnd - smallItem.size;
1088 item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1089 if (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size)
1090 {
1091 item.isFragment = true;
1092 }
1093 else
1094 {
1095 item.isFragment = false;
1096 }
1097 TypeId tid;
1098 tid.SetUid(uid);
1099 if (uid == 0)
1100 {
1102 }
1103 else if (tid.IsChildOf(Header::GetTypeId()))
1104 {
1106 if (!item.isFragment)
1107 {
1108 item.current = m_buffer.Begin();
1109 item.current.Next(m_offset);
1110 }
1111 }
1112 else if (tid.IsChildOf(Trailer::GetTypeId()))
1113 {
1115 if (!item.isFragment)
1116 {
1117 item.current = m_buffer.End();
1118 item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1119 }
1120 }
1121 else
1122 {
1123 NS_ASSERT(false);
1124 }
1125 m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1126 return item;
1127}
1128
1131{
1132 NS_LOG_FUNCTION(this);
1133 uint32_t totalSize = 0;
1134
1135 // add 8 bytes for the packet uid
1136 totalSize += 8;
1137
1138 // if packet-metadata not enabled, total size
1139 // is simply 4-bytes for itself plus 8-bytes
1140 // for packet uid
1141 if (!m_enable)
1142 {
1143 return totalSize;
1144 }
1145
1146 struct PacketMetadata::SmallItem item;
1147 struct PacketMetadata::ExtraItem extraItem;
1148 uint32_t current = m_head;
1149 while (current != 0xffff)
1150 {
1151 ReadItems(current, &item, &extraItem);
1152 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1153 if (uid == 0)
1154 {
1155 totalSize += 4;
1156 }
1157 else
1158 {
1159 TypeId tid;
1160 tid.SetUid(uid);
1161 totalSize += 4 + tid.GetName().size();
1162 }
1163 totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1164 if (current == m_tail)
1165 {
1166 break;
1167 }
1168 NS_ASSERT(current != item.next);
1169 current = item.next;
1170 }
1171 return totalSize;
1172}
1173
1175PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1176{
1177 NS_LOG_FUNCTION(this << &buffer << maxSize);
1178 uint8_t* start = buffer;
1179
1180 buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1181 if (buffer == nullptr)
1182 {
1183 return 0;
1184 }
1185
1186 struct PacketMetadata::SmallItem item;
1187 struct PacketMetadata::ExtraItem extraItem;
1188 uint32_t current = m_head;
1189 while (current != 0xffff)
1190 {
1191 ReadItems(current, &item, &extraItem);
1192 NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1193 << ", typeUid=" << item.typeUid << ", size=" << item.size
1194 << ", chunkUid=" << item.chunkUid
1195 << ", fragmentStart=" << extraItem.fragmentStart
1196 << ", fragmentEnd=" << extraItem.fragmentEnd
1197 << ", packetUid=" << extraItem.packetUid);
1198
1199 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1200 if (uid != 0)
1201 {
1202 TypeId tid;
1203 tid.SetUid(uid);
1204 std::string uidString = tid.GetName();
1205 uint32_t uidStringSize = uidString.size();
1206 buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1207 if (buffer == nullptr)
1208 {
1209 return 0;
1210 }
1211 buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1212 uidStringSize,
1213 start,
1214 buffer,
1215 maxSize);
1216 if (buffer == nullptr)
1217 {
1218 return 0;
1219 }
1220 }
1221 else
1222 {
1223 buffer = AddToRawU32(0, start, buffer, maxSize);
1224 if (buffer == nullptr)
1225 {
1226 return 0;
1227 }
1228 }
1229
1230 uint8_t isBig = item.typeUid & 0x1;
1231 buffer = AddToRawU8(isBig, start, buffer, maxSize);
1232 if (buffer == nullptr)
1233 {
1234 return 0;
1235 }
1236
1237 buffer = AddToRawU32(item.size, start, buffer, maxSize);
1238 if (buffer == nullptr)
1239 {
1240 return 0;
1241 }
1242
1243 buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1244 if (buffer == nullptr)
1245 {
1246 return 0;
1247 }
1248
1249 buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1250 if (buffer == nullptr)
1251 {
1252 return 0;
1253 }
1254
1255 buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1256 if (buffer == nullptr)
1257 {
1258 return 0;
1259 }
1260
1261 buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1262 if (buffer == nullptr)
1263 {
1264 return 0;
1265 }
1266
1267 if (current == m_tail)
1268 {
1269 break;
1270 }
1271
1272 NS_ASSERT(current != item.next);
1273 current = item.next;
1274 }
1275
1276 NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1277 return 1;
1278}
1279
1281PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1282{
1283 NS_LOG_FUNCTION(this << &buffer << size);
1284 const uint8_t* start = buffer;
1285 uint32_t desSize = size - 4;
1286
1287 buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1288 desSize -= 8;
1289
1290 struct PacketMetadata::SmallItem item = {0};
1291 struct PacketMetadata::ExtraItem extraItem = {0};
1292 while (desSize > 0)
1293 {
1294 uint32_t uidStringSize = 0;
1295 buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1296 desSize -= 4;
1297 uint32_t uid;
1298 if (uidStringSize == 0)
1299 {
1300 // uid zero for payload.
1301 uid = 0;
1302 }
1303 else
1304 {
1305 std::string uidString;
1306 for (uint32_t j = 0; j < uidStringSize; j++)
1307 {
1308 uint8_t ch = 0;
1309 buffer = ReadFromRawU8(ch, start, buffer, size);
1310 uidString.push_back(ch);
1311 desSize--;
1312 }
1313 TypeId tid = TypeId::LookupByName(uidString);
1314 uid = tid.GetUid();
1315 }
1316 uint8_t isBig = 0;
1317 buffer = ReadFromRawU8(isBig, start, buffer, size);
1318 desSize--;
1319 item.typeUid = (uid << 1) | isBig;
1320 buffer = ReadFromRawU32(item.size, start, buffer, size);
1321 desSize -= 4;
1322 buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1323 desSize -= 2;
1324 buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1325 desSize -= 4;
1326 buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1327 desSize -= 4;
1328 buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1329 desSize -= 8;
1330 NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1331 << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1332 << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1333 << ", packetUid=" << extraItem.packetUid);
1334 uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1335 UpdateTail(tmp);
1336 }
1337 NS_ASSERT(desSize == 0);
1338 return (desSize != 0) ? 0 : 1;
1339}
1340
1341uint8_t*
1342PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1343{
1344 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1345 // First check buffer overflow
1346 if (static_cast<uint32_t>((current + sizeof(uint8_t) - start)) > maxSize)
1347 {
1348 return nullptr;
1349 }
1350 memcpy(current, &data, sizeof(uint8_t));
1351 return current + sizeof(uint8_t);
1352}
1353
1354uint8_t*
1356 uint8_t* start,
1357 uint8_t* current,
1358 uint32_t maxSize)
1359{
1360 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1361 // First check buffer overflow
1362 if (static_cast<uint32_t>((current + sizeof(uint16_t) - start)) > maxSize)
1363 {
1364 return nullptr;
1365 }
1366 memcpy(current, &data, sizeof(uint16_t));
1367 return current + sizeof(uint16_t);
1368}
1369
1370uint8_t*
1372 uint8_t* start,
1373 uint8_t* current,
1374 uint32_t maxSize)
1375{
1376 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1377 // First check buffer overflow
1378 if (static_cast<uint32_t>((current + sizeof(uint32_t) - start)) > maxSize)
1379 {
1380 return nullptr;
1381 }
1382 memcpy(current, &data, sizeof(uint32_t));
1383 return current + sizeof(uint32_t);
1384}
1385
1386uint8_t*
1388 uint8_t* start,
1389 uint8_t* current,
1390 uint32_t maxSize)
1391{
1392 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1393 // First check buffer overflow
1394 if (static_cast<uint32_t>((current + sizeof(uint64_t) - start)) > maxSize)
1395 {
1396 return nullptr;
1397 }
1398 memcpy(current, &data, sizeof(uint64_t));
1399 return current + sizeof(uint64_t);
1400}
1401
1402uint8_t*
1404 uint32_t dataSize,
1405 uint8_t* start,
1406 uint8_t* current,
1407 uint32_t maxSize)
1408{
1409 NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1410 // First check buffer overflow
1411 if (static_cast<uint32_t>((current + dataSize - start)) > maxSize)
1412 {
1413 return nullptr;
1414 }
1415 memcpy(current, data, dataSize);
1416 return current + dataSize;
1417}
1418
1419uint8_t*
1421 const uint8_t* start,
1422 const uint8_t* current,
1423 uint32_t maxSize)
1424{
1425 NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1426 // First check buffer underflow
1427 if (static_cast<uint32_t>((current + sizeof(uint8_t) - start)) > maxSize)
1428 {
1429 return nullptr;
1430 }
1431 memcpy(&data, current, sizeof(uint8_t));
1432 return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1433}
1434
1435uint8_t*
1437 const uint8_t* start,
1438 const uint8_t* current,
1439 uint32_t maxSize)
1440{
1441 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1442 // First check buffer underflow
1443 if (static_cast<uint32_t>((current + sizeof(uint16_t) - start)) > maxSize)
1444 {
1445 return nullptr;
1446 }
1447 memcpy(&data, current, sizeof(uint16_t));
1448 return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1449}
1450
1451uint8_t*
1453 const uint8_t* start,
1454 const uint8_t* current,
1455 uint32_t maxSize)
1456{
1457 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1458 // First check buffer underflow
1459 if (static_cast<uint32_t>((current + sizeof(uint32_t) - start)) > maxSize)
1460 {
1461 return nullptr;
1462 }
1463 memcpy(&data, current, sizeof(uint32_t));
1464 return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1465}
1466
1467uint8_t*
1469 const uint8_t* start,
1470 const uint8_t* current,
1471 uint32_t maxSize)
1472{
1473 NS_LOG_FUNCTION(data << &start << &current << maxSize);
1474 // First check buffer underflow
1475 if ((uint32_t)((current + sizeof(uint64_t) - start)) > maxSize)
1476 {
1477 return nullptr;
1478 }
1479 memcpy(&data, current, sizeof(uint64_t));
1480 return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1481}
1482
1483} // namespace ns3
#define max(a, b)
Definition: 80211b.c:43
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.
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.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
void AddHeader(const Header &header, uint32_t size)
Add an header.
void AppendValueExtra(uint32_t value, uint8_t *buffer)
Append a value to the buffer - extra.
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 Deallocate(struct PacketMetadata::Data *data)
Deallocate 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 struct PacketMetadata::Data * Allocate(uint32_t n)
Allocate a buffer data storage.
static bool m_enable
Enable the packet metadata.
struct Data * m_data
Metadata storage.
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.
uint32_t ReadItems(uint16_t current, struct PacketMetadata::SmallItem *item, struct PacketMetadata::ExtraItem *extraItem) const
Read items.
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 struct PacketMetadata::Data * Create(uint32_t size)
Create a buffer data storage.
static uint16_t m_chunkUid
Chunk Uid.
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.
static void Recycle(struct PacketMetadata::Data *data)
Recycle the buffer memory.
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.
uint16_t m_used
used portion
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:60
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition: type-id.cc:975
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1216
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1209
std::string GetName() const
Get the name.
Definition: type-id.cc:995
#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:160
#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.
value
Definition: second.py:41
def start()
Definition: core.py:1861
#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]
uint16_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
TypeId tid
TypeId of Header or Trailer.
enum ns3::PacketMetadata::Item::ItemType type
metadata type
bool isFragment
true: this is a fragmented header, trailer, or, payload.
uint32_t currentTrimedFromEnd
how many bytes were trimmed from the end of a fragment.
uint32_t currentTrimedFromStart
how many bytes were trimmed from the start of a fragment.
Buffer::Iterator current
an iterator which can be fed to Deserialize.
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