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