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 
30 namespace ns3 {
31 
32 NS_LOG_COMPONENT_DEFINE ("PacketMetadata");
33 
34 bool PacketMetadata::m_enable = false;
37 uint32_t PacketMetadata::m_maxSize = 0;
38 uint16_t PacketMetadata::m_chunkUid = 0;
39 PacketMetadata::DataFreeList PacketMetadata::m_freeList;
40 
42 {
43  NS_LOG_FUNCTION (this);
44  for (iterator i = begin (); i != end (); i++)
45  {
47  }
48  PacketMetadata::m_enable = false;
49 }
50 
51 void
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 
65 void
67 {
69  Enable ();
70  m_enableChecking = true;
71 }
72 
73 void
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
91  start = &m_data->m_data[m_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 }
98 void
99 PacketMetadata::Reserve (uint32_t size)
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 ||
106  m_data->m_dirtyEnd == m_used))
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 
117 bool
118 PacketMetadata::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 }
124 bool
125 PacketMetadata::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 
132 bool
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;
143  PacketMetadata::ExtraItem extraItem;
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 
164 uint32_t
165 PacketMetadata::GetUleb128Size (uint32_t value) const
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 }
186 uint32_t
187 PacketMetadata::ReadUleb128 (const uint8_t **pBuffer) const
188 {
189  NS_LOG_FUNCTION (this << &pBuffer);
190  const uint8_t *buffer = *pBuffer;
191  uint32_t result = 0;
192  uint8_t byte;
193  result = 0;
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 
236 void
237 PacketMetadata::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 }
244 void
245 PacketMetadata::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 
254 void
255 PacketMetadata::AppendValueExtra (uint32_t value, uint8_t *buffer)
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  byte = value & (~0x80);
267  buffer[2] = value;
268  return;
269  }
270  if (value < 0x10000000)
271  {
272  uint8_t byte = value & (~0x80);
273  buffer[0] = 0x80 | byte;
274  value >>= 7;
275  byte = value & (~0x80);
276  buffer[1] = 0x80 | byte;
277  value >>= 7;
278  byte = value & (~0x80);
279  buffer[2] = 0x80 | byte;
280  value >>= 7;
281  buffer[3] = value;
282  return;
283  }
284  {
285  uint8_t byte = value & (~0x80);
286  buffer[0] = 0x80 | byte;
287  value >>= 7;
288  byte = value & (~0x80);
289  buffer[1] = 0x80 | byte;
290  value >>= 7;
291  byte = value & (~0x80);
292  buffer[2] = 0x80 | byte;
293  value >>= 7;
294  byte = value & (~0x80);
295  buffer[3] = 0x80 | byte;
296  value >>= 7;
297  buffer[4] = value;
298  }
299 }
300 
301 void
302 PacketMetadata::AppendValue (uint32_t value, uint8_t *buffer)
303 {
304  NS_LOG_FUNCTION (this << value << &buffer);
305  if (value < 0x80)
306  {
307  buffer[0] = value;
308  return;
309  }
310  if (value < 0x4000)
311  {
312  uint8_t byte = value & (~0x80);
313  buffer[0] = 0x80 | byte;
314  value >>= 7;
315  buffer[1] = value;
316  return;
317  }
318  AppendValueExtra (value, buffer);
319 }
320 
321 void
322 PacketMetadata::UpdateTail (uint16_t written)
323 {
324  NS_LOG_FUNCTION (this << written);
325  if (m_head == 0xffff)
326  {
327  NS_ASSERT (m_tail == 0xffff);
328  m_head = m_used;
329  m_tail = m_used;
330  }
331  else
332  {
333  NS_ASSERT (m_tail != 0xffff);
334  // overwrite the next field of the previous tail of the list.
335  uint8_t *previousTail = &m_data->m_data[m_tail];
336  Append16 (m_used, previousTail);
337  // update the tail of the list to the new node.
338  m_tail = m_used;
339  }
340  NS_ASSERT (m_tail != 0xffff);
341  NS_ASSERT (m_head != 0xffff);
342  NS_ASSERT (written >= 8);
343  m_used += written;
345 }
346 
347 
348 void
349 PacketMetadata::UpdateHead (uint16_t written)
350 {
351  NS_LOG_FUNCTION (this << written);
352  if (m_head == 0xffff)
353  {
354  NS_ASSERT (m_tail == 0xffff);
355  m_head = m_used;
356  m_tail = m_used;
357  }
358  else
359  {
360  NS_ASSERT (m_head != 0xffff);
361  // overwrite the prev field of the previous head of the list.
362  uint8_t *previousHead = &m_data->m_data[m_head + 2];
363  Append16 (m_used, previousHead);
364  // update the head of list to the new node.
365  m_head = m_used;
366  }
367  NS_ASSERT (m_tail != 0xffff);
368  NS_ASSERT (m_head != 0xffff);
369  NS_ASSERT (written >= 8);
370  m_used += written;
372 }
373 
374 uint16_t
376 {
377  NS_LOG_FUNCTION (this << item->next << item->prev << item->typeUid << item->size << item->chunkUid);
378  NS_ASSERT (m_data != 0);
379  NS_ASSERT (m_used != item->prev && m_used != item->next);
380  uint32_t typeUidSize = GetUleb128Size (item->typeUid);
381  uint32_t sizeSize = GetUleb128Size (item->size);
382  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
383  if (m_used + n > m_data->m_size ||
384  (m_head != 0xffff &&
385  m_data->m_count != 1 &&
386  m_used != m_data->m_dirtyEnd))
387  {
388  ReserveCopy (n);
389  }
390  uint8_t *buffer = &m_data->m_data[m_used];
391  Append16 (item->next, buffer);
392  buffer += 2;
393  Append16 (item->prev, buffer);
394  buffer += 2;
395  AppendValue (item->typeUid, buffer);
396  buffer += typeUidSize;
397  AppendValue (item->size, buffer);
398  buffer += sizeSize;
399  Append16 (item->chunkUid, buffer);
400  return n;
401 }
402 
403 uint16_t
404 PacketMetadata::AddBig (uint32_t next, uint32_t prev,
405  const PacketMetadata::SmallItem *item,
406  const PacketMetadata::ExtraItem *extraItem)
407 {
408  NS_LOG_FUNCTION (this << next << prev <<
409  item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
410  extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid);
411  NS_ASSERT (m_data != 0);
412  uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid+1;
413  NS_ASSERT (m_used != prev && m_used != next);
414 
415  uint32_t typeUidSize = GetUleb128Size (typeUid);
416  uint32_t sizeSize = GetUleb128Size (item->size);
417  uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
418  uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
419  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
420 
421  if (m_used + n > m_data->m_size ||
422  (m_head != 0xffff &&
423  m_data->m_count != 1 &&
424  m_used != m_data->m_dirtyEnd))
425  {
426  ReserveCopy (n);
427  }
428 
429  uint8_t *buffer = &m_data->m_data[m_used];
430 
431  Append16 (next, buffer);
432  buffer += 2;
433  Append16 (prev, buffer);
434  buffer += 2;
435  AppendValue (typeUid, buffer);
436  buffer += typeUidSize;
437  AppendValue (item->size, buffer);
438  buffer += sizeSize;
439  Append16 (item->chunkUid, buffer);
440  buffer += 2;
441  AppendValue (extraItem->fragmentStart, buffer);
442  buffer += fragStartSize;
443  AppendValue (extraItem->fragmentEnd, buffer);
444  buffer += fragEndSize;
445  Append32 (extraItem->packetUid, buffer);
446 
447  return n;
448 }
449 
450 void
452  PacketMetadata::ExtraItem *extraItem,
453  uint32_t available)
454 {
455  NS_LOG_FUNCTION (this <<
456  item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
457  extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid <<
458  available);
459 
460  NS_ASSERT (m_data != 0);
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 &&
468  {
469  available = m_data->m_size - m_tail;
470  }
471 
472  uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid+1;
473  uint32_t typeUidSize = GetUleb128Size (typeUid);
474  uint32_t sizeSize = GetUleb128Size (item->size);
475  uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
476  uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
477  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
478 
479  if (available >= n &&
480  m_data->m_count == 1)
481  {
482  uint8_t *buffer = &m_data->m_data[m_tail];
483  Append16 (item->next, buffer);
484  buffer += 2;
485  Append16 (item->prev, buffer);
486  buffer += 2;
487  AppendValue (typeUid, buffer);
488  buffer += typeUidSize;
489  AppendValue (item->size, buffer);
490  buffer += sizeSize;
491  Append16 (item->chunkUid, buffer);
492  buffer += 2;
493  AppendValue (extraItem->fragmentStart, buffer);
494  buffer += fragStartSize;
495  AppendValue (extraItem->fragmentEnd, buffer);
496  buffer += fragEndSize;
497  Append32 (extraItem->packetUid, buffer);
498  m_used = std::max (m_used, (uint16_t)(buffer - &m_data->m_data[0]));
500  return;
501  }
502 
503  /* Below is the slow path which is hit if the new tail we want
504  * to append is bigger than the previous tail.
505  */
506 
507  // create a copy of the packet without its tail.
509  uint16_t current = m_head;
510  while (current != 0xffff && current != m_tail)
511  {
512  struct PacketMetadata::SmallItem tmpItem;
513  PacketMetadata::ExtraItem tmpExtraItem;
514  ReadItems (current, &tmpItem, &tmpExtraItem);
515  uint16_t written = h.AddBig (0xffff, h.m_tail,
516  &tmpItem, &tmpExtraItem);
517  h.UpdateTail (written);
518  current = tmpItem.next;
519  }
520  // append new tail.
521  uint16_t written = h.AddBig (0xffff, h.m_tail, item, extraItem);
522  h.UpdateTail (written);
523 
524  *this = h;
525 }
526 
527 
528 uint32_t
529 PacketMetadata::ReadItems (uint16_t current,
530  struct PacketMetadata::SmallItem *item,
531  struct PacketMetadata::ExtraItem *extraItem) const
532 {
533  NS_LOG_FUNCTION (this << current << item->chunkUid << item->prev << item->next << item->size <<
534  item->typeUid << extraItem->fragmentEnd << extraItem->fragmentStart <<
535  extraItem->packetUid);
536  NS_ASSERT (current <= m_data->m_size);
537  const uint8_t *buffer = &m_data->m_data[current];
538  item->next = buffer[0];
539  item->next |= (buffer[1]) << 8;
540  item->prev = buffer[2];
541  item->prev |= (buffer[3]) << 8;
542  buffer += 4;
543  item->typeUid = ReadUleb128 (&buffer);
544  item->size = ReadUleb128 (&buffer);
545  item->chunkUid = buffer[0];
546  item->chunkUid |= (buffer[1]) << 8;
547  buffer += 2;
548 
549  bool isExtra = (item->typeUid & 0x1) == 0x1;
550  if (isExtra)
551  {
552  extraItem->fragmentStart = ReadUleb128 (&buffer);
553  extraItem->fragmentEnd = ReadUleb128 (&buffer);
554  extraItem->packetUid = buffer[0];
555  extraItem->packetUid |= buffer[1] << 8;
556  extraItem->packetUid |= buffer[2] << 16;
557  extraItem->packetUid |= buffer[3] << 24;
558  buffer += 4;
559  }
560  else
561  {
562  extraItem->fragmentStart = 0;
563  extraItem->fragmentEnd = item->size;
564  extraItem->packetUid = m_packetUid;
565  }
566  NS_ASSERT (buffer <= &m_data->m_data[m_data->m_size]);
567  return buffer - &m_data->m_data[current];
568 }
569 
570 struct PacketMetadata::Data *
571 PacketMetadata::Create (uint32_t size)
572 {
573  NS_LOG_FUNCTION (size);
574  NS_LOG_LOGIC ("create size="<<size<<", max="<<m_maxSize);
575  if (size > m_maxSize)
576  {
577  m_maxSize = size;
578  }
579  while (!m_freeList.empty ())
580  {
581  struct PacketMetadata::Data *data = m_freeList.back ();
582  m_freeList.pop_back ();
583  if (data->m_size >= size)
584  {
585  NS_LOG_LOGIC ("create found size="<<data->m_size);
586  data->m_count = 1;
587  return data;
588  }
590  NS_LOG_LOGIC ("create dealloc size="<<data->m_size);
591  }
592  NS_LOG_LOGIC ("create alloc size="<<m_maxSize);
594 }
595 
596 void
598 {
599  NS_LOG_FUNCTION (data);
600  if (!m_enable)
601  {
603  return;
604  }
605  NS_LOG_LOGIC ("recycle size="<<data->m_size<<", list="<<m_freeList.size ());
606  NS_ASSERT (data->m_count == 0);
607  if (m_freeList.size () > 1000 ||
608  data->m_size < m_maxSize)
609  {
611  }
612  else
613  {
614  m_freeList.push_back (data);
615  }
616 }
617 
618 struct PacketMetadata::Data *
620 {
621  NS_LOG_FUNCTION (n);
622  uint32_t size = sizeof (struct Data);
624  {
626  }
628  uint8_t *buf = new uint8_t [size];
629  struct PacketMetadata::Data *data = (struct PacketMetadata::Data *)buf;
630  data->m_size = n;
631  data->m_count = 1;
632  data->m_dirtyEnd = 0;
633  return data;
634 }
635 void
637 {
638  NS_LOG_FUNCTION (data);
639  uint8_t *buf = (uint8_t *)data;
640  delete [] buf;
641 }
642 
643 
645 PacketMetadata::CreateFragment (uint32_t start, uint32_t end) const
646 {
647  NS_LOG_FUNCTION (this << start << end);
648  PacketMetadata fragment = *this;
649  fragment.RemoveAtStart (start);
650  fragment.RemoveAtEnd (end);
651  return fragment;
652 }
653 
654 void
655 PacketMetadata::AddHeader (const Header &header, uint32_t size)
656 {
657  NS_LOG_FUNCTION (this << &header << size);
658  NS_ASSERT (IsStateOk ());
659  uint32_t uid = header.GetInstanceTypeId ().GetUid () << 1;
660  DoAddHeader (uid, size);
661  NS_ASSERT (IsStateOk ());
662 }
663 void
664 PacketMetadata::DoAddHeader (uint32_t uid, uint32_t size)
665 {
666  NS_LOG_FUNCTION (this << uid << size);
667  if (!m_enable)
668  {
669  m_metadataSkipped = true;
670  return;
671  }
672 
673  struct PacketMetadata::SmallItem item;
674  item.next = m_head;
675  item.prev = 0xffff;
676  item.typeUid = uid;
677  item.size = size;
678  item.chunkUid = m_chunkUid;
679  m_chunkUid++;
680  uint16_t written = AddSmall (&item);
681  UpdateHead (written);
682 }
683 void
684 PacketMetadata::RemoveHeader (const Header &header, uint32_t size)
685 {
686  uint32_t uid = header.GetInstanceTypeId ().GetUid () << 1;
687  NS_LOG_FUNCTION (this << &header << size);
688  NS_ASSERT (IsStateOk ());
689  if (!m_enable)
690  {
691  m_metadataSkipped = true;
692  return;
693  }
694  struct PacketMetadata::SmallItem item;
695  struct PacketMetadata::ExtraItem extraItem;
696  uint32_t read = ReadItems (m_head, &item, &extraItem);
697  if ((item.typeUid & 0xfffffffe) != uid ||
698  item.size != size)
699  {
700  if (m_enableChecking)
701  {
702  NS_FATAL_ERROR ("Removing unexpected header.");
703  }
704  return;
705  }
706  else if (item.typeUid != uid &&
707  (extraItem.fragmentStart != 0 ||
708  extraItem.fragmentEnd != size))
709  {
710  if (m_enableChecking)
711  {
712  NS_FATAL_ERROR ("Removing incomplete header.");
713  }
714  return;
715  }
716  if (m_head + read == m_used)
717  {
718  m_used = m_head;
719  }
720  if (m_head == m_tail)
721  {
722  m_head = 0xffff;
723  m_tail = 0xffff;
724  }
725  else
726  {
727  m_head = item.next;
728  }
729  NS_ASSERT (IsStateOk ());
730 }
731 void
732 PacketMetadata::AddTrailer (const Trailer &trailer, uint32_t size)
733 {
734  uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
735  NS_LOG_FUNCTION (this << &trailer << size);
736  NS_ASSERT (IsStateOk ());
737  if (!m_enable)
738  {
739  m_metadataSkipped = true;
740  return;
741  }
742  struct PacketMetadata::SmallItem item;
743  item.next = 0xffff;
744  item.prev = m_tail;
745  item.typeUid = uid;
746  item.size = size;
747  item.chunkUid = m_chunkUid;
748  m_chunkUid++;
749  uint16_t written = AddSmall (&item);
750  UpdateTail (written);
751  NS_ASSERT (IsStateOk ());
752 }
753 void
754 PacketMetadata::RemoveTrailer (const Trailer &trailer, uint32_t size)
755 {
756  uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
757  NS_LOG_FUNCTION (this << &trailer << size);
758  NS_ASSERT (IsStateOk ());
759  if (!m_enable)
760  {
761  m_metadataSkipped = true;
762  return;
763  }
764  struct PacketMetadata::SmallItem item;
765  struct PacketMetadata::ExtraItem extraItem;
766  uint32_t read = ReadItems (m_tail, &item, &extraItem);
767  if ((item.typeUid & 0xfffffffe) != uid ||
768  item.size != size)
769  {
770  if (m_enableChecking)
771  {
772  NS_FATAL_ERROR ("Removing unexpected trailer.");
773  }
774  return;
775  }
776  else if (item.typeUid != uid &&
777  (extraItem.fragmentStart != 0 ||
778  extraItem.fragmentEnd != size))
779  {
780  if (m_enableChecking)
781  {
782  NS_FATAL_ERROR ("Removing incomplete trailer.");
783  }
784  return;
785  }
786  if (m_tail + read == m_used)
787  {
788  m_used = m_tail;
789  }
790  if (m_head == m_tail)
791  {
792  m_head = 0xffff;
793  m_tail = 0xffff;
794  }
795  else
796  {
797  m_tail = item.prev;
798  }
799  NS_ASSERT (IsStateOk ());
800 }
801 void
803 {
804  NS_LOG_FUNCTION (this << &o);
805  NS_ASSERT (IsStateOk ());
806  if (!m_enable)
807  {
808  m_metadataSkipped = true;
809  return;
810  }
811  if (m_tail == 0xffff)
812  {
813  // We have no items so 'AddAtEnd' is
814  // equivalent to self-assignment.
815  *this = o;
816  NS_ASSERT (IsStateOk ());
817  return;
818  }
819  if (o.m_head == 0xffff)
820  {
821  NS_ASSERT (o.m_tail == 0xffff);
822  // we have nothing to append.
823  return;
824  }
825  NS_ASSERT (m_head != 0xffff && m_tail != 0xffff);
826 
827  // We read the current tail because we are going to append
828  // after this item.
829  struct PacketMetadata::SmallItem tailItem;
830  PacketMetadata::ExtraItem tailExtraItem;
831  uint32_t tailSize = ReadItems (m_tail, &tailItem, &tailExtraItem);
832 
833  uint16_t current;
834  struct PacketMetadata::SmallItem item;
835  PacketMetadata::ExtraItem extraItem;
836  o.ReadItems (o.m_head, &item, &extraItem);
837  if (extraItem.packetUid == tailExtraItem.packetUid &&
838  item.typeUid == tailItem.typeUid &&
839  item.chunkUid == tailItem.chunkUid &&
840  item.size == tailItem.size &&
841  extraItem.fragmentStart == tailExtraItem.fragmentEnd)
842  {
843  /* If the previous tail came from the same header as
844  * the next item we want to append to our array, then,
845  * we merge them and attempt to reuse the previous tail's
846  * location.
847  */
848  tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
849  ReplaceTail (&tailItem, &tailExtraItem, tailSize);
850  if (o.m_head == o.m_tail)
851  {
852  // there is only one item to append to self from other.
853  return;
854  }
855  current = item.next;
856  }
857  else
858  {
859  current = o.m_head;
860  }
861 
862  /* Now that we have merged our current tail with the head of the
863  * next packet, we just append all items from the next packet
864  * to the current packet.
865  */
866  while (current != 0xffff)
867  {
868  o.ReadItems (current, &item, &extraItem);
869  uint16_t written = AddBig (0xffff, m_tail, &item, &extraItem);
870  UpdateTail (written);
871  if (current == o.m_tail)
872  {
873  break;
874  }
875  current = item.next;
876  }
877  NS_ASSERT (IsStateOk ());
878 }
879 void
881 {
882  NS_LOG_FUNCTION (this << end);
883  if (!m_enable)
884  {
885  m_metadataSkipped = true;
886  return;
887  }
888 }
889 void
891 {
892  NS_LOG_FUNCTION (this << start);
893  NS_ASSERT (IsStateOk ());
894  if (!m_enable)
895  {
896  m_metadataSkipped = true;
897  return;
898  }
899  NS_ASSERT (m_data != 0);
900  uint32_t leftToRemove = start;
901  uint16_t current = m_head;
902  while (current != 0xffff && leftToRemove > 0)
903  {
904  struct PacketMetadata::SmallItem item;
905  PacketMetadata::ExtraItem extraItem;
906  ReadItems (current, &item, &extraItem);
907  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
908  if (itemRealSize <= leftToRemove)
909  {
910  // remove from list.
911  if (m_head == m_tail)
912  {
913  m_head = 0xffff;
914  m_tail = 0xffff;
915  }
916  else
917  {
918  m_head = item.next;
919  }
920  leftToRemove -= itemRealSize;
921  }
922  else
923  {
924  // fragment the list item.
925  PacketMetadata fragment (m_packetUid, 0);
926  extraItem.fragmentStart += leftToRemove;
927  leftToRemove = 0;
928  uint16_t written = fragment.AddBig (0xffff, fragment.m_tail,
929  &item, &extraItem);
930  fragment.UpdateTail (written);
931  while (current != 0xffff && current != m_tail)
932  {
933  current = item.next;
934  ReadItems (current, &item, &extraItem);
935  written = fragment.AddBig (0xffff, fragment.m_tail,
936  &item, &extraItem);
937  fragment.UpdateTail (written);
938  }
939  *this = fragment;
940  }
941  NS_ASSERT (item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
942  extraItem.fragmentStart <= extraItem.fragmentEnd);
943  if (current == m_tail)
944  {
945  break;
946  }
947  current = item.next;
948  }
949  NS_ASSERT (leftToRemove == 0);
950  NS_ASSERT (IsStateOk ());
951 }
952 void
954 {
955  NS_LOG_FUNCTION (this << end);
956  NS_ASSERT (IsStateOk ());
957  if (!m_enable)
958  {
959  m_metadataSkipped = true;
960  return;
961  }
962  NS_ASSERT (m_data != 0);
963 
964  uint32_t leftToRemove = end;
965  uint16_t current = m_tail;
966  while (current != 0xffff && leftToRemove > 0)
967  {
968  struct PacketMetadata::SmallItem item;
969  PacketMetadata::ExtraItem extraItem;
970  ReadItems (current, &item, &extraItem);
971  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
972  if (itemRealSize <= leftToRemove)
973  {
974  // remove from list.
975  if (m_head == m_tail)
976  {
977  m_head = 0xffff;
978  m_tail = 0xffff;
979  }
980  else
981  {
982  m_tail = item.prev;
983  }
984  leftToRemove -= itemRealSize;
985  }
986  else
987  {
988  // fragment the list item.
989  PacketMetadata fragment (m_packetUid, 0);
990  NS_ASSERT (extraItem.fragmentEnd > leftToRemove);
991  extraItem.fragmentEnd -= leftToRemove;
992  leftToRemove = 0;
993  uint16_t written = fragment.AddBig (fragment.m_head, 0xffff,
994  &item, &extraItem);
995  fragment.UpdateHead (written);
996  while (current != 0xffff && current != m_head)
997  {
998  current = item.prev;
999  ReadItems (current, &item, &extraItem);
1000  written = fragment.AddBig (fragment.m_head, 0xffff,
1001  &item, &extraItem);
1002  fragment.UpdateHead (written);
1003  }
1004  *this = fragment;
1005  }
1006  NS_ASSERT (item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
1007  extraItem.fragmentStart <= extraItem.fragmentEnd);
1008  if (current == m_head)
1009  {
1010  break;
1011  }
1012  current = item.prev;
1013  }
1014  NS_ASSERT (leftToRemove == 0);
1015  NS_ASSERT (IsStateOk ());
1016 }
1017 uint32_t
1019 {
1020  NS_LOG_FUNCTION (this);
1021  uint32_t totalSize = 0;
1022  uint16_t current = m_head;
1023  uint16_t tail = m_tail;
1024  while (current != 0xffff)
1025  {
1026  struct PacketMetadata::SmallItem item;
1027  PacketMetadata::ExtraItem extraItem;
1028  ReadItems (current, &item, &extraItem);
1029  totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1030  if (current == tail)
1031  {
1032  break;
1033  }
1034  NS_ASSERT (current != item.next);
1035  current = item.next;
1036  }
1037  return totalSize;
1038 }
1039 
1040 uint64_t
1042 {
1043  NS_LOG_FUNCTION (this);
1044  return m_packetUid;
1045 }
1048 {
1049  NS_LOG_FUNCTION (this << &buffer);
1050  return ItemIterator (this, buffer);
1051 }
1053  : m_metadata (metadata),
1054  m_buffer (buffer),
1055  m_current (metadata->m_head),
1056  m_offset (0),
1057  m_hasReadTail (false)
1058 {
1059  NS_LOG_FUNCTION (this << metadata << &buffer);
1060 }
1061 bool
1063 {
1064  NS_LOG_FUNCTION (this);
1065  if (m_current == 0xffff)
1066  {
1067  return false;
1068  }
1069  if (m_hasReadTail)
1070  {
1071  return false;
1072  }
1073  return true;
1074 }
1077 {
1078  NS_LOG_FUNCTION (this);
1079  struct PacketMetadata::Item item;
1080  struct PacketMetadata::SmallItem smallItem;
1081  struct PacketMetadata::ExtraItem extraItem;
1082  m_metadata->ReadItems (m_current, &smallItem, &extraItem);
1083  if (m_current == m_metadata->m_tail)
1084  {
1085  m_hasReadTail = true;
1086  }
1087  m_current = smallItem.next;
1088  uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1089  item.tid.SetUid (uid);
1090  item.currentTrimedFromStart = extraItem.fragmentStart;
1091  item.currentTrimedFromEnd = extraItem.fragmentEnd - smallItem.size;
1092  item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1093  if (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size)
1094  {
1095  item.isFragment = true;
1096  }
1097  else
1098  {
1099  item.isFragment = false;
1100  }
1101  TypeId tid;
1102  tid.SetUid (uid);
1103  if (uid == 0)
1104  {
1106  }
1107  else if (tid.IsChildOf (Header::GetTypeId ()))
1108  {
1110  if (!item.isFragment)
1111  {
1112  item.current = m_buffer.Begin ();
1113  item.current.Next (m_offset);
1114  }
1115  }
1116  else if (tid.IsChildOf (Trailer::GetTypeId ()))
1117  {
1119  if (!item.isFragment)
1120  {
1121  item.current = m_buffer.End ();
1122  item.current.Prev (m_buffer.GetSize () - (m_offset + smallItem.size));
1123  }
1124  }
1125  else
1126  {
1127  NS_ASSERT (false);
1128  }
1129  m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1130  return item;
1131 }
1132 
1133 uint32_t
1135 {
1136  NS_LOG_FUNCTION (this);
1137  uint32_t totalSize = 0;
1138 
1139  // add 8 bytes for the packet uid
1140  totalSize += 8;
1141 
1142  // if packet-metadata not enabled, total size
1143  // is simply 4-bytes for itself plus 8-bytes
1144  // for packet uid
1145  if (!m_enable)
1146  {
1147  return totalSize;
1148  }
1149 
1150  struct PacketMetadata::SmallItem item;
1151  struct PacketMetadata::ExtraItem extraItem;
1152  uint32_t current = m_head;
1153  while (current != 0xffff)
1154  {
1155  ReadItems (current, &item, &extraItem);
1156  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1157  if (uid == 0)
1158  {
1159  totalSize += 4;
1160  }
1161  else
1162  {
1163  TypeId tid;
1164  tid.SetUid (uid);
1165  totalSize += 4 + tid.GetName ().size ();
1166  }
1167  totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1168  if (current == m_tail)
1169  {
1170  break;
1171  }
1172  NS_ASSERT (current != item.next);
1173  current = item.next;
1174  }
1175  return totalSize;
1176 }
1177 
1178 uint32_t
1179 PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const
1180 {
1181  NS_LOG_FUNCTION (this << &buffer << maxSize);
1182  uint8_t* start = buffer;
1183 
1184  buffer = AddToRawU64 (m_packetUid, start, buffer, maxSize);
1185  if (buffer == 0)
1186  {
1187  return 0;
1188  }
1189 
1190  struct PacketMetadata::SmallItem item;
1191  struct PacketMetadata::ExtraItem extraItem;
1192  uint32_t current = m_head;
1193  while (current != 0xffff)
1194  {
1195  ReadItems (current, &item, &extraItem);
1196  NS_LOG_LOGIC ("bytesWritten=" << static_cast<uint32_t> (buffer - start) << ", typeUid="<<
1197  item.typeUid << ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
1198  ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
1199  extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
1200 
1201  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1202  if (uid != 0)
1203  {
1204  TypeId tid;
1205  tid.SetUid (uid);
1206  std::string uidString = tid.GetName ();
1207  uint32_t uidStringSize = uidString.size ();
1208  buffer = AddToRawU32 (uidStringSize, start, buffer, maxSize);
1209  if (buffer == 0)
1210  {
1211  return 0;
1212  }
1213  buffer = AddToRaw (reinterpret_cast<const uint8_t *> (uidString.c_str ()),
1214  uidStringSize, start, buffer, maxSize);
1215  if (buffer == 0)
1216  {
1217  return 0;
1218  }
1219  }
1220  else
1221  {
1222  buffer = AddToRawU32 (0, start, buffer, maxSize);
1223  if (buffer == 0)
1224  {
1225  return 0;
1226  }
1227  }
1228 
1229  uint8_t isBig = item.typeUid & 0x1;
1230  buffer = AddToRawU8 (isBig, start, buffer, maxSize);
1231  if (buffer == 0)
1232  {
1233  return 0;
1234  }
1235 
1236  buffer = AddToRawU32 (item.size, start, buffer, maxSize);
1237  if (buffer == 0)
1238  {
1239  return 0;
1240  }
1241 
1242  buffer = AddToRawU16 (item.chunkUid, start, buffer, maxSize);
1243  if (buffer == 0)
1244  {
1245  return 0;
1246  }
1247 
1248  buffer = AddToRawU32 (extraItem.fragmentStart, start, buffer, maxSize);
1249  if (buffer == 0)
1250  {
1251  return 0;
1252  }
1253 
1254  buffer = AddToRawU32 (extraItem.fragmentEnd, start, buffer, maxSize);
1255  if (buffer == 0)
1256  {
1257  return 0;
1258  }
1259 
1260  buffer = AddToRawU64 (extraItem.packetUid, start, buffer, maxSize);
1261  if (buffer == 0)
1262  {
1263  return 0;
1264  }
1265 
1266  if (current == m_tail)
1267  {
1268  break;
1269  }
1270 
1271  NS_ASSERT (current != item.next);
1272  current = item.next;
1273  }
1274 
1275  NS_ASSERT (static_cast<uint32_t> (buffer - start) == maxSize);
1276  return 1;
1277 }
1278 
1279 uint32_t
1280 PacketMetadata::Deserialize (const uint8_t* buffer, uint32_t size)
1281 {
1282  NS_LOG_FUNCTION (this << &buffer << size);
1283  const uint8_t* start = buffer;
1284  uint32_t desSize = size - 4;
1285 
1286  buffer = ReadFromRawU64 (m_packetUid, start, buffer, size);
1287  desSize -= 8;
1288 
1289  struct PacketMetadata::SmallItem item = {0};
1290  struct PacketMetadata::ExtraItem extraItem = {0};
1291  while (desSize > 0)
1292  {
1293  uint32_t uidStringSize = 0;
1294  buffer = ReadFromRawU32 (uidStringSize, start, buffer, size);
1295  desSize -= 4;
1296  uint32_t uid;
1297  if (uidStringSize == 0)
1298  {
1299  // uid zero for payload.
1300  uid = 0;
1301  }
1302  else
1303  {
1304  std::string uidString;
1305  for (uint32_t j = 0; j < uidStringSize; j++)
1306  {
1307  uint8_t ch = 0;
1308  buffer = ReadFromRawU8 (ch, start, buffer, size);
1309  uidString.push_back (ch);
1310  desSize--;
1311  }
1312  TypeId tid = TypeId::LookupByName (uidString);
1313  uid = tid.GetUid ();
1314  }
1315  uint8_t isBig = 0;
1316  buffer = ReadFromRawU8 (isBig, start, buffer, size);
1317  desSize--;
1318  item.typeUid = (uid << 1) | isBig;
1319  buffer = ReadFromRawU32 (item.size, start, buffer, size);
1320  desSize -= 4;
1321  buffer = ReadFromRawU16 (item.chunkUid, start, buffer, size);
1322  desSize -= 2;
1323  buffer = ReadFromRawU32 (extraItem.fragmentStart, start, buffer, size);
1324  desSize -= 4;
1325  buffer = ReadFromRawU32 (extraItem.fragmentEnd, start, buffer, size);
1326  desSize -= 4;
1327  buffer = ReadFromRawU64 (extraItem.packetUid, start, buffer, size);
1328  desSize -= 8;
1329  NS_LOG_LOGIC ("size=" << size << ", typeUid="<<item.typeUid <<
1330  ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
1331  ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
1332  extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
1333  uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
1334  UpdateTail (tmp);
1335  }
1336  NS_ASSERT (desSize == 0);
1337  return (desSize !=0) ? 0 : 1;
1338 }
1339 
1340 uint8_t*
1342  uint8_t* start,
1343  uint8_t* current,
1344  uint32_t maxSize)
1345 {
1346  NS_LOG_FUNCTION (static_cast<uint32_t> (data) << &start << &current << maxSize);
1347  // First check buffer overflow
1348  if (static_cast<uint32_t> ((current + sizeof (uint8_t) - start)) > maxSize)
1349  {
1350  return 0;
1351  }
1352  memcpy (current, &data, sizeof (uint8_t));
1353  return current + sizeof (uint8_t);
1354 }
1355 
1356 uint8_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 (uint16_t) - start)) > maxSize)
1365  {
1366  return 0;
1367  }
1368  memcpy (current, &data, sizeof (uint16_t));
1369  return current + sizeof (uint16_t);
1370 }
1371 
1372 uint8_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 (uint32_t) - start)) > maxSize)
1381  {
1382  return 0;
1383  }
1384  memcpy (current, &data, sizeof (uint32_t));
1385  return current + sizeof (uint32_t);
1386 }
1387 
1388 uint8_t*
1390  uint8_t* start,
1391  uint8_t* current,
1392  uint32_t maxSize)
1393 {
1394  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1395  // First check buffer overflow
1396  if (static_cast<uint32_t> ((current + sizeof (uint64_t) - start)) > maxSize)
1397  {
1398  return 0;
1399  }
1400  memcpy (current, &data, sizeof (uint64_t));
1401  return current + sizeof (uint64_t);
1402 }
1403 
1404 uint8_t*
1406  uint32_t dataSize,
1407  uint8_t* start,
1408  uint8_t* current,
1409  uint32_t maxSize)
1410 {
1411  NS_LOG_FUNCTION (&data << dataSize << &start << &current << maxSize);
1412  // First check buffer overflow
1413  if (static_cast<uint32_t> ((current + dataSize - start)) > maxSize)
1414  {
1415  return 0;
1416  }
1417  memcpy (current, data, dataSize);
1418  return current + dataSize;
1419 }
1420 
1421 uint8_t*
1423  const uint8_t* start,
1424  const uint8_t* current,
1425  uint32_t maxSize)
1426 {
1427  NS_LOG_FUNCTION (static_cast<uint32_t> (data) << &start << &current << maxSize);
1428  // First check buffer underflow
1429  if (static_cast<uint32_t> ((current + sizeof (uint8_t) - start)) > maxSize)
1430  {
1431  return 0;
1432  }
1433  memcpy (&data, current, sizeof (uint8_t));
1434  return const_cast<uint8_t *> (current) + sizeof (uint8_t);
1435 }
1436 
1437 uint8_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 (uint16_t) - start)) > maxSize)
1446  {
1447  return 0;
1448  }
1449  memcpy (&data, current, sizeof (uint16_t));
1450  return const_cast<uint8_t *> (current) + sizeof (uint16_t);
1451 }
1452 
1453 uint8_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 (static_cast<uint32_t> ((current + sizeof (uint32_t) - start)) > maxSize)
1462  {
1463  return 0;
1464  }
1465  memcpy (&data, current, sizeof (uint32_t));
1466  return const_cast<uint8_t *> (current) + sizeof (uint32_t);
1467 }
1468 
1469 uint8_t*
1471  const uint8_t* start,
1472  const uint8_t* current,
1473  uint32_t maxSize)
1474 {
1475  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1476  // First check buffer underflow
1477  if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
1478  {
1479  return 0;
1480  }
1481  memcpy (&data, current, sizeof (uint64_t));
1482  return const_cast<uint8_t *> (current) + sizeof (uint64_t);
1483 }
1484 
1485 
1486 } // namespace ns3
1487 
Protocol header serialization and deserialization.
Definition: header.h:42
void RemoveAtEnd(uint32_t end)
Remove a chunk of metadata at the metadata end.
static void Recycle(struct PacketMetadata::Data *data)
Recycle the buffer memory.
friend class ItemIterator
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
Buffer::Iterator current
an iterator which can be fed to Deserialize.
static uint8_t * ReadFromRawU8(uint8_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static bool m_enableChecking
Enable the packet metadata checking.
static bool m_enable
Enable the packet metadata.
uint64_t GetUid(void) const
Get the packet Uid.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
Item Next(void)
Retrieve the next metadata item.
automatically resized byte buffer
Definition: buffer.h:92
def start()
Definition: core.py:1482
structure describing a packet metadata item
bool isFragment
true: this is a fragmented header, trailer, or, payload.
static void Deallocate(struct PacketMetadata::Data *data)
Deallocate the buffer memory.
TypeId tid
TypeId of Header or Trailer.
static void EnableChecking(void)
Enable the packet metadata checking.
static uint8_t * ReadFromRawU16(uint16_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
struct Data * m_data
Metadata storage.
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:162
uint32_t GetSerializedSize(void) const
Get the metadata serialized size.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
uint16_t AddSmall(const PacketMetadata::SmallItem *item)
Add a SmallItem.
static TypeId GetTypeId(void)
Get the type ID.
Definition: trailer.cc:36
void UpdateHead(uint16_t written)
Update the head.
uint32_t currentTrimedFromEnd
how many bytes were trimed from the end of a fragment.
bool IsSharedPointerOk(uint16_t pointer) const
Check if the position is valid.
void AddHeader(Header const &header, uint32_t size)
Add an header.
void AppendValueExtra(uint32_t value, uint8_t *buffer)
Append a value to the buffer - extra.
void DoAddHeader(uint32_t uid, uint32_t size)
Add an header.
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.
bool IsPointerOk(uint16_t pointer) const
Check if the position is valid.
void AddTrailer(Trailer const &trailer, uint32_t size)
Add a trailer.
static TypeId GetTypeId(void)
Get the type ID.
Definition: header.cc:36
void AddPaddingAtEnd(uint32_t end)
Add some padding at the end.
#define max(a, b)
Definition: 80211b.c:45
PacketMetadata CreateFragment(uint32_t start, uint32_t end) const
Creates a fragment.
void Prev(void)
go backward by one byte
Definition: buffer.h:850
uint8_t data[writeSize]
static uint8_t * AddToRawU16(const uint16_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
Iterator class for metadata items.
uint16_t next
offset (in bytes) from start of m_data buffer to next element in linked list.
void Next(void)
go forward by one byte
Definition: buffer.h:844
static DataFreeList m_freeList
the metadata data storage
bool HasNext(void) const
Checks if there is another metadata item.
void AppendValue(uint32_t value, uint8_t *buffer)
Append a value to the buffer.
static struct PacketMetadata::Data * Allocate(uint32_t n)
Allocate a buffer data storage.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
void AddAtEnd(PacketMetadata const &o)
Add a metadata at the metadata start.
Protocol trailer serialization and deserialization.
Definition: trailer.h:40
uint64_t m_packetUid
packet Uid
uint32_t GetUleb128Size(uint32_t value) const
Get the ULEB128 (Unsigned Little Endian Base 128) size.
static void Enable(void)
Enable the packet metadata.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
enum ns3::PacketMetadata::Item::@79 type
metadata type
uint32_t size
the size (in bytes) of the header or trailer represented by this element.
uint16_t m_tail
list tail
static uint8_t * AddToRawU64(const uint64_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
void Append32(uint32_t value, uint8_t *buffer)
Append a 32-bit value to the buffer.
std::string GetName(void) const
Get the name.
Definition: type-id.cc:958
uint16_t m_size
size (in bytes) of m_data buffer below
void Append16(uint16_t value, uint8_t *buffer)
Append a 16-bit value to the buffer.
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Deserialization from raw uint8_t*.
static uint32_t m_maxSize
maximum metadata size
bool IsStateOk(void) const
Check if the metadata state is ok.
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1172
void RemoveHeader(Header const &header, uint32_t size)
Remove an header.
static uint8_t * AddToRawU32(const uint32_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
uint16_t prev
offset (in bytes) from start of m_data buffer to previous element in linked list. ...
static uint16_t m_chunkUid
Chunk Uid.
uint16_t m_used
used portion
uint32_t currentSize
size of item.
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1178
#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:90
uint32_t GetTotalSize(void) const
Get the total size used by the metadata.
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)
uint32_t m_count
number of references to this struct Data instance.
static struct PacketMetadata::Data * Create(uint32_t size)
Create a buffer data storage.
void RemoveTrailer(Trailer const &trailer, uint32_t size)
Remove a trailer.
virtual TypeId GetInstanceTypeId(void) const =0
Get the most derived TypeId for this Object.
ItemIterator BeginItem(Buffer buffer) const
Initialize the item iterator to the buffer begin.
static uint8_t * ReadFromRawU64(uint64_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
uint16_t m_dirtyEnd
max of the m_used field over all objects which reference this struct Data instance ...
static bool m_metadataSkipped
Set to true when adding metadata to a packet is skipped because m_enable is false; used to detect ena...
uint32_t fragmentEnd
offset (in bytes) from start of original header to the end of the fragment still present.
uint32_t typeUid
the high 31 bits of this field identify the type of the header or trailer represented by this item: t...
uint16_t chunkUid
this field tries to uniquely identify each header or trailer instance while the typeUid field uniquel...
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition: type-id.cc:939
void UpdateTail(uint16_t written)
Update the tail.
uint64_t packetUid
the packetUid of the packet in which this header or trailer was first added.
void RemoveAtStart(uint32_t start)
Remove a chunk of metadata at the metadata start.
uint32_t currentTrimedFromStart
how many bytes were trimed from the start of a fragment.
void Reserve(uint32_t n)
Reserve space.
void ReplaceTail(PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem, uint32_t available)
Replace the tail.
static uint8_t * AddToRawU8(const uint8_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
uint8_t m_data[PACKET_METADATA_DATA_M_DATA_SIZE]
variable-sized buffer of bytes
a unique identifier for an interface.
Definition: type-id.h:58
uint32_t ReadUleb128(const uint8_t **pBuffer) const
Read a ULEB128 (Unsigned Little Endian Base 128) coded number.
ItemIterator(const PacketMetadata *metadata, Buffer buffer)
Constructor.
uint32_t fragmentStart
offset (in bytes) from start of original header to the start of the fragment still present...
uint16_t m_head
list head
uint32_t ReadItems(uint16_t current, struct PacketMetadata::SmallItem *item, struct PacketMetadata::ExtraItem *extraItem) const
Read items.
#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...
static uint8_t * ReadFromRawU32(uint32_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialization to raw uint8_t*.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:813
Handle packet metadata about packet headers and trailers.