A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
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 NS_LOG_COMPONENT_DEFINE ("PacketMetadata");
31 
32 namespace ns3 {
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  }
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
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:501
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:456
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
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:61
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:170
struct Data * m_data
Metadata storage.
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:95
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.
enum ns3::PacketMetadata::Item::@81 type
metadata type
static TypeId GetTypeId(void)
Get the type ID.
Definition: trailer.cc:16
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:16
void AddPaddingAtEnd(uint32_t end)
Add some padding at the end.
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:1082
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:233
Buffer::Iterator Begin(void) const
Definition: buffer.h:1076
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.
void SetUid(uint16_t tid)
Definition: type-id.cc:818
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
Definition: type-id.cc:657
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
Definition: type-id.cc:812
uint32_t GetSize(void) const
Definition: buffer.h:1070
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:84
uint32_t GetTotalSize(void) const
Get the total size used by the metadata.
Time current
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
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
Definition: type-id.cc:638
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:49
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)
Definition: type-id.cc:535
Handle packet metadata about packet headers and trailers.