A Discrete-Event Network Simulator
API
packet-metadata.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006,2007 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18  */
19 #include "packet-metadata.h"
20 
21 #include "buffer.h"
22 #include "header.h"
23 #include "trailer.h"
24 
25 #include "ns3/assert.h"
26 #include "ns3/fatal-error.h"
27 #include "ns3/log.h"
28 
29 #include <list>
30 #include <utility>
31 
32 namespace ns3
33 {
34 
35 NS_LOG_COMPONENT_DEFINE("PacketMetadata");
36 
37 bool PacketMetadata::m_enable = false;
40 uint32_t PacketMetadata::m_maxSize = 0;
41 uint16_t PacketMetadata::m_chunkUid = 0;
42 PacketMetadata::DataFreeList PacketMetadata::m_freeList;
43 
45 {
46  NS_LOG_FUNCTION(this);
47  for (auto i = begin(); i != end(); i++)
48  {
50  }
52 }
53 
54 void
56 {
59  "Error: attempting to enable the packet metadata "
60  "subsystem too late in the simulation, which is not allowed.\n"
61  "A common cause for this problem is to enable ASCII tracing "
62  "after sending any packets. One way to fix this problem is "
63  "to call ns3::PacketMetadata::Enable () near the beginning of"
64  " the program, before any packets are sent.");
65  m_enable = true;
66 }
67 
68 void
70 {
72  Enable();
73  m_enableChecking = true;
74 }
75 
76 void
78 {
79  NS_LOG_FUNCTION(this << size);
81  memcpy(newData->m_data, m_data->m_data, m_used);
82  newData->m_dirtyEnd = m_used;
83  m_data->m_count--;
84  if (m_data->m_count == 0)
85  {
87  }
88  m_data = newData;
89  if (m_head != 0xffff)
90  {
91  uint8_t* start;
92  NS_ASSERT(m_tail != 0xffff);
93  // clear the next field of the tail
95  Append16(0xffff, start);
96  // clear the prev field of the head
97  start = &m_data->m_data[m_head] + 2;
98  Append16(0xffff, start);
99  }
100 }
101 
102 void
104 {
105  NS_LOG_FUNCTION(this << size);
106  NS_ASSERT(m_data != nullptr);
107  if (m_data->m_size >= m_used + size &&
108  (m_head == 0xffff || m_data->m_count == 1 || m_data->m_dirtyEnd == m_used))
109  {
110  /* enough room, not dirty. */
111  }
112  else
113  {
114  /* (enough room and dirty) or (not enough room) */
115  ReserveCopy(size);
116  }
117 }
118 
119 bool
120 PacketMetadata::IsSharedPointerOk(uint16_t pointer) const
121 {
122  NS_LOG_FUNCTION(this << pointer);
123  bool ok = pointer == 0xffff || pointer <= m_data->m_size;
124  return ok;
125 }
126 
127 bool
128 PacketMetadata::IsPointerOk(uint16_t pointer) const
129 {
130  NS_LOG_FUNCTION(this << pointer);
131  bool ok = pointer == 0xffff || pointer <= m_used;
132  return ok;
133 }
134 
135 bool
137 {
138  NS_LOG_FUNCTION(this);
139  bool ok = m_used <= m_data->m_size;
140  ok &= IsPointerOk(m_head);
141  ok &= IsPointerOk(m_tail);
142  uint16_t current = m_head;
143  while (ok && current != 0xffff)
144  {
146  PacketMetadata::ExtraItem extraItem;
147  ReadItems(current, &item, &extraItem);
148  ok &= IsSharedPointerOk(item.next);
149  ok &= IsSharedPointerOk(item.prev);
150  if (current != m_head)
151  {
152  ok &= IsPointerOk(item.prev);
153  }
154  if (current != m_tail)
155  {
156  ok &= IsPointerOk(item.next);
157  }
158  if (current == m_tail)
159  {
160  break;
161  }
162  current = item.next;
163  }
164  return ok;
165 }
166 
167 uint32_t
168 PacketMetadata::GetUleb128Size(uint32_t value) const
169 {
170  NS_LOG_FUNCTION(this << value);
171  if (value < 0x80)
172  {
173  return 1;
174  }
175  if (value < 0x4000)
176  {
177  return 2;
178  }
179  if (value < 0x200000)
180  {
181  return 3;
182  }
183  if (value < 0x10000000)
184  {
185  return 4;
186  }
187  return 5;
188 }
189 
190 uint32_t
191 PacketMetadata::ReadUleb128(const uint8_t** pBuffer) const
192 {
193  NS_LOG_FUNCTION(this << &pBuffer);
194  const uint8_t* buffer = *pBuffer;
195  uint32_t result;
196  uint8_t byte;
197 
198  byte = buffer[0];
199  result = (byte & (~0x80));
200  if (!(byte & 0x80))
201  {
202  *pBuffer = buffer + 1;
203  return result;
204  }
205  byte = buffer[1];
206  result |= (byte & (~0x80)) << 7;
207  if (!(byte & 0x80))
208  {
209  *pBuffer = buffer + 2;
210  return result;
211  }
212  byte = buffer[2];
213  result |= (byte & (~0x80)) << 14;
214  if (!(byte & 0x80))
215  {
216  *pBuffer = buffer + 3;
217  return result;
218  }
219  byte = buffer[3];
220  result |= (byte & (~0x80)) << 21;
221  if (!(byte & 0x80))
222  {
223  *pBuffer = buffer + 4;
224  return result;
225  }
226  byte = buffer[4];
227  result |= (byte & (~0x80)) << 28;
228  if (!(byte & 0x80))
229  {
230  *pBuffer = buffer + 5;
231  return result;
232  }
233  /* This means that the LEB128 number was not valid.
234  * ie: the last (5th) byte did not have the high-order bit zeroed.
235  */
236  NS_ASSERT(false);
237  return 0;
238 }
239 
240 void
241 PacketMetadata::Append16(uint16_t value, uint8_t* buffer)
242 {
243  NS_LOG_FUNCTION(this << value << &buffer);
244  buffer[0] = value & 0xff;
245  value >>= 8;
246  buffer[1] = value;
247 }
248 
249 void
250 PacketMetadata::Append32(uint32_t value, uint8_t* buffer)
251 {
252  NS_LOG_FUNCTION(this << value << &buffer);
253  buffer[0] = value & 0xff;
254  buffer[1] = (value >> 8) & 0xff;
255  buffer[2] = (value >> 16) & 0xff;
256  buffer[3] = (value >> 24) & 0xff;
257 }
258 
259 void
260 PacketMetadata::AppendValueExtra(uint32_t value, uint8_t* buffer)
261 {
262  NS_LOG_FUNCTION(this << value << &buffer);
263  if (value < 0x200000)
264  {
265  uint8_t byte = value & (~0x80);
266  buffer[0] = 0x80 | byte;
267  value >>= 7;
268  byte = value & (~0x80);
269  buffer[1] = 0x80 | byte;
270  value >>= 7;
271  buffer[2] = value;
272  return;
273  }
274  if (value < 0x10000000)
275  {
276  uint8_t byte = value & (~0x80);
277  buffer[0] = 0x80 | byte;
278  value >>= 7;
279  byte = value & (~0x80);
280  buffer[1] = 0x80 | byte;
281  value >>= 7;
282  byte = value & (~0x80);
283  buffer[2] = 0x80 | byte;
284  value >>= 7;
285  buffer[3] = value;
286  return;
287  }
288  {
289  uint8_t byte = value & (~0x80);
290  buffer[0] = 0x80 | byte;
291  value >>= 7;
292  byte = value & (~0x80);
293  buffer[1] = 0x80 | byte;
294  value >>= 7;
295  byte = value & (~0x80);
296  buffer[2] = 0x80 | byte;
297  value >>= 7;
298  byte = value & (~0x80);
299  buffer[3] = 0x80 | byte;
300  value >>= 7;
301  buffer[4] = value;
302  }
303 }
304 
305 void
306 PacketMetadata::AppendValue(uint32_t value, uint8_t* buffer)
307 {
308  NS_LOG_FUNCTION(this << value << &buffer);
309  if (value < 0x80)
310  {
311  buffer[0] = value;
312  return;
313  }
314  if (value < 0x4000)
315  {
316  uint8_t byte = value & (~0x80);
317  buffer[0] = 0x80 | byte;
318  value >>= 7;
319  buffer[1] = value;
320  return;
321  }
322  AppendValueExtra(value, buffer);
323 }
324 
325 void
326 PacketMetadata::UpdateTail(uint16_t written)
327 {
328  NS_LOG_FUNCTION(this << written);
329  if (m_head == 0xffff)
330  {
331  NS_ASSERT(m_tail == 0xffff);
332  m_head = m_used;
333  m_tail = m_used;
334  }
335  else
336  {
337  NS_ASSERT(m_tail != 0xffff);
338  // overwrite the next field of the previous tail of the list.
339  uint8_t* previousTail = &m_data->m_data[m_tail];
340  Append16(m_used, previousTail);
341  // update the tail of the list to the new node.
342  m_tail = m_used;
343  }
344  NS_ASSERT(m_tail != 0xffff);
345  NS_ASSERT(m_head != 0xffff);
346  NS_ASSERT(written >= 8);
347  m_used += written;
349 }
350 
351 void
352 PacketMetadata::UpdateHead(uint16_t written)
353 {
354  NS_LOG_FUNCTION(this << written);
355  if (m_head == 0xffff)
356  {
357  NS_ASSERT(m_tail == 0xffff);
358  m_head = m_used;
359  m_tail = m_used;
360  }
361  else
362  {
363  NS_ASSERT(m_head != 0xffff);
364  // overwrite the prev field of the previous head of the list.
365  uint8_t* previousHead = &m_data->m_data[m_head + 2];
366  Append16(m_used, previousHead);
367  // update the head of list to the new node.
368  m_head = m_used;
369  }
370  NS_ASSERT(m_tail != 0xffff);
371  NS_ASSERT(m_head != 0xffff);
372  NS_ASSERT(written >= 8);
373  m_used += written;
375 }
376 
377 uint16_t
379 {
380  NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
381  << item->chunkUid);
382  NS_ASSERT(m_data != nullptr);
383  NS_ASSERT(m_used != item->prev && m_used != item->next);
384  uint32_t typeUidSize = GetUleb128Size(item->typeUid);
385  uint32_t sizeSize = GetUleb128Size(item->size);
386  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
387  if (m_used + n > m_data->m_size ||
388  (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
389  {
390  ReserveCopy(n);
391  }
392  uint8_t* buffer = &m_data->m_data[m_used];
393  Append16(item->next, buffer);
394  buffer += 2;
395  Append16(item->prev, buffer);
396  buffer += 2;
397  AppendValue(item->typeUid, buffer);
398  buffer += typeUidSize;
399  AppendValue(item->size, buffer);
400  buffer += sizeSize;
401  Append16(item->chunkUid, buffer);
402  return n;
403 }
404 
405 uint16_t
407  uint32_t prev,
408  const PacketMetadata::SmallItem* item,
409  const PacketMetadata::ExtraItem* extraItem)
410 {
411  NS_LOG_FUNCTION(this << next << prev << item->next << item->prev << item->typeUid << item->size
412  << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
413  << extraItem->packetUid);
414  NS_ASSERT(m_data != nullptr);
415  uint32_t typeUid = ((item->typeUid & 0x1) == 0x1) ? item->typeUid : item->typeUid + 1;
416  NS_ASSERT(m_used != prev && m_used != next);
417 
418  uint32_t typeUidSize = GetUleb128Size(typeUid);
419  uint32_t sizeSize = GetUleb128Size(item->size);
420  uint32_t fragStartSize = GetUleb128Size(extraItem->fragmentStart);
421  uint32_t fragEndSize = GetUleb128Size(extraItem->fragmentEnd);
422  uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
423 
424  if (m_used + n > m_data->m_size ||
425  (m_head != 0xffff && m_data->m_count != 1 && m_used != m_data->m_dirtyEnd))
426  {
427  ReserveCopy(n);
428  }
429 
430  uint8_t* buffer = &m_data->m_data[m_used];
431 
432  Append16(next, buffer);
433  buffer += 2;
434  Append16(prev, buffer);
435  buffer += 2;
436  AppendValue(typeUid, buffer);
437  buffer += typeUidSize;
438  AppendValue(item->size, buffer);
439  buffer += sizeSize;
440  Append16(item->chunkUid, buffer);
441  buffer += 2;
442  AppendValue(extraItem->fragmentStart, buffer);
443  buffer += fragStartSize;
444  AppendValue(extraItem->fragmentEnd, buffer);
445  buffer += fragEndSize;
446  Append32(extraItem->packetUid, buffer);
447 
448  return n;
449 }
450 
451 void
453  PacketMetadata::ExtraItem* extraItem,
454  uint32_t available)
455 {
456  NS_LOG_FUNCTION(this << item->next << item->prev << item->typeUid << item->size
457  << item->chunkUid << extraItem->fragmentStart << extraItem->fragmentEnd
458  << extraItem->packetUid << available);
459 
460  NS_ASSERT(m_data != nullptr);
461  /* If the tail we want to replace is located at the end of the data array,
462  * and if there is extra room at the end of this array, then,
463  * we can try to use that extra space to avoid falling in the slow
464  * path below.
465  */
466  if (m_tail + available == m_used && m_used == m_data->m_dirtyEnd)
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 && m_data->m_count == 1)
479  {
480  uint8_t* buffer = &m_data->m_data[m_tail];
481  Append16(item->next, buffer);
482  buffer += 2;
483  Append16(item->prev, buffer);
484  buffer += 2;
485  AppendValue(typeUid, buffer);
486  buffer += typeUidSize;
487  AppendValue(item->size, buffer);
488  buffer += sizeSize;
489  Append16(item->chunkUid, buffer);
490  buffer += 2;
491  AppendValue(extraItem->fragmentStart, buffer);
492  buffer += fragStartSize;
493  AppendValue(extraItem->fragmentEnd, buffer);
494  buffer += fragEndSize;
495  Append32(extraItem->packetUid, buffer);
496  m_used = std::max(m_used, static_cast<uint32_t>(buffer - &m_data->m_data[0]));
498  return;
499  }
500 
501  /* Below is the slow path which is hit if the new tail we want
502  * to append is bigger than the previous tail.
503  */
504 
505  // create a copy of the packet without its tail.
507  uint16_t current = m_head;
508  while (current != 0xffff && current != m_tail)
509  {
511  PacketMetadata::ExtraItem tmpExtraItem;
512  ReadItems(current, &tmpItem, &tmpExtraItem);
513  uint16_t written = h.AddBig(0xffff, h.m_tail, &tmpItem, &tmpExtraItem);
514  h.UpdateTail(written);
515  current = tmpItem.next;
516  }
517  // append new tail.
518  uint16_t written = h.AddBig(0xffff, h.m_tail, item, extraItem);
519  h.UpdateTail(written);
520 
521  *this = h;
522 }
523 
524 uint32_t
525 PacketMetadata::ReadItems(uint16_t current,
527  PacketMetadata::ExtraItem* extraItem) const
528 {
529  NS_LOG_FUNCTION(this << current << item->chunkUid << item->prev << item->next << item->size
530  << item->typeUid << extraItem->fragmentEnd << extraItem->fragmentStart
531  << extraItem->packetUid);
532  NS_ASSERT(current <= m_data->m_size);
533  const uint8_t* buffer = &m_data->m_data[current];
534  item->next = buffer[0];
535  item->next |= (buffer[1]) << 8;
536  item->prev = buffer[2];
537  item->prev |= (buffer[3]) << 8;
538  buffer += 4;
539  item->typeUid = ReadUleb128(&buffer);
540  item->size = ReadUleb128(&buffer);
541  item->chunkUid = buffer[0];
542  item->chunkUid |= (buffer[1]) << 8;
543  buffer += 2;
544 
545  bool isExtra = (item->typeUid & 0x1) == 0x1;
546  if (isExtra)
547  {
548  extraItem->fragmentStart = ReadUleb128(&buffer);
549  extraItem->fragmentEnd = ReadUleb128(&buffer);
550  extraItem->packetUid = buffer[0];
551  extraItem->packetUid |= buffer[1] << 8;
552  extraItem->packetUid |= buffer[2] << 16;
553  extraItem->packetUid |= buffer[3] << 24;
554  buffer += 4;
555  }
556  else
557  {
558  extraItem->fragmentStart = 0;
559  extraItem->fragmentEnd = item->size;
560  extraItem->packetUid = m_packetUid;
561  }
562  NS_ASSERT(buffer <= &m_data->m_data[m_data->m_size]);
563  return buffer - &m_data->m_data[current];
564 }
565 
568 {
569  NS_LOG_FUNCTION(size);
570  NS_LOG_LOGIC("create size=" << size << ", max=" << m_maxSize);
571  if (size > m_maxSize)
572  {
573  m_maxSize = size;
574  }
575  while (!m_freeList.empty())
576  {
578  m_freeList.pop_back();
579  if (data->m_size >= size)
580  {
581  NS_LOG_LOGIC("create found size=" << data->m_size);
582  data->m_count = 1;
583  return data;
584  }
585  NS_LOG_LOGIC("create dealloc size=" << data->m_size);
587  }
588  NS_LOG_LOGIC("create alloc size=" << m_maxSize);
590 }
591 
592 void
594 {
596  if (!m_enable)
597  {
599  return;
600  }
601  NS_LOG_LOGIC("recycle size=" << data->m_size << ", list=" << m_freeList.size());
602  NS_ASSERT(data->m_count == 0);
603  if (m_freeList.size() > 1000 || data->m_size < m_maxSize)
604  {
606  }
607  else
608  {
609  m_freeList.push_back(data);
610  }
611 }
612 
615 {
616  NS_LOG_FUNCTION(n);
617  uint32_t size = sizeof(Data);
619  {
621  }
623  auto buf = new uint8_t[size];
624  auto data = (PacketMetadata::Data*)buf;
625  data->m_size = n;
626  data->m_count = 1;
627  data->m_dirtyEnd = 0;
628  return data;
629 }
630 
631 void
633 {
635  auto buf = (uint8_t*)data;
636  delete[] buf;
637 }
638 
640 PacketMetadata::CreateFragment(uint32_t start, uint32_t end) const
641 {
642  NS_LOG_FUNCTION(this << start << end);
643  PacketMetadata fragment = *this;
644  fragment.RemoveAtStart(start);
645  fragment.RemoveAtEnd(end);
646  return fragment;
647 }
648 
649 void
650 PacketMetadata::AddHeader(const Header& header, uint32_t size)
651 {
652  NS_LOG_FUNCTION(this << &header << size);
653  uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
654  DoAddHeader(uid, size);
655  NS_ASSERT(IsStateOk());
656 }
657 
658 void
659 PacketMetadata::DoAddHeader(uint32_t uid, uint32_t size)
660 {
661  NS_LOG_FUNCTION(this << uid << size);
662  if (!m_enable)
663  {
664  m_metadataSkipped = true;
665  return;
666  }
667 
669  item.next = m_head;
670  item.prev = 0xffff;
671  item.typeUid = uid;
672  item.size = size;
673  item.chunkUid = m_chunkUid;
674  m_chunkUid++;
675  uint16_t written = AddSmall(&item);
676  UpdateHead(written);
677 }
678 
679 void
680 PacketMetadata::RemoveHeader(const Header& header, uint32_t size)
681 {
682  uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
683  NS_LOG_FUNCTION(this << &header << size);
684  if (!m_enable)
685  {
686  m_metadataSkipped = true;
687  return;
688  }
690  PacketMetadata::ExtraItem extraItem;
691  uint32_t read = ReadItems(m_head, &item, &extraItem);
692  if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
693  {
694  if (m_enableChecking)
695  {
696  NS_FATAL_ERROR("Removing unexpected header.");
697  }
698  return;
699  }
700  else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
701  {
702  if (m_enableChecking)
703  {
704  NS_FATAL_ERROR("Removing incomplete header.");
705  }
706  return;
707  }
708  if (m_head + read == m_used)
709  {
710  m_used = m_head;
711  }
712  if (m_head == m_tail)
713  {
714  m_head = 0xffff;
715  m_tail = 0xffff;
716  }
717  else
718  {
719  m_head = item.next;
720  }
721  NS_ASSERT(IsStateOk());
722 }
723 
724 void
725 PacketMetadata::AddTrailer(const Trailer& trailer, uint32_t size)
726 {
727  uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
728  NS_LOG_FUNCTION(this << &trailer << size);
729  if (!m_enable)
730  {
731  m_metadataSkipped = true;
732  return;
733  }
735  item.next = 0xffff;
736  item.prev = m_tail;
737  item.typeUid = uid;
738  item.size = size;
739  item.chunkUid = m_chunkUid;
740  m_chunkUid++;
741  uint16_t written = AddSmall(&item);
742  UpdateTail(written);
743  NS_ASSERT(IsStateOk());
744 }
745 
746 void
747 PacketMetadata::RemoveTrailer(const Trailer& trailer, uint32_t size)
748 {
749  uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
750  NS_LOG_FUNCTION(this << &trailer << size);
751  if (!m_enable)
752  {
753  m_metadataSkipped = true;
754  return;
755  }
757  PacketMetadata::ExtraItem extraItem;
758  uint32_t read = ReadItems(m_tail, &item, &extraItem);
759  if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
760  {
761  if (m_enableChecking)
762  {
763  NS_FATAL_ERROR("Removing unexpected trailer.");
764  }
765  return;
766  }
767  else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
768  {
769  if (m_enableChecking)
770  {
771  NS_FATAL_ERROR("Removing incomplete trailer.");
772  }
773  return;
774  }
775  if (m_tail + read == m_used)
776  {
777  m_used = m_tail;
778  }
779  if (m_head == m_tail)
780  {
781  m_head = 0xffff;
782  m_tail = 0xffff;
783  }
784  else
785  {
786  m_tail = item.prev;
787  }
788  NS_ASSERT(IsStateOk());
789 }
790 
791 void
793 {
794  NS_LOG_FUNCTION(this << &o);
795  if (!m_enable)
796  {
797  m_metadataSkipped = true;
798  return;
799  }
800  if (m_tail == 0xffff)
801  {
802  // We have no items so 'AddAtEnd' is
803  // equivalent to self-assignment.
804  *this = o;
805  NS_ASSERT(IsStateOk());
806  return;
807  }
808  if (o.m_head == 0xffff)
809  {
810  NS_ASSERT(o.m_tail == 0xffff);
811  // we have nothing to append.
812  return;
813  }
814  NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
815 
816  // We read the current tail because we are going to append
817  // after this item.
818  PacketMetadata::SmallItem tailItem;
819  PacketMetadata::ExtraItem tailExtraItem;
820  uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
821 
822  uint16_t current;
824  PacketMetadata::ExtraItem extraItem;
825  o.ReadItems(o.m_head, &item, &extraItem);
826  if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
827  item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
828  extraItem.fragmentStart == tailExtraItem.fragmentEnd)
829  {
830  /* If the previous tail came from the same header as
831  * the next item we want to append to our array, then,
832  * we merge them and attempt to reuse the previous tail's
833  * location.
834  */
835  tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
836  ReplaceTail(&tailItem, &tailExtraItem, tailSize);
837  if (o.m_head == o.m_tail)
838  {
839  // there is only one item to append to self from other.
840  return;
841  }
842  current = item.next;
843  }
844  else
845  {
846  current = o.m_head;
847  }
848 
849  /* Now that we have merged our current tail with the head of the
850  * next packet, we just append all items from the next packet
851  * to the current packet.
852  */
853  while (current != 0xffff)
854  {
855  o.ReadItems(current, &item, &extraItem);
856  uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
857  UpdateTail(written);
858  if (current == o.m_tail)
859  {
860  break;
861  }
862  current = item.next;
863  }
864  NS_ASSERT(IsStateOk());
865 }
866 
867 void
869 {
870  NS_LOG_FUNCTION(this << end);
871  if (!m_enable)
872  {
873  m_metadataSkipped = true;
874  return;
875  }
876 }
877 
878 void
880 {
881  NS_LOG_FUNCTION(this << start);
882  if (!m_enable)
883  {
884  m_metadataSkipped = true;
885  return;
886  }
887  NS_ASSERT(m_data != nullptr);
888  uint32_t leftToRemove = start;
889  uint16_t current = m_head;
890  while (current != 0xffff && leftToRemove > 0)
891  {
893  PacketMetadata::ExtraItem extraItem;
894  ReadItems(current, &item, &extraItem);
895  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
896  if (itemRealSize <= leftToRemove)
897  {
898  // remove from list.
899  if (m_head == m_tail)
900  {
901  m_head = 0xffff;
902  m_tail = 0xffff;
903  }
904  else
905  {
906  m_head = item.next;
907  }
908  leftToRemove -= itemRealSize;
909  }
910  else
911  {
912  // fragment the list item.
913  PacketMetadata fragment(m_packetUid, 0);
914  extraItem.fragmentStart += leftToRemove;
915  leftToRemove = 0;
916  uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
917  fragment.UpdateTail(written);
918  while (current != 0xffff && current != m_tail)
919  {
920  current = item.next;
921  ReadItems(current, &item, &extraItem);
922  written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
923  fragment.UpdateTail(written);
924  }
925  *this = fragment;
926  }
927  NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
928  extraItem.fragmentStart <= extraItem.fragmentEnd);
929  if (current == m_tail)
930  {
931  break;
932  }
933  current = item.next;
934  }
935  NS_ASSERT(leftToRemove == 0);
936  NS_ASSERT(IsStateOk());
937 }
938 
939 void
941 {
942  NS_LOG_FUNCTION(this << end);
943  if (!m_enable)
944  {
945  m_metadataSkipped = true;
946  return;
947  }
948  NS_ASSERT(m_data != nullptr);
949 
950  uint32_t leftToRemove = end;
951  uint16_t current = m_tail;
952  while (current != 0xffff && leftToRemove > 0)
953  {
955  PacketMetadata::ExtraItem extraItem;
956  ReadItems(current, &item, &extraItem);
957  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
958  if (itemRealSize <= leftToRemove)
959  {
960  // remove from list.
961  if (m_head == m_tail)
962  {
963  m_head = 0xffff;
964  m_tail = 0xffff;
965  }
966  else
967  {
968  m_tail = item.prev;
969  }
970  leftToRemove -= itemRealSize;
971  }
972  else
973  {
974  // fragment the list item.
975  PacketMetadata fragment(m_packetUid, 0);
976  NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
977  extraItem.fragmentEnd -= leftToRemove;
978  leftToRemove = 0;
979  uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
980  fragment.UpdateHead(written);
981  while (current != 0xffff && current != m_head)
982  {
983  current = item.prev;
984  ReadItems(current, &item, &extraItem);
985  written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
986  fragment.UpdateHead(written);
987  }
988  *this = fragment;
989  }
990  NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
991  extraItem.fragmentStart <= extraItem.fragmentEnd);
992  if (current == m_head)
993  {
994  break;
995  }
996  current = item.prev;
997  }
998  NS_ASSERT(leftToRemove == 0);
999  NS_ASSERT(IsStateOk());
1000 }
1001 
1002 uint32_t
1004 {
1005  NS_LOG_FUNCTION(this);
1006  uint32_t totalSize = 0;
1007  uint16_t current = m_head;
1008  uint16_t tail = m_tail;
1009  while (current != 0xffff)
1010  {
1012  PacketMetadata::ExtraItem extraItem;
1013  ReadItems(current, &item, &extraItem);
1014  totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1015  if (current == tail)
1016  {
1017  break;
1018  }
1019  NS_ASSERT(current != item.next);
1020  current = item.next;
1021  }
1022  return totalSize;
1023 }
1024 
1025 uint64_t
1027 {
1028  NS_LOG_FUNCTION(this);
1029  return m_packetUid;
1030 }
1031 
1034 {
1035  NS_LOG_FUNCTION(this << &buffer);
1036  return ItemIterator(this, buffer);
1037 }
1038 
1040  : m_metadata(metadata),
1041  m_buffer(buffer),
1042  m_current(metadata->m_head),
1043  m_offset(0),
1044  m_hasReadTail(false)
1045 {
1046  NS_LOG_FUNCTION(this << metadata << &buffer);
1047 }
1048 
1049 bool
1051 {
1052  NS_LOG_FUNCTION(this);
1053  if (m_current == 0xffff)
1054  {
1055  return false;
1056  }
1057  if (m_hasReadTail)
1058  {
1059  return false;
1060  }
1061  return true;
1062 }
1063 
1066 {
1067  NS_LOG_FUNCTION(this);
1068  PacketMetadata::Item item;
1069  PacketMetadata::SmallItem smallItem;
1070  PacketMetadata::ExtraItem extraItem;
1071  m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1072  if (m_current == m_metadata->m_tail)
1073  {
1074  m_hasReadTail = true;
1075  }
1076  m_current = smallItem.next;
1077  uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1078  item.tid.SetUid(uid);
1079  item.currentTrimmedFromStart = extraItem.fragmentStart;
1080  item.currentTrimmedFromEnd = extraItem.fragmentEnd - smallItem.size;
1081  item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1082  item.isFragment = (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size);
1083  TypeId tid;
1084  tid.SetUid(uid);
1085  if (uid == 0)
1086  {
1088  }
1089  else if (tid.IsChildOf(Header::GetTypeId()))
1090  {
1092  if (!item.isFragment)
1093  {
1094  item.current = m_buffer.Begin();
1095  item.current.Next(m_offset);
1096  }
1097  }
1098  else if (tid.IsChildOf(Trailer::GetTypeId()))
1099  {
1101  if (!item.isFragment)
1102  {
1103  item.current = m_buffer.End();
1104  item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1105  }
1106  }
1107  else
1108  {
1109  NS_ASSERT(false);
1110  }
1111  m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1112  return item;
1113 }
1114 
1115 uint32_t
1117 {
1118  NS_LOG_FUNCTION(this);
1119  uint32_t totalSize = 0;
1120 
1121  // add 8 bytes for the packet uid
1122  totalSize += 8;
1123 
1124  // if packet-metadata not enabled, total size
1125  // is simply 4-bytes for itself plus 8-bytes
1126  // for packet uid
1127  if (!m_enable)
1128  {
1129  return totalSize;
1130  }
1131 
1133  PacketMetadata::ExtraItem extraItem;
1134  uint32_t current = m_head;
1135  while (current != 0xffff)
1136  {
1137  ReadItems(current, &item, &extraItem);
1138  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1139  if (uid == 0)
1140  {
1141  totalSize += 4;
1142  }
1143  else
1144  {
1145  TypeId tid;
1146  tid.SetUid(uid);
1147  totalSize += 4 + tid.GetName().size();
1148  }
1149  totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1150  if (current == m_tail)
1151  {
1152  break;
1153  }
1154  NS_ASSERT(current != item.next);
1155  current = item.next;
1156  }
1157  return totalSize;
1158 }
1159 
1160 uint32_t
1161 PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1162 {
1163  NS_LOG_FUNCTION(this << &buffer << maxSize);
1164  uint8_t* start = buffer;
1165 
1166  buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1167  if (buffer == nullptr)
1168  {
1169  return 0;
1170  }
1171 
1173  PacketMetadata::ExtraItem extraItem;
1174  uint32_t current = m_head;
1175  while (current != 0xffff)
1176  {
1177  ReadItems(current, &item, &extraItem);
1178  NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1179  << ", typeUid=" << item.typeUid << ", size=" << item.size
1180  << ", chunkUid=" << item.chunkUid
1181  << ", fragmentStart=" << extraItem.fragmentStart
1182  << ", fragmentEnd=" << extraItem.fragmentEnd
1183  << ", packetUid=" << extraItem.packetUid);
1184 
1185  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1186  if (uid != 0)
1187  {
1188  TypeId tid;
1189  tid.SetUid(uid);
1190  std::string uidString = tid.GetName();
1191  uint32_t uidStringSize = uidString.size();
1192  buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1193  if (buffer == nullptr)
1194  {
1195  return 0;
1196  }
1197  buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1198  uidStringSize,
1199  start,
1200  buffer,
1201  maxSize);
1202  if (buffer == nullptr)
1203  {
1204  return 0;
1205  }
1206  }
1207  else
1208  {
1209  buffer = AddToRawU32(0, start, buffer, maxSize);
1210  if (buffer == nullptr)
1211  {
1212  return 0;
1213  }
1214  }
1215 
1216  uint8_t isBig = item.typeUid & 0x1;
1217  buffer = AddToRawU8(isBig, start, buffer, maxSize);
1218  if (buffer == nullptr)
1219  {
1220  return 0;
1221  }
1222 
1223  buffer = AddToRawU32(item.size, start, buffer, maxSize);
1224  if (buffer == nullptr)
1225  {
1226  return 0;
1227  }
1228 
1229  buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1230  if (buffer == nullptr)
1231  {
1232  return 0;
1233  }
1234 
1235  buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1236  if (buffer == nullptr)
1237  {
1238  return 0;
1239  }
1240 
1241  buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1242  if (buffer == nullptr)
1243  {
1244  return 0;
1245  }
1246 
1247  buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1248  if (buffer == nullptr)
1249  {
1250  return 0;
1251  }
1252 
1253  if (current == m_tail)
1254  {
1255  break;
1256  }
1257 
1258  NS_ASSERT(current != item.next);
1259  current = item.next;
1260  }
1261 
1262  NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1263  return 1;
1264 }
1265 
1266 uint32_t
1267 PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1268 {
1269  NS_LOG_FUNCTION(this << &buffer << size);
1270  const uint8_t* start = buffer;
1271  uint32_t desSize = size - 4;
1272 
1273  buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1274  desSize -= 8;
1275 
1276  PacketMetadata::SmallItem item = {0};
1277  PacketMetadata::ExtraItem extraItem = {0};
1278  while (desSize > 0)
1279  {
1280  uint32_t uidStringSize = 0;
1281  buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1282  desSize -= 4;
1283  uint32_t uid;
1284  if (uidStringSize == 0)
1285  {
1286  // uid zero for payload.
1287  uid = 0;
1288  }
1289  else
1290  {
1291  std::string uidString;
1292  for (uint32_t j = 0; j < uidStringSize; j++)
1293  {
1294  uint8_t ch = 0;
1295  buffer = ReadFromRawU8(ch, start, buffer, size);
1296  uidString.push_back(ch);
1297  desSize--;
1298  }
1299  TypeId tid = TypeId::LookupByName(uidString);
1300  uid = tid.GetUid();
1301  }
1302  uint8_t isBig = 0;
1303  buffer = ReadFromRawU8(isBig, start, buffer, size);
1304  desSize--;
1305  item.typeUid = (uid << 1) | isBig;
1306  buffer = ReadFromRawU32(item.size, start, buffer, size);
1307  desSize -= 4;
1308  buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1309  desSize -= 2;
1310  buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1311  desSize -= 4;
1312  buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1313  desSize -= 4;
1314  buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1315  desSize -= 8;
1316  NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1317  << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1318  << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1319  << ", packetUid=" << extraItem.packetUid);
1320  uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1321  UpdateTail(tmp);
1322  }
1323  NS_ASSERT(desSize == 0);
1324  return (desSize != 0) ? 0 : 1;
1325 }
1326 
1327 uint8_t*
1328 PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1329 {
1330  NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1331  // First check buffer overflow
1332  if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1333  {
1334  return nullptr;
1335  }
1336  memcpy(current, &data, sizeof(uint8_t));
1337  return current + sizeof(uint8_t);
1338 }
1339 
1340 uint8_t*
1342  uint8_t* start,
1343  uint8_t* current,
1344  uint32_t maxSize)
1345 {
1346  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1347  // First check buffer overflow
1348  if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1349  {
1350  return nullptr;
1351  }
1352  memcpy(current, &data, sizeof(uint16_t));
1353  return current + sizeof(uint16_t);
1354 }
1355 
1356 uint8_t*
1358  uint8_t* start,
1359  uint8_t* current,
1360  uint32_t maxSize)
1361 {
1362  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1363  // First check buffer overflow
1364  if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1365  {
1366  return nullptr;
1367  }
1368  memcpy(current, &data, sizeof(uint32_t));
1369  return current + sizeof(uint32_t);
1370 }
1371 
1372 uint8_t*
1374  uint8_t* start,
1375  uint8_t* current,
1376  uint32_t maxSize)
1377 {
1378  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1379  // First check buffer overflow
1380  if (static_cast<uint32_t>(current + sizeof(uint64_t) - start) > maxSize)
1381  {
1382  return nullptr;
1383  }
1384  memcpy(current, &data, sizeof(uint64_t));
1385  return current + sizeof(uint64_t);
1386 }
1387 
1388 uint8_t*
1390  uint32_t dataSize,
1391  uint8_t* start,
1392  uint8_t* current,
1393  uint32_t maxSize)
1394 {
1395  NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1396  // First check buffer overflow
1397  if (static_cast<uint32_t>(current + dataSize - start) > maxSize)
1398  {
1399  return nullptr;
1400  }
1401  memcpy(current, data, dataSize);
1402  return current + dataSize;
1403 }
1404 
1405 uint8_t*
1407  const uint8_t* start,
1408  const uint8_t* current,
1409  uint32_t maxSize)
1410 {
1411  NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1412  // First check buffer underflow
1413  if (static_cast<uint32_t>(current + sizeof(uint8_t) - start) > maxSize)
1414  {
1415  return nullptr;
1416  }
1417  memcpy(&data, current, sizeof(uint8_t));
1418  return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1419 }
1420 
1421 uint8_t*
1423  const uint8_t* start,
1424  const uint8_t* current,
1425  uint32_t maxSize)
1426 {
1427  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1428  // First check buffer underflow
1429  if (static_cast<uint32_t>(current + sizeof(uint16_t) - start) > maxSize)
1430  {
1431  return nullptr;
1432  }
1433  memcpy(&data, current, sizeof(uint16_t));
1434  return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1435 }
1436 
1437 uint8_t*
1439  const uint8_t* start,
1440  const uint8_t* current,
1441  uint32_t maxSize)
1442 {
1443  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1444  // First check buffer underflow
1445  if (static_cast<uint32_t>(current + sizeof(uint32_t) - start) > maxSize)
1446  {
1447  return nullptr;
1448  }
1449  memcpy(&data, current, sizeof(uint32_t));
1450  return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1451 }
1452 
1453 uint8_t*
1455  const uint8_t* start,
1456  const uint8_t* current,
1457  uint32_t maxSize)
1458 {
1459  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1460  // First check buffer underflow
1461  if ((uint32_t)(current + sizeof(uint64_t) - start) > maxSize)
1462  {
1463  return nullptr;
1464  }
1465  memcpy(&data, current, sizeof(uint64_t));
1466  return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1467 }
1468 
1469 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:42
void Prev()
go backward by one byte
Definition: buffer.h:860
void Next()
go forward by one byte
Definition: buffer.h:853
automatically resized byte buffer
Definition: buffer.h:94
Protocol header serialization and deserialization.
Definition: header.h:44
static TypeId GetTypeId()
Get the type ID.
Definition: header.cc:37
virtual TypeId GetInstanceTypeId() const =0
Get the most derived TypeId for this Object.
Iterator class for metadata items.
bool HasNext() const
Checks if there is another metadata item.
Item Next()
Retrieve the next metadata item.
ItemIterator(const PacketMetadata *metadata, Buffer buffer)
Constructor.
Handle packet metadata about packet headers and trailers.
uint32_t m_used
used portion
static uint8_t * ReadFromRawU64(uint64_t &data, const uint8_t *start, const uint8_t *current, uint32_t maxSize)
Helper for the raw deserialization.
uint32_t GetSerializedSize() const
Get the metadata serialized size.
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.
Data * m_data
Metadata storage.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
void AddHeader(const Header &header, uint32_t size)
Add an header.
uint32_t ReadItems(uint16_t current, PacketMetadata::SmallItem *item, PacketMetadata::ExtraItem *extraItem) const
Read items.
static void Deallocate(PacketMetadata::Data *data)
Deallocate the buffer memory.
void AppendValueExtra(uint32_t value, uint8_t *buffer)
Append a value to the buffer - extra.
static PacketMetadata::Data * Create(uint32_t size)
Create a buffer data storage.
void Append32(uint32_t value, uint8_t *buffer)
Append a 32-bit value to the buffer.
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.
uint64_t GetUid() const
Get the packet Uid.
uint16_t m_head
list head
void AppendValue(uint32_t value, uint8_t *buffer)
Append a value to the buffer.
static void Recycle(PacketMetadata::Data *data)
Recycle the buffer memory.
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 bool m_enable
Enable the packet metadata.
void AddAtEnd(const PacketMetadata &o)
Add a metadata at the metadata start.
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.
static void EnableChecking()
Enable the packet metadata checking.
void RemoveAtEnd(uint32_t end)
Remove a chunk of metadata at the metadata end.
void RemoveHeader(const Header &header, uint32_t size)
Remove an header.
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 uint16_t m_chunkUid
Chunk Uid.
static PacketMetadata::Data * Allocate(uint32_t n)
Allocate a buffer data storage.
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.
uint32_t GetTotalSize() const
Get the total size used by the metadata.
void Append16(uint16_t value, uint8_t *buffer)
Append a 16-bit value to the buffer.
void RemoveTrailer(const Trailer &trailer, uint32_t size)
Remove a trailer.
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.
bool IsStateOk() const
Check if the metadata state is ok.
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.
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.
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.
void AddTrailer(const Trailer &trailer, uint32_t size)
Add a trailer.
static uint8_t * AddToRawU16(const uint16_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static uint8_t * AddToRawU64(const uint64_t &data, uint8_t *start, uint8_t *current, uint32_t maxSize)
Helper for the raw serialization.
static void Enable()
Enable the packet metadata.
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
static TypeId GetTypeId()
Get the type ID.
Definition: trailer.cc:37
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:971
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1212
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1205
std::string GetName() const
Get the name.
Definition: type-id.cc:991
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#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:86
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:179
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#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.
#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]
uint32_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
ItemType type
metadata type
TypeId tid
TypeId of Header or Trailer.
bool isFragment
true: this is a fragmented header, trailer, or, payload.
uint32_t currentTrimmedFromEnd
how many bytes were trimmed from the end of a fragment.
Buffer::Iterator current
an iterator which can be fed to Deserialize.
uint32_t currentTrimmedFromStart
how many bytes were trimmed from the start of a fragment.
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.
uint32_t prev