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  ns3::Buffer tmp = m_buffer;
1113  tmp.RemoveAtStart (m_offset);
1114  tmp.RemoveAtEnd (tmp.GetSize () - item.currentSize);
1115  item.current = tmp.Begin ();
1116  }
1117  }
1118  else if (tid.IsChildOf (Trailer::GetTypeId ()))
1119  {
1121  if (!item.isFragment)
1122  {
1123  ns3::Buffer tmp = m_buffer;
1124  tmp.RemoveAtEnd (tmp.GetSize () - (m_offset + smallItem.size));
1125  tmp.RemoveAtStart (tmp.GetSize () - item.currentSize);
1126  item.current = tmp.End ();
1127  }
1128  }
1129  else
1130  {
1131  NS_ASSERT (false);
1132  }
1133  m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1134  return item;
1135 }
1136 
1137 uint32_t
1139 {
1140  NS_LOG_FUNCTION (this);
1141  uint32_t totalSize = 0;
1142 
1143  // add 8 bytes for the packet uid
1144  totalSize += 8;
1145 
1146  // if packet-metadata not enabled, total size
1147  // is simply 4-bytes for itself plus 8-bytes
1148  // for packet uid
1149  if (!m_enable)
1150  {
1151  return totalSize;
1152  }
1153 
1154  struct PacketMetadata::SmallItem item;
1155  struct PacketMetadata::ExtraItem extraItem;
1156  uint32_t current = m_head;
1157  while (current != 0xffff)
1158  {
1159  ReadItems (current, &item, &extraItem);
1160  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1161  if (uid == 0)
1162  {
1163  totalSize += 4;
1164  }
1165  else
1166  {
1167  TypeId tid;
1168  tid.SetUid (uid);
1169  totalSize += 4 + tid.GetName ().size ();
1170  }
1171  totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1172  if (current == m_tail)
1173  {
1174  break;
1175  }
1176  NS_ASSERT (current != item.next);
1177  current = item.next;
1178  }
1179  return totalSize;
1180 }
1181 
1182 uint32_t
1183 PacketMetadata::Serialize (uint8_t* buffer, uint32_t maxSize) const
1184 {
1185  NS_LOG_FUNCTION (this << &buffer << maxSize);
1186  uint8_t* start = buffer;
1187 
1188  buffer = AddToRawU64 (m_packetUid, start, buffer, maxSize);
1189  if (buffer == 0)
1190  {
1191  return 0;
1192  }
1193 
1194  struct PacketMetadata::SmallItem item;
1195  struct PacketMetadata::ExtraItem extraItem;
1196  uint32_t current = m_head;
1197  while (current != 0xffff)
1198  {
1199  ReadItems (current, &item, &extraItem);
1200  NS_LOG_LOGIC ("bytesWritten=" << static_cast<uint32_t> (buffer - start) << ", typeUid="<<
1201  item.typeUid << ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
1202  ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
1203  extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
1204 
1205  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1206  if (uid != 0)
1207  {
1208  TypeId tid;
1209  tid.SetUid (uid);
1210  std::string uidString = tid.GetName ();
1211  uint32_t uidStringSize = uidString.size ();
1212  buffer = AddToRawU32 (uidStringSize, start, buffer, maxSize);
1213  if (buffer == 0)
1214  {
1215  return 0;
1216  }
1217  buffer = AddToRaw (reinterpret_cast<const uint8_t *> (uidString.c_str ()),
1218  uidStringSize, start, buffer, maxSize);
1219  if (buffer == 0)
1220  {
1221  return 0;
1222  }
1223  }
1224  else
1225  {
1226  buffer = AddToRawU32 (0, start, buffer, maxSize);
1227  if (buffer == 0)
1228  {
1229  return 0;
1230  }
1231  }
1232 
1233  uint8_t isBig = item.typeUid & 0x1;
1234  buffer = AddToRawU8 (isBig, start, buffer, maxSize);
1235  if (buffer == 0)
1236  {
1237  return 0;
1238  }
1239 
1240  buffer = AddToRawU32 (item.size, start, buffer, maxSize);
1241  if (buffer == 0)
1242  {
1243  return 0;
1244  }
1245 
1246  buffer = AddToRawU16 (item.chunkUid, start, buffer, maxSize);
1247  if (buffer == 0)
1248  {
1249  return 0;
1250  }
1251 
1252  buffer = AddToRawU32 (extraItem.fragmentStart, start, buffer, maxSize);
1253  if (buffer == 0)
1254  {
1255  return 0;
1256  }
1257 
1258  buffer = AddToRawU32 (extraItem.fragmentEnd, start, buffer, maxSize);
1259  if (buffer == 0)
1260  {
1261  return 0;
1262  }
1263 
1264  buffer = AddToRawU64 (extraItem.packetUid, start, buffer, maxSize);
1265  if (buffer == 0)
1266  {
1267  return 0;
1268  }
1269 
1270  if (current == m_tail)
1271  {
1272  break;
1273  }
1274 
1275  NS_ASSERT (current != item.next);
1276  current = item.next;
1277  }
1278 
1279  NS_ASSERT (static_cast<uint32_t> (buffer - start) == maxSize);
1280  return 1;
1281 }
1282 
1283 uint32_t
1284 PacketMetadata::Deserialize (const uint8_t* buffer, uint32_t size)
1285 {
1286  NS_LOG_FUNCTION (this << &buffer << size);
1287  const uint8_t* start = buffer;
1288  uint32_t desSize = size - 4;
1289 
1290  buffer = ReadFromRawU64 (m_packetUid, start, buffer, size);
1291  desSize -= 8;
1292 
1293  struct PacketMetadata::SmallItem item = {0};
1294  struct PacketMetadata::ExtraItem extraItem = {0};
1295  while (desSize > 0)
1296  {
1297  uint32_t uidStringSize = 0;
1298  buffer = ReadFromRawU32 (uidStringSize, start, buffer, size);
1299  desSize -= 4;
1300  uint32_t uid;
1301  if (uidStringSize == 0)
1302  {
1303  // uid zero for payload.
1304  uid = 0;
1305  }
1306  else
1307  {
1308  std::string uidString;
1309  for (uint32_t j = 0; j < uidStringSize; j++)
1310  {
1311  uint8_t ch = 0;
1312  buffer = ReadFromRawU8 (ch, start, buffer, size);
1313  uidString.push_back (ch);
1314  desSize--;
1315  }
1316  TypeId tid = TypeId::LookupByName (uidString);
1317  uid = tid.GetUid ();
1318  }
1319  uint8_t isBig = 0;
1320  buffer = ReadFromRawU8 (isBig, start, buffer, size);
1321  desSize--;
1322  item.typeUid = (uid << 1) | isBig;
1323  buffer = ReadFromRawU32 (item.size, start, buffer, size);
1324  desSize -= 4;
1325  buffer = ReadFromRawU16 (item.chunkUid, start, buffer, size);
1326  desSize -= 2;
1327  buffer = ReadFromRawU32 (extraItem.fragmentStart, start, buffer, size);
1328  desSize -= 4;
1329  buffer = ReadFromRawU32 (extraItem.fragmentEnd, start, buffer, size);
1330  desSize -= 4;
1331  buffer = ReadFromRawU64 (extraItem.packetUid, start, buffer, size);
1332  desSize -= 8;
1333  NS_LOG_LOGIC ("size=" << size << ", typeUid="<<item.typeUid <<
1334  ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
1335  ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
1336  extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
1337  uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
1338  UpdateTail (tmp);
1339  }
1340  NS_ASSERT (desSize == 0);
1341  return (desSize !=0) ? 0 : 1;
1342 }
1343 
1344 uint8_t*
1346  uint8_t* start,
1347  uint8_t* current,
1348  uint32_t maxSize)
1349 {
1350  NS_LOG_FUNCTION (static_cast<uint32_t> (data) << &start << &current << maxSize);
1351  // First check buffer overflow
1352  if (static_cast<uint32_t> ((current + sizeof (uint8_t) - start)) > maxSize)
1353  {
1354  return 0;
1355  }
1356  memcpy (current, &data, sizeof (uint8_t));
1357  return current + sizeof (uint8_t);
1358 }
1359 
1360 uint8_t*
1362  uint8_t* start,
1363  uint8_t* current,
1364  uint32_t maxSize)
1365 {
1366  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1367  // First check buffer overflow
1368  if (static_cast<uint32_t> ((current + sizeof (uint16_t) - start)) > maxSize)
1369  {
1370  return 0;
1371  }
1372  memcpy (current, &data, sizeof (uint16_t));
1373  return current + sizeof (uint16_t);
1374 }
1375 
1376 uint8_t*
1378  uint8_t* start,
1379  uint8_t* current,
1380  uint32_t maxSize)
1381 {
1382  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1383  // First check buffer overflow
1384  if (static_cast<uint32_t> ((current + sizeof (uint32_t) - start)) > maxSize)
1385  {
1386  return 0;
1387  }
1388  memcpy (current, &data, sizeof (uint32_t));
1389  return current + sizeof (uint32_t);
1390 }
1391 
1392 uint8_t*
1394  uint8_t* start,
1395  uint8_t* current,
1396  uint32_t maxSize)
1397 {
1398  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1399  // First check buffer overflow
1400  if (static_cast<uint32_t> ((current + sizeof (uint64_t) - start)) > maxSize)
1401  {
1402  return 0;
1403  }
1404  memcpy (current, &data, sizeof (uint64_t));
1405  return current + sizeof (uint64_t);
1406 }
1407 
1408 uint8_t*
1410  uint32_t dataSize,
1411  uint8_t* start,
1412  uint8_t* current,
1413  uint32_t maxSize)
1414 {
1415  NS_LOG_FUNCTION (&data << dataSize << &start << &current << maxSize);
1416  // First check buffer overflow
1417  if (static_cast<uint32_t> ((current + dataSize - start)) > maxSize)
1418  {
1419  return 0;
1420  }
1421  memcpy (current, data, dataSize);
1422  return current + dataSize;
1423 }
1424 
1425 uint8_t*
1427  const uint8_t* start,
1428  const uint8_t* current,
1429  uint32_t maxSize)
1430 {
1431  NS_LOG_FUNCTION (static_cast<uint32_t> (data) << &start << &current << maxSize);
1432  // First check buffer underflow
1433  if (static_cast<uint32_t> ((current + sizeof (uint8_t) - start)) > maxSize)
1434  {
1435  return 0;
1436  }
1437  memcpy (&data, current, sizeof (uint8_t));
1438  return const_cast<uint8_t *> (current) + sizeof (uint8_t);
1439 }
1440 
1441 uint8_t*
1443  const uint8_t* start,
1444  const uint8_t* current,
1445  uint32_t maxSize)
1446 {
1447  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1448  // First check buffer underflow
1449  if (static_cast<uint32_t> ((current + sizeof (uint16_t) - start)) > maxSize)
1450  {
1451  return 0;
1452  }
1453  memcpy (&data, current, sizeof (uint16_t));
1454  return const_cast<uint8_t *> (current) + sizeof (uint16_t);
1455 }
1456 
1457 uint8_t*
1459  const uint8_t* start,
1460  const uint8_t* current,
1461  uint32_t maxSize)
1462 {
1463  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1464  // First check buffer underflow
1465  if (static_cast<uint32_t> ((current + sizeof (uint32_t) - start)) > maxSize)
1466  {
1467  return 0;
1468  }
1469  memcpy (&data, current, sizeof (uint32_t));
1470  return const_cast<uint8_t *> (current) + sizeof (uint32_t);
1471 }
1472 
1473 uint8_t*
1475  const uint8_t* start,
1476  const uint8_t* current,
1477  uint32_t maxSize)
1478 {
1479  NS_LOG_FUNCTION (data << &start << &current << maxSize);
1480  // First check buffer underflow
1481  if ((uint32_t)((current + sizeof (uint64_t) - start)) > maxSize)
1482  {
1483  return 0;
1484  }
1485  memcpy (&data, current, sizeof (uint64_t));
1486  return const_cast<uint8_t *> (current) + sizeof (uint64_t);
1487 }
1488 
1489 
1490 } // namespace ns3
1491 
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 "...
void RemoveAtEnd(uint32_t end)
Definition: buffer.cc:486
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.
void RemoveAtStart(uint32_t start)
Definition: buffer.cc:441
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:145
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.
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.
Buffer::Iterator End(void) const
Definition: buffer.h:1069
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
Buffer::Iterator Begin(void) const
Definition: buffer.h:1063
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.
void SetUid(uint16_t tid)
Set the internal id of this TypeId.
Definition: type-id.cc:1057
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:880
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:1051
uint32_t GetSize(void) const
Definition: buffer.h:1057
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.
#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:861
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:751
Handle packet metadata about packet headers and trailers.