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 (iterator 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);
80  struct PacketMetadata::Data* newData = PacketMetadata::Create(m_used + 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  {
145  struct PacketMetadata::SmallItem item;
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
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, (uint16_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  {
510  struct PacketMetadata::SmallItem tmpItem;
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,
526  struct PacketMetadata::SmallItem* item,
527  struct 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 
566 struct PacketMetadata::Data*
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  {
577  struct PacketMetadata::Data* data = m_freeList.back();
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 
613 struct PacketMetadata::Data*
615 {
616  NS_LOG_FUNCTION(n);
617  uint32_t size = sizeof(struct Data);
619  {
621  }
623  uint8_t* buf = new uint8_t[size];
624  struct PacketMetadata::Data* data = (struct 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  uint8_t* 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  NS_ASSERT(IsStateOk());
654  uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
655  DoAddHeader(uid, size);
656  NS_ASSERT(IsStateOk());
657 }
658 
659 void
660 PacketMetadata::DoAddHeader(uint32_t uid, uint32_t size)
661 {
662  NS_LOG_FUNCTION(this << uid << size);
663  if (!m_enable)
664  {
665  m_metadataSkipped = true;
666  return;
667  }
668 
669  struct PacketMetadata::SmallItem item;
670  item.next = m_head;
671  item.prev = 0xffff;
672  item.typeUid = uid;
673  item.size = size;
674  item.chunkUid = m_chunkUid;
675  m_chunkUid++;
676  uint16_t written = AddSmall(&item);
677  UpdateHead(written);
678 }
679 
680 void
681 PacketMetadata::RemoveHeader(const Header& header, uint32_t size)
682 {
683  uint32_t uid = header.GetInstanceTypeId().GetUid() << 1;
684  NS_LOG_FUNCTION(this << &header << size);
685  NS_ASSERT(IsStateOk());
686  if (!m_enable)
687  {
688  m_metadataSkipped = true;
689  return;
690  }
691  struct PacketMetadata::SmallItem item;
692  struct PacketMetadata::ExtraItem extraItem;
693  uint32_t read = ReadItems(m_head, &item, &extraItem);
694  if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
695  {
696  if (m_enableChecking)
697  {
698  NS_FATAL_ERROR("Removing unexpected header.");
699  }
700  return;
701  }
702  else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
703  {
704  if (m_enableChecking)
705  {
706  NS_FATAL_ERROR("Removing incomplete header.");
707  }
708  return;
709  }
710  if (m_head + read == m_used)
711  {
712  m_used = m_head;
713  }
714  if (m_head == m_tail)
715  {
716  m_head = 0xffff;
717  m_tail = 0xffff;
718  }
719  else
720  {
721  m_head = item.next;
722  }
723  NS_ASSERT(IsStateOk());
724 }
725 
726 void
727 PacketMetadata::AddTrailer(const Trailer& trailer, uint32_t size)
728 {
729  uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
730  NS_LOG_FUNCTION(this << &trailer << size);
731  NS_ASSERT(IsStateOk());
732  if (!m_enable)
733  {
734  m_metadataSkipped = true;
735  return;
736  }
737  struct PacketMetadata::SmallItem item;
738  item.next = 0xffff;
739  item.prev = m_tail;
740  item.typeUid = uid;
741  item.size = size;
742  item.chunkUid = m_chunkUid;
743  m_chunkUid++;
744  uint16_t written = AddSmall(&item);
745  UpdateTail(written);
746  NS_ASSERT(IsStateOk());
747 }
748 
749 void
750 PacketMetadata::RemoveTrailer(const Trailer& trailer, uint32_t size)
751 {
752  uint32_t uid = trailer.GetInstanceTypeId().GetUid() << 1;
753  NS_LOG_FUNCTION(this << &trailer << size);
754  NS_ASSERT(IsStateOk());
755  if (!m_enable)
756  {
757  m_metadataSkipped = true;
758  return;
759  }
760  struct PacketMetadata::SmallItem item;
761  struct PacketMetadata::ExtraItem extraItem;
762  uint32_t read = ReadItems(m_tail, &item, &extraItem);
763  if ((item.typeUid & 0xfffffffe) != uid || item.size != size)
764  {
765  if (m_enableChecking)
766  {
767  NS_FATAL_ERROR("Removing unexpected trailer.");
768  }
769  return;
770  }
771  else if (item.typeUid != uid && (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != size))
772  {
773  if (m_enableChecking)
774  {
775  NS_FATAL_ERROR("Removing incomplete trailer.");
776  }
777  return;
778  }
779  if (m_tail + read == m_used)
780  {
781  m_used = m_tail;
782  }
783  if (m_head == m_tail)
784  {
785  m_head = 0xffff;
786  m_tail = 0xffff;
787  }
788  else
789  {
790  m_tail = item.prev;
791  }
792  NS_ASSERT(IsStateOk());
793 }
794 
795 void
797 {
798  NS_LOG_FUNCTION(this << &o);
799  NS_ASSERT(IsStateOk());
800  if (!m_enable)
801  {
802  m_metadataSkipped = true;
803  return;
804  }
805  if (m_tail == 0xffff)
806  {
807  // We have no items so 'AddAtEnd' is
808  // equivalent to self-assignment.
809  *this = o;
810  NS_ASSERT(IsStateOk());
811  return;
812  }
813  if (o.m_head == 0xffff)
814  {
815  NS_ASSERT(o.m_tail == 0xffff);
816  // we have nothing to append.
817  return;
818  }
819  NS_ASSERT(m_head != 0xffff && m_tail != 0xffff);
820 
821  // We read the current tail because we are going to append
822  // after this item.
823  struct PacketMetadata::SmallItem tailItem;
824  PacketMetadata::ExtraItem tailExtraItem;
825  uint32_t tailSize = ReadItems(m_tail, &tailItem, &tailExtraItem);
826 
827  uint16_t current;
828  struct PacketMetadata::SmallItem item;
829  PacketMetadata::ExtraItem extraItem;
830  o.ReadItems(o.m_head, &item, &extraItem);
831  if (extraItem.packetUid == tailExtraItem.packetUid && item.typeUid == tailItem.typeUid &&
832  item.chunkUid == tailItem.chunkUid && item.size == tailItem.size &&
833  extraItem.fragmentStart == tailExtraItem.fragmentEnd)
834  {
835  /* If the previous tail came from the same header as
836  * the next item we want to append to our array, then,
837  * we merge them and attempt to reuse the previous tail's
838  * location.
839  */
840  tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
841  ReplaceTail(&tailItem, &tailExtraItem, tailSize);
842  if (o.m_head == o.m_tail)
843  {
844  // there is only one item to append to self from other.
845  return;
846  }
847  current = item.next;
848  }
849  else
850  {
851  current = o.m_head;
852  }
853 
854  /* Now that we have merged our current tail with the head of the
855  * next packet, we just append all items from the next packet
856  * to the current packet.
857  */
858  while (current != 0xffff)
859  {
860  o.ReadItems(current, &item, &extraItem);
861  uint16_t written = AddBig(0xffff, m_tail, &item, &extraItem);
862  UpdateTail(written);
863  if (current == o.m_tail)
864  {
865  break;
866  }
867  current = item.next;
868  }
869  NS_ASSERT(IsStateOk());
870 }
871 
872 void
874 {
875  NS_LOG_FUNCTION(this << end);
876  if (!m_enable)
877  {
878  m_metadataSkipped = true;
879  return;
880  }
881 }
882 
883 void
885 {
886  NS_LOG_FUNCTION(this << start);
887  NS_ASSERT(IsStateOk());
888  if (!m_enable)
889  {
890  m_metadataSkipped = true;
891  return;
892  }
893  NS_ASSERT(m_data != nullptr);
894  uint32_t leftToRemove = start;
895  uint16_t current = m_head;
896  while (current != 0xffff && leftToRemove > 0)
897  {
898  struct PacketMetadata::SmallItem item;
899  PacketMetadata::ExtraItem extraItem;
900  ReadItems(current, &item, &extraItem);
901  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
902  if (itemRealSize <= leftToRemove)
903  {
904  // remove from list.
905  if (m_head == m_tail)
906  {
907  m_head = 0xffff;
908  m_tail = 0xffff;
909  }
910  else
911  {
912  m_head = item.next;
913  }
914  leftToRemove -= itemRealSize;
915  }
916  else
917  {
918  // fragment the list item.
919  PacketMetadata fragment(m_packetUid, 0);
920  extraItem.fragmentStart += leftToRemove;
921  leftToRemove = 0;
922  uint16_t written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
923  fragment.UpdateTail(written);
924  while (current != 0xffff && current != m_tail)
925  {
926  current = item.next;
927  ReadItems(current, &item, &extraItem);
928  written = fragment.AddBig(0xffff, fragment.m_tail, &item, &extraItem);
929  fragment.UpdateTail(written);
930  }
931  *this = fragment;
932  }
933  NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
934  extraItem.fragmentStart <= extraItem.fragmentEnd);
935  if (current == m_tail)
936  {
937  break;
938  }
939  current = item.next;
940  }
941  NS_ASSERT(leftToRemove == 0);
942  NS_ASSERT(IsStateOk());
943 }
944 
945 void
947 {
948  NS_LOG_FUNCTION(this << end);
949  NS_ASSERT(IsStateOk());
950  if (!m_enable)
951  {
952  m_metadataSkipped = true;
953  return;
954  }
955  NS_ASSERT(m_data != nullptr);
956 
957  uint32_t leftToRemove = end;
958  uint16_t current = m_tail;
959  while (current != 0xffff && leftToRemove > 0)
960  {
961  struct PacketMetadata::SmallItem item;
962  PacketMetadata::ExtraItem extraItem;
963  ReadItems(current, &item, &extraItem);
964  uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
965  if (itemRealSize <= leftToRemove)
966  {
967  // remove from list.
968  if (m_head == m_tail)
969  {
970  m_head = 0xffff;
971  m_tail = 0xffff;
972  }
973  else
974  {
975  m_tail = item.prev;
976  }
977  leftToRemove -= itemRealSize;
978  }
979  else
980  {
981  // fragment the list item.
982  PacketMetadata fragment(m_packetUid, 0);
983  NS_ASSERT(extraItem.fragmentEnd > leftToRemove);
984  extraItem.fragmentEnd -= leftToRemove;
985  leftToRemove = 0;
986  uint16_t written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
987  fragment.UpdateHead(written);
988  while (current != 0xffff && current != m_head)
989  {
990  current = item.prev;
991  ReadItems(current, &item, &extraItem);
992  written = fragment.AddBig(fragment.m_head, 0xffff, &item, &extraItem);
993  fragment.UpdateHead(written);
994  }
995  *this = fragment;
996  }
997  NS_ASSERT(item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
998  extraItem.fragmentStart <= extraItem.fragmentEnd);
999  if (current == m_head)
1000  {
1001  break;
1002  }
1003  current = item.prev;
1004  }
1005  NS_ASSERT(leftToRemove == 0);
1006  NS_ASSERT(IsStateOk());
1007 }
1008 
1009 uint32_t
1011 {
1012  NS_LOG_FUNCTION(this);
1013  uint32_t totalSize = 0;
1014  uint16_t current = m_head;
1015  uint16_t tail = m_tail;
1016  while (current != 0xffff)
1017  {
1018  struct PacketMetadata::SmallItem item;
1019  PacketMetadata::ExtraItem extraItem;
1020  ReadItems(current, &item, &extraItem);
1021  totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
1022  if (current == tail)
1023  {
1024  break;
1025  }
1026  NS_ASSERT(current != item.next);
1027  current = item.next;
1028  }
1029  return totalSize;
1030 }
1031 
1032 uint64_t
1034 {
1035  NS_LOG_FUNCTION(this);
1036  return m_packetUid;
1037 }
1038 
1041 {
1042  NS_LOG_FUNCTION(this << &buffer);
1043  return ItemIterator(this, buffer);
1044 }
1045 
1047  : m_metadata(metadata),
1048  m_buffer(buffer),
1049  m_current(metadata->m_head),
1050  m_offset(0),
1051  m_hasReadTail(false)
1052 {
1053  NS_LOG_FUNCTION(this << metadata << &buffer);
1054 }
1055 
1056 bool
1058 {
1059  NS_LOG_FUNCTION(this);
1060  if (m_current == 0xffff)
1061  {
1062  return false;
1063  }
1064  if (m_hasReadTail)
1065  {
1066  return false;
1067  }
1068  return true;
1069 }
1070 
1073 {
1074  NS_LOG_FUNCTION(this);
1075  struct PacketMetadata::Item item;
1076  struct PacketMetadata::SmallItem smallItem;
1077  struct PacketMetadata::ExtraItem extraItem;
1078  m_metadata->ReadItems(m_current, &smallItem, &extraItem);
1079  if (m_current == m_metadata->m_tail)
1080  {
1081  m_hasReadTail = true;
1082  }
1083  m_current = smallItem.next;
1084  uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
1085  item.tid.SetUid(uid);
1086  item.currentTrimedFromStart = extraItem.fragmentStart;
1087  item.currentTrimedFromEnd = extraItem.fragmentEnd - smallItem.size;
1088  item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
1089  if (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size)
1090  {
1091  item.isFragment = true;
1092  }
1093  else
1094  {
1095  item.isFragment = false;
1096  }
1097  TypeId tid;
1098  tid.SetUid(uid);
1099  if (uid == 0)
1100  {
1102  }
1103  else if (tid.IsChildOf(Header::GetTypeId()))
1104  {
1106  if (!item.isFragment)
1107  {
1108  item.current = m_buffer.Begin();
1109  item.current.Next(m_offset);
1110  }
1111  }
1112  else if (tid.IsChildOf(Trailer::GetTypeId()))
1113  {
1115  if (!item.isFragment)
1116  {
1117  item.current = m_buffer.End();
1118  item.current.Prev(m_buffer.GetSize() - (m_offset + smallItem.size));
1119  }
1120  }
1121  else
1122  {
1123  NS_ASSERT(false);
1124  }
1125  m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
1126  return item;
1127 }
1128 
1129 uint32_t
1131 {
1132  NS_LOG_FUNCTION(this);
1133  uint32_t totalSize = 0;
1134 
1135  // add 8 bytes for the packet uid
1136  totalSize += 8;
1137 
1138  // if packet-metadata not enabled, total size
1139  // is simply 4-bytes for itself plus 8-bytes
1140  // for packet uid
1141  if (!m_enable)
1142  {
1143  return totalSize;
1144  }
1145 
1146  struct PacketMetadata::SmallItem item;
1147  struct PacketMetadata::ExtraItem extraItem;
1148  uint32_t current = m_head;
1149  while (current != 0xffff)
1150  {
1151  ReadItems(current, &item, &extraItem);
1152  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1153  if (uid == 0)
1154  {
1155  totalSize += 4;
1156  }
1157  else
1158  {
1159  TypeId tid;
1160  tid.SetUid(uid);
1161  totalSize += 4 + tid.GetName().size();
1162  }
1163  totalSize += 1 + 4 + 2 + 4 + 4 + 8;
1164  if (current == m_tail)
1165  {
1166  break;
1167  }
1168  NS_ASSERT(current != item.next);
1169  current = item.next;
1170  }
1171  return totalSize;
1172 }
1173 
1174 uint32_t
1175 PacketMetadata::Serialize(uint8_t* buffer, uint32_t maxSize) const
1176 {
1177  NS_LOG_FUNCTION(this << &buffer << maxSize);
1178  uint8_t* start = buffer;
1179 
1180  buffer = AddToRawU64(m_packetUid, start, buffer, maxSize);
1181  if (buffer == nullptr)
1182  {
1183  return 0;
1184  }
1185 
1186  struct PacketMetadata::SmallItem item;
1187  struct PacketMetadata::ExtraItem extraItem;
1188  uint32_t current = m_head;
1189  while (current != 0xffff)
1190  {
1191  ReadItems(current, &item, &extraItem);
1192  NS_LOG_LOGIC("bytesWritten=" << static_cast<uint32_t>(buffer - start)
1193  << ", typeUid=" << item.typeUid << ", size=" << item.size
1194  << ", chunkUid=" << item.chunkUid
1195  << ", fragmentStart=" << extraItem.fragmentStart
1196  << ", fragmentEnd=" << extraItem.fragmentEnd
1197  << ", packetUid=" << extraItem.packetUid);
1198 
1199  uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
1200  if (uid != 0)
1201  {
1202  TypeId tid;
1203  tid.SetUid(uid);
1204  std::string uidString = tid.GetName();
1205  uint32_t uidStringSize = uidString.size();
1206  buffer = AddToRawU32(uidStringSize, start, buffer, maxSize);
1207  if (buffer == nullptr)
1208  {
1209  return 0;
1210  }
1211  buffer = AddToRaw(reinterpret_cast<const uint8_t*>(uidString.c_str()),
1212  uidStringSize,
1213  start,
1214  buffer,
1215  maxSize);
1216  if (buffer == nullptr)
1217  {
1218  return 0;
1219  }
1220  }
1221  else
1222  {
1223  buffer = AddToRawU32(0, start, buffer, maxSize);
1224  if (buffer == nullptr)
1225  {
1226  return 0;
1227  }
1228  }
1229 
1230  uint8_t isBig = item.typeUid & 0x1;
1231  buffer = AddToRawU8(isBig, start, buffer, maxSize);
1232  if (buffer == nullptr)
1233  {
1234  return 0;
1235  }
1236 
1237  buffer = AddToRawU32(item.size, start, buffer, maxSize);
1238  if (buffer == nullptr)
1239  {
1240  return 0;
1241  }
1242 
1243  buffer = AddToRawU16(item.chunkUid, start, buffer, maxSize);
1244  if (buffer == nullptr)
1245  {
1246  return 0;
1247  }
1248 
1249  buffer = AddToRawU32(extraItem.fragmentStart, start, buffer, maxSize);
1250  if (buffer == nullptr)
1251  {
1252  return 0;
1253  }
1254 
1255  buffer = AddToRawU32(extraItem.fragmentEnd, start, buffer, maxSize);
1256  if (buffer == nullptr)
1257  {
1258  return 0;
1259  }
1260 
1261  buffer = AddToRawU64(extraItem.packetUid, start, buffer, maxSize);
1262  if (buffer == nullptr)
1263  {
1264  return 0;
1265  }
1266 
1267  if (current == m_tail)
1268  {
1269  break;
1270  }
1271 
1272  NS_ASSERT(current != item.next);
1273  current = item.next;
1274  }
1275 
1276  NS_ASSERT(static_cast<uint32_t>(buffer - start) == maxSize);
1277  return 1;
1278 }
1279 
1280 uint32_t
1281 PacketMetadata::Deserialize(const uint8_t* buffer, uint32_t size)
1282 {
1283  NS_LOG_FUNCTION(this << &buffer << size);
1284  const uint8_t* start = buffer;
1285  uint32_t desSize = size - 4;
1286 
1287  buffer = ReadFromRawU64(m_packetUid, start, buffer, size);
1288  desSize -= 8;
1289 
1290  struct PacketMetadata::SmallItem item = {0};
1291  struct PacketMetadata::ExtraItem extraItem = {0};
1292  while (desSize > 0)
1293  {
1294  uint32_t uidStringSize = 0;
1295  buffer = ReadFromRawU32(uidStringSize, start, buffer, size);
1296  desSize -= 4;
1297  uint32_t uid;
1298  if (uidStringSize == 0)
1299  {
1300  // uid zero for payload.
1301  uid = 0;
1302  }
1303  else
1304  {
1305  std::string uidString;
1306  for (uint32_t j = 0; j < uidStringSize; j++)
1307  {
1308  uint8_t ch = 0;
1309  buffer = ReadFromRawU8(ch, start, buffer, size);
1310  uidString.push_back(ch);
1311  desSize--;
1312  }
1313  TypeId tid = TypeId::LookupByName(uidString);
1314  uid = tid.GetUid();
1315  }
1316  uint8_t isBig = 0;
1317  buffer = ReadFromRawU8(isBig, start, buffer, size);
1318  desSize--;
1319  item.typeUid = (uid << 1) | isBig;
1320  buffer = ReadFromRawU32(item.size, start, buffer, size);
1321  desSize -= 4;
1322  buffer = ReadFromRawU16(item.chunkUid, start, buffer, size);
1323  desSize -= 2;
1324  buffer = ReadFromRawU32(extraItem.fragmentStart, start, buffer, size);
1325  desSize -= 4;
1326  buffer = ReadFromRawU32(extraItem.fragmentEnd, start, buffer, size);
1327  desSize -= 4;
1328  buffer = ReadFromRawU64(extraItem.packetUid, start, buffer, size);
1329  desSize -= 8;
1330  NS_LOG_LOGIC("size=" << size << ", typeUid=" << item.typeUid << ", size=" << item.size
1331  << ", chunkUid=" << item.chunkUid << ", fragmentStart="
1332  << extraItem.fragmentStart << ", fragmentEnd=" << extraItem.fragmentEnd
1333  << ", packetUid=" << extraItem.packetUid);
1334  uint32_t tmp = AddBig(0xffff, m_tail, &item, &extraItem);
1335  UpdateTail(tmp);
1336  }
1337  NS_ASSERT(desSize == 0);
1338  return (desSize != 0) ? 0 : 1;
1339 }
1340 
1341 uint8_t*
1342 PacketMetadata::AddToRawU8(const uint8_t& data, uint8_t* start, uint8_t* current, uint32_t maxSize)
1343 {
1344  NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1345  // First check buffer overflow
1346  if (static_cast<uint32_t>((current + sizeof(uint8_t) - start)) > maxSize)
1347  {
1348  return nullptr;
1349  }
1350  memcpy(current, &data, sizeof(uint8_t));
1351  return current + sizeof(uint8_t);
1352 }
1353 
1354 uint8_t*
1356  uint8_t* start,
1357  uint8_t* current,
1358  uint32_t maxSize)
1359 {
1360  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1361  // First check buffer overflow
1362  if (static_cast<uint32_t>((current + sizeof(uint16_t) - start)) > maxSize)
1363  {
1364  return nullptr;
1365  }
1366  memcpy(current, &data, sizeof(uint16_t));
1367  return current + sizeof(uint16_t);
1368 }
1369 
1370 uint8_t*
1372  uint8_t* start,
1373  uint8_t* current,
1374  uint32_t maxSize)
1375 {
1376  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1377  // First check buffer overflow
1378  if (static_cast<uint32_t>((current + sizeof(uint32_t) - start)) > maxSize)
1379  {
1380  return nullptr;
1381  }
1382  memcpy(current, &data, sizeof(uint32_t));
1383  return current + sizeof(uint32_t);
1384 }
1385 
1386 uint8_t*
1388  uint8_t* start,
1389  uint8_t* current,
1390  uint32_t maxSize)
1391 {
1392  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1393  // First check buffer overflow
1394  if (static_cast<uint32_t>((current + sizeof(uint64_t) - start)) > maxSize)
1395  {
1396  return nullptr;
1397  }
1398  memcpy(current, &data, sizeof(uint64_t));
1399  return current + sizeof(uint64_t);
1400 }
1401 
1402 uint8_t*
1404  uint32_t dataSize,
1405  uint8_t* start,
1406  uint8_t* current,
1407  uint32_t maxSize)
1408 {
1409  NS_LOG_FUNCTION(&data << dataSize << &start << &current << maxSize);
1410  // First check buffer overflow
1411  if (static_cast<uint32_t>((current + dataSize - start)) > maxSize)
1412  {
1413  return nullptr;
1414  }
1415  memcpy(current, data, dataSize);
1416  return current + dataSize;
1417 }
1418 
1419 uint8_t*
1421  const uint8_t* start,
1422  const uint8_t* current,
1423  uint32_t maxSize)
1424 {
1425  NS_LOG_FUNCTION(static_cast<uint32_t>(data) << &start << &current << maxSize);
1426  // First check buffer underflow
1427  if (static_cast<uint32_t>((current + sizeof(uint8_t) - start)) > maxSize)
1428  {
1429  return nullptr;
1430  }
1431  memcpy(&data, current, sizeof(uint8_t));
1432  return const_cast<uint8_t*>(current) + sizeof(uint8_t);
1433 }
1434 
1435 uint8_t*
1437  const uint8_t* start,
1438  const uint8_t* current,
1439  uint32_t maxSize)
1440 {
1441  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1442  // First check buffer underflow
1443  if (static_cast<uint32_t>((current + sizeof(uint16_t) - start)) > maxSize)
1444  {
1445  return nullptr;
1446  }
1447  memcpy(&data, current, sizeof(uint16_t));
1448  return const_cast<uint8_t*>(current) + sizeof(uint16_t);
1449 }
1450 
1451 uint8_t*
1453  const uint8_t* start,
1454  const uint8_t* current,
1455  uint32_t maxSize)
1456 {
1457  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1458  // First check buffer underflow
1459  if (static_cast<uint32_t>((current + sizeof(uint32_t) - start)) > maxSize)
1460  {
1461  return nullptr;
1462  }
1463  memcpy(&data, current, sizeof(uint32_t));
1464  return const_cast<uint8_t*>(current) + sizeof(uint32_t);
1465 }
1466 
1467 uint8_t*
1469  const uint8_t* start,
1470  const uint8_t* current,
1471  uint32_t maxSize)
1472 {
1473  NS_LOG_FUNCTION(data << &start << &current << maxSize);
1474  // First check buffer underflow
1475  if ((uint32_t)((current + sizeof(uint64_t) - start)) > maxSize)
1476  {
1477  return nullptr;
1478  }
1479  memcpy(&data, current, sizeof(uint64_t));
1480  return const_cast<uint8_t*>(current) + sizeof(uint64_t);
1481 }
1482 
1483 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:43
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.
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.
void ReserveCopy(uint32_t n)
Reserve space and make a metadata copy.
void AddHeader(const Header &header, uint32_t size)
Add an header.
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.
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 Deallocate(struct PacketMetadata::Data *data)
Deallocate 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 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 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.
uint32_t ReadItems(uint16_t current, struct PacketMetadata::SmallItem *item, struct PacketMetadata::ExtraItem *extraItem) const
Read items.
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 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.
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.
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.
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.
uint16_t m_used
used portion
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:60
bool IsChildOf(TypeId other) const
Check if this TypeId is a child of another.
Definition: type-id.cc:975
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:839
void SetUid(uint16_t uid)
Set the internal id of this TypeId.
Definition: type-id.cc:1216
uint16_t GetUid() const
Get the internal id of this TypeId.
Definition: type-id.cc:1209
std::string GetName() const
Get the name.
Definition: type-id.cc:995
#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.
value
Definition: second.py:41
#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
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
ItemType type
metadata type
TypeId tid
TypeId of Header or Trailer.
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.
uint32_t prev