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 
#define max(a, b)
Definition: 80211b.c:43
void Next(void)
go forward by one byte
Definition: buffer.h:845
void Prev(void)
go backward by one byte
Definition: buffer.h:851
automatically resized byte buffer
Definition: buffer.h:93
Protocol header serialization and deserialization.
Definition: header.h:43
static TypeId GetTypeId(void)
Get the type ID.
Definition: header.cc:36
virtual TypeId GetInstanceTypeId(void) const =0
Get the most derived TypeId for this Object.
Iterator class for metadata items.
bool HasNext(void) const
Checks if there is another metadata item.
Item Next(void)
Retrieve the next metadata item.
ItemIterator(const PacketMetadata *metadata, Buffer buffer)
Constructor.
Handle packet metadata about packet headers and trailers.
static uint8_t * ReadFromRawU64(uint64_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
void ReplaceTail(PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem, uint32_t available)
Replace the tail.
PacketMetadata CreateFragment(uint32_t start, uint32_t end) const
Creates a fragment.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
void AppendValueExtra(uint32_t value, uint8_t *buffer)
Append a value to the buffer - extra.
void Append32(uint32_t value, uint8_t *buffer)
Append a 32-bit value to the buffer.
void RemoveTrailer(Trailer const &trailer, uint32_t size)
Remove a trailer.
friend class ItemIterator
Friend class.
static uint32_t m_maxSize
maximum metadata size
static bool m_enableChecking
Enable the packet metadata checking.
void UpdateHead(uint16_t written)
Update the head.
uint16_t m_head
list head
void AppendValue(uint32_t value, uint8_t *buffer)
Append a value to the buffer.
static void Deallocate(struct PacketMetadata::Data *data)
Deallocate the buffer memory.
bool IsStateOk(void) const
Check if the metadata state is ok.
static uint8_t * ReadFromRawU32(uint32_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static uint8_t * AddToRawU32(const uint32_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static void EnableChecking(void)
Enable the packet metadata checking.
static struct PacketMetadata::Data * Allocate(uint32_t n)
Allocate a buffer data storage.
static bool m_enable
Enable the packet metadata.
struct Data * m_data
Metadata storage.
void Reserve(uint32_t n)
Reserve space.
uint32_t ReadUleb128(const uint8_t **pBuffer) const
Read a ULEB128 (Unsigned Little Endian Base 128) coded number.
ItemIterator BeginItem(Buffer buffer) const
Initialize the item iterator to the buffer begin.
void RemoveAtEnd(uint32_t end)
Remove a chunk of metadata at the metadata end.
uint32_t ReadItems(uint16_t current, struct PacketMetadata::SmallItem *item, struct PacketMetadata::ExtraItem *extraItem) const
Read items.
uint32_t Deserialize(const uint8_t *buffer, uint32_t size)
Deserialization from raw uint8_t*.
void AddPaddingAtEnd(uint32_t end)
Add some padding at the end.
static uint8_t * ReadFromRawU16(uint16_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static struct PacketMetadata::Data * Create(uint32_t size)
Create a buffer data storage.
static uint16_t m_chunkUid
Chunk Uid.
void RemoveAtStart(uint32_t start)
Remove a chunk of metadata at the metadata start.
uint16_t AddSmall(const PacketMetadata::SmallItem *item)
Add a SmallItem.
static DataFreeList m_freeList
the metadata data storage
uint32_t GetUleb128Size(uint32_t value) const
Get the ULEB128 (Unsigned Little Endian Base 128) size.
void Append16(uint16_t value, uint8_t *buffer)
Append a 16-bit value to the buffer.
void AddHeader(Header const &header, uint32_t size)
Add an header.
static bool m_metadataSkipped
Set to true when adding metadata to a packet is skipped because m_enable is false; used to detect ena...
bool IsPointerOk(uint16_t pointer) const
Check if the position is valid.
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialization to raw uint8_t*.
bool IsSharedPointerOk(uint16_t pointer) const
Check if the position is valid.
uint32_t GetTotalSize(void) const
Get the total size used by the metadata.
static uint8_t * AddToRawU8(const uint8_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
uint16_t m_tail
list tail
void UpdateTail(uint16_t written)
Update the tail.
uint64_t m_packetUid
packet Uid
static uint8_t * AddToRaw(const uint8_t *data, uint32_t dataSize, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static void Enable(void)
Enable the packet metadata.
static void Recycle(struct PacketMetadata::Data *data)
Recycle the buffer memory.
void DoAddHeader(uint32_t uid, uint32_t size)
Add an header.
uint16_t AddBig(uint32_t head, uint32_t tail, const PacketMetadata::SmallItem *item, const PacketMetadata::ExtraItem *extraItem)
Add a "Big" Item (a SmallItem plus an ExtraItem)
static uint8_t * ReadFromRawU8(uint8_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
static uint8_t * AddToRawU16(const uint16_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
void AddAtEnd(PacketMetadata const &o)
Add a metadata at the metadata start.
static uint8_t * AddToRawU64(const uint64_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
uint32_t GetSerializedSize(void) const
Get the metadata serialized size.
void RemoveHeader(Header const &header, uint32_t size)
Remove an header.
void AddTrailer(Trailer const &trailer, uint32_t size)
Add a trailer.
uint16_t m_used
used portion
uint64_t GetUid(void) const
Get the packet Uid.
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
static TypeId GetTypeId(void)
Get the type ID.
Definition: trailer.cc:36
a unique identifier for an interface.
Definition: type-id.h:59
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition: type-id.cc:957
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:829
uint16_t GetUid(void) const
Get the internal id of this TypeId.
Definition: type-id.cc:1184
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1190
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1853
#define PACKET_METADATA_DATA_M_DATA_SIZE
the size of PacketMetadata::Data::m_data such that the total size of PacketMetadata::Data is 16 bytes
unsigned char byte
Definition: qkd-encryptor.h:64
uint8_t data[writeSize]
uint16_t m_size
size (in bytes) of m_data buffer below
uint8_t m_data[PACKET_METADATA_DATA_M_DATA_SIZE]
variable-sized buffer of bytes
uint32_t m_count
number of references to this struct Data instance.
uint16_t m_dirtyEnd
max of the m_used field over all objects which reference this struct Data instance
uint32_t fragmentEnd
offset (in bytes) from start of original header to the end of the fragment still present.
uint64_t packetUid
the packetUid of the packet in which this header or trailer was first added.
uint32_t fragmentStart
offset (in bytes) from start of original header to the start of the fragment still present.
structure describing a packet metadata item
TypeId tid
TypeId of Header or Trailer.
enum ns3::PacketMetadata::Item::ItemType type
metadata type
bool isFragment
true: this is a fragmented header, trailer, or, payload.
uint32_t currentTrimedFromEnd
how many bytes were trimmed from the end of a fragment.
uint32_t currentTrimedFromStart
how many bytes were trimmed from the start of a fragment.
Buffer::Iterator current
an iterator which can be fed to Deserialize.
uint32_t currentSize
size of item.
uint16_t next
offset (in bytes) from start of m_data buffer to next element in linked list.
uint16_t chunkUid
this field tries to uniquely identify each header or trailer instance while the typeUid field uniquel...
uint32_t typeUid
the high 31 bits of this field identify the type of the header or trailer represented by this item: t...
uint32_t size
the size (in bytes) of the header or trailer represented by this element.
uint16_t prev
offset (in bytes) from start of m_data buffer to previous element in linked list.