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