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