00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <utility>
00021 #include <list>
00022 #include "ns3/assert.h"
00023 #include "ns3/fatal-error.h"
00024 #include "ns3/log.h"
00025 #include "packet-metadata.h"
00026 #include "buffer.h"
00027 #include "header.h"
00028 #include "trailer.h"
00029
00030 NS_LOG_COMPONENT_DEFINE ("PacketMetadata");
00031
00032 namespace ns3 {
00033
00034 bool PacketMetadata::m_enable = false;
00035 bool PacketMetadata::m_enableChecking = false;
00036 bool PacketMetadata::m_metadataSkipped = false;
00037 uint32_t PacketMetadata::m_maxSize = 0;
00038 uint16_t PacketMetadata::m_chunkUid = 0;
00039 PacketMetadata::DataFreeList PacketMetadata::m_freeList;
00040
00041 PacketMetadata::DataFreeList::~DataFreeList ()
00042 {
00043 for (iterator i = begin (); i != end (); i++)
00044 {
00045 PacketMetadata::Deallocate (*i);
00046 }
00047 PacketMetadata::m_enable = false;
00048 }
00049
00050 void
00051 PacketMetadata::Enable (void)
00052 {
00053 NS_ASSERT_MSG (!m_metadataSkipped,
00054 "Error: attempting to enable the packet metadata "
00055 "subsystem too late in the simulation, which is not allowed.\n"
00056 "A common cause for this problem is to enable ASCII tracing "
00057 "after sending any packets. One way to fix this problem is "
00058 "to call ns3::PacketMetadata::Enable () near the beginning of"
00059 " the program, before any packets are sent.");
00060 m_enable = true;
00061 }
00062
00063 void
00064 PacketMetadata::EnableChecking (void)
00065 {
00066 Enable ();
00067 m_enableChecking = true;
00068 }
00069
00070 void
00071 PacketMetadata::ReserveCopy (uint32_t size)
00072 {
00073 struct PacketMetadata::Data *newData = PacketMetadata::Create (m_used + size);
00074 memcpy (newData->m_data, m_data->m_data, m_used);
00075 newData->m_dirtyEnd = m_used;
00076 m_data->m_count--;
00077 if (m_data->m_count == 0)
00078 {
00079 PacketMetadata::Recycle (m_data);
00080 }
00081 m_data = newData;
00082 if (m_head != 0xffff)
00083 {
00084 uint8_t *start;
00085 NS_ASSERT (m_tail != 0xffff);
00086
00087 start = &m_data->m_data[m_tail];
00088 Append16 (0xffff, start);
00089
00090 start = &m_data->m_data[m_head] + 2;
00091 Append16 (0xffff, start);
00092 }
00093 }
00094 void
00095 PacketMetadata::Reserve (uint32_t size)
00096 {
00097 NS_ASSERT (m_data != 0);
00098 if (m_data->m_size >= m_used + size &&
00099 (m_head == 0xffff ||
00100 m_data->m_count == 1 ||
00101 m_data->m_dirtyEnd == m_used))
00102 {
00103
00104 }
00105 else
00106 {
00107
00108 ReserveCopy (size);
00109 }
00110 }
00111
00112 uint32_t
00113 PacketMetadata::GetUleb128Size (uint32_t value) const
00114 {
00115 if (value < 0x80)
00116 {
00117 return 1;
00118 }
00119 if (value < 0x4000)
00120 {
00121 return 2;
00122 }
00123 if (value < 0x200000)
00124 {
00125 return 3;
00126 }
00127 if (value < 0x10000000)
00128 {
00129 return 4;
00130 }
00131 return 5;
00132 }
00133 uint32_t
00134 PacketMetadata::ReadUleb128 (const uint8_t **pBuffer) const
00135 {
00136 const uint8_t *buffer = *pBuffer;
00137 uint32_t result = 0;
00138 uint8_t byte;
00139 result = 0;
00140 byte = buffer[0];
00141 result = (byte & (~0x80));
00142 if (!(byte & 0x80))
00143 {
00144 *pBuffer = buffer + 1;
00145 return result;
00146 }
00147 byte = buffer[1];
00148 result |= (byte & (~0x80)) << 7;
00149 if (!(byte & 0x80))
00150 {
00151 *pBuffer = buffer + 2;
00152 return result;
00153 }
00154 byte = buffer[2];
00155 result |= (byte & (~0x80)) << 14;
00156 if (!(byte & 0x80))
00157 {
00158 *pBuffer = buffer + 3;
00159 return result;
00160 }
00161 byte = buffer[3];
00162 result |= (byte & (~0x80)) << 21;
00163 if (!(byte & 0x80))
00164 {
00165 *pBuffer = buffer + 4;
00166 return result;
00167 }
00168 byte = buffer[4];
00169 result |= (byte & (~0x80)) << 28;
00170 if (!(byte & 0x80))
00171 {
00172 *pBuffer = buffer + 5;
00173 return result;
00174 }
00175
00176
00177
00178 NS_ASSERT (false);
00179 return 0;
00180 }
00181
00182 void
00183 PacketMetadata::Append16 (uint16_t value, uint8_t *buffer)
00184 {
00185 buffer[0] = value & 0xff;
00186 value >>= 8;
00187 buffer[1] = value;
00188 }
00189 void
00190 PacketMetadata::Append32 (uint32_t value, uint8_t *buffer)
00191 {
00192 buffer[0] = value & 0xff;
00193 buffer[1] = (value >> 8) & 0xff;
00194 buffer[2] = (value >> 16) & 0xff;
00195 buffer[3] = (value >> 24) & 0xff;
00196 }
00197
00198 void
00199 PacketMetadata::AppendValueExtra (uint32_t value, uint8_t *buffer)
00200 {
00201 if (value < 0x200000)
00202 {
00203 uint8_t byte = value & (~0x80);
00204 buffer[0] = 0x80 | byte;
00205 value >>= 7;
00206 byte = value & (~0x80);
00207 buffer[1] = 0x80 | byte;
00208 value >>= 7;
00209 byte = value & (~0x80);
00210 buffer[2] = value;
00211 return;
00212 }
00213 if (value < 0x10000000)
00214 {
00215 uint8_t byte = value & (~0x80);
00216 buffer[0] = 0x80 | byte;
00217 value >>= 7;
00218 byte = value & (~0x80);
00219 buffer[1] = 0x80 | byte;
00220 value >>= 7;
00221 byte = value & (~0x80);
00222 buffer[2] = 0x80 | byte;
00223 value >>= 7;
00224 buffer[3] = value;
00225 return;
00226 }
00227 {
00228 uint8_t byte = value & (~0x80);
00229 buffer[0] = 0x80 | byte;
00230 value >>= 7;
00231 byte = value & (~0x80);
00232 buffer[1] = 0x80 | byte;
00233 value >>= 7;
00234 byte = value & (~0x80);
00235 buffer[2] = 0x80 | byte;
00236 value >>= 7;
00237 byte = value & (~0x80);
00238 buffer[3] = 0x80 | byte;
00239 value >>= 7;
00240 buffer[4] = value;
00241 }
00242 }
00243
00244 void
00245 PacketMetadata::AppendValue (uint32_t value, uint8_t *buffer)
00246 {
00247 if (value < 0x80)
00248 {
00249 buffer[0] = value;
00250 return;
00251 }
00252 if (value < 0x4000)
00253 {
00254 uint8_t byte = value & (~0x80);
00255 buffer[0] = 0x80 | byte;
00256 value >>= 7;
00257 buffer[1] = value;
00258 return;
00259 }
00260 AppendValueExtra (value, buffer);
00261 }
00262
00263 void
00264 PacketMetadata::UpdateTail (uint16_t written)
00265 {
00266 NS_LOG_FUNCTION (this << written);
00267 if (m_head == 0xffff)
00268 {
00269 NS_ASSERT (m_tail == 0xffff);
00270 m_head = m_used;
00271 m_tail = m_used;
00272 }
00273 else
00274 {
00275 NS_ASSERT (m_tail != 0xffff);
00276
00277 uint8_t *previousTail = &m_data->m_data[m_tail];
00278 Append16 (m_used, previousTail);
00279
00280 m_tail = m_used;
00281 }
00282 NS_ASSERT (m_tail != 0xffff);
00283 NS_ASSERT (m_head != 0xffff);
00284 NS_ASSERT (written >= 8);
00285 m_used += written;
00286 m_data->m_dirtyEnd = m_used;
00287 }
00288
00289
00290 void
00291 PacketMetadata::UpdateHead (uint16_t written)
00292 {
00293 NS_LOG_FUNCTION (this << written);
00294 if (m_head == 0xffff)
00295 {
00296 NS_ASSERT (m_tail == 0xffff);
00297 m_head = m_used;
00298 m_tail = m_used;
00299 }
00300 else
00301 {
00302 NS_ASSERT (m_head != 0xffff);
00303
00304 uint8_t *previousHead = &m_data->m_data[m_head + 2];
00305 Append16 (m_used, previousHead);
00306
00307 m_head = m_used;
00308 }
00309 NS_ASSERT (m_tail != 0xffff);
00310 NS_ASSERT (m_head != 0xffff);
00311 NS_ASSERT (written >= 8);
00312 m_used += written;
00313 m_data->m_dirtyEnd = m_used;
00314 }
00315
00316 uint16_t
00317 PacketMetadata::AddSmall (const struct PacketMetadata::SmallItem *item)
00318 {
00319 NS_LOG_FUNCTION (this << item->next << item->prev << item->typeUid << item->size << item->chunkUid);
00320 NS_ASSERT (m_data != 0);
00321 NS_ASSERT (m_used != item->prev && m_used != item->next);
00322 uint32_t typeUidSize = GetUleb128Size (item->typeUid);
00323 uint32_t sizeSize = GetUleb128Size (item->size);
00324 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2;
00325 if (m_used + n > m_data->m_size ||
00326 (m_head != 0xffff &&
00327 m_data->m_count != 1 &&
00328 m_used != m_data->m_dirtyEnd))
00329 {
00330 ReserveCopy (n);
00331 }
00332 uint8_t *buffer = &m_data->m_data[m_used];
00333 Append16 (item->next, buffer);
00334 buffer += 2;
00335 Append16 (item->prev, buffer);
00336 buffer += 2;
00337 AppendValue (item->typeUid, buffer);
00338 buffer += typeUidSize;
00339 AppendValue (item->size, buffer);
00340 buffer += sizeSize;
00341 Append16 (item->chunkUid, buffer);
00342 return n;
00343 }
00344
00345 uint16_t
00346 PacketMetadata::AddBig (uint32_t next, uint32_t prev,
00347 const PacketMetadata::SmallItem *item,
00348 const PacketMetadata::ExtraItem *extraItem)
00349 {
00350 NS_LOG_FUNCTION (this << next << prev <<
00351 item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
00352 extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid);
00353 NS_ASSERT (m_data != 0);
00354 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1)?item->typeUid:item->typeUid+1;
00355 NS_ASSERT (m_used != prev && m_used != next);
00356
00357 uint32_t typeUidSize = GetUleb128Size (typeUid);
00358 uint32_t sizeSize = GetUleb128Size (item->size);
00359 uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
00360 uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
00361 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
00362
00363 if (m_used + n > m_data->m_size ||
00364 (m_head != 0xffff &&
00365 m_data->m_count != 1 &&
00366 m_used != m_data->m_dirtyEnd))
00367 {
00368 ReserveCopy (n);
00369 }
00370
00371 uint8_t *buffer = &m_data->m_data[m_used];
00372
00373 Append16 (next, buffer);
00374 buffer += 2;
00375 Append16 (prev, buffer);
00376 buffer += 2;
00377 AppendValue (typeUid, buffer);
00378 buffer += typeUidSize;
00379 AppendValue (item->size, buffer);
00380 buffer += sizeSize;
00381 Append16 (item->chunkUid, buffer);
00382 buffer += 2;
00383 AppendValue (extraItem->fragmentStart, buffer);
00384 buffer += fragStartSize;
00385 AppendValue (extraItem->fragmentEnd, buffer);
00386 buffer += fragEndSize;
00387 Append32 (extraItem->packetUid, buffer);
00388
00389 return n;
00390 }
00391
00392
00393
00394
00395
00396
00397
00398 void
00399 PacketMetadata::ReplaceTail (PacketMetadata::SmallItem *item,
00400 PacketMetadata::ExtraItem *extraItem,
00401 uint32_t available)
00402 {
00403 NS_LOG_FUNCTION (this <<
00404 item->next << item->prev << item->typeUid << item->size << item->chunkUid <<
00405 extraItem->fragmentStart << extraItem->fragmentEnd << extraItem->packetUid <<
00406 available);
00407
00408 NS_ASSERT (m_data != 0);
00409
00410
00411
00412
00413
00414 if (m_tail + available == m_used &&
00415 m_used == m_data->m_dirtyEnd)
00416 {
00417 available = m_data->m_size - m_tail;
00418 }
00419
00420 uint32_t typeUid = ((item->typeUid & 0x1) == 0x1)?item->typeUid:item->typeUid+1;
00421 uint32_t typeUidSize = GetUleb128Size (typeUid);
00422 uint32_t sizeSize = GetUleb128Size (item->size);
00423 uint32_t fragStartSize = GetUleb128Size (extraItem->fragmentStart);
00424 uint32_t fragEndSize = GetUleb128Size (extraItem->fragmentEnd);
00425 uint32_t n = 2 + 2 + typeUidSize + sizeSize + 2 + fragStartSize + fragEndSize + 4;
00426
00427 if (available >= n &&
00428 m_data->m_count == 1)
00429 {
00430 uint8_t *buffer = &m_data->m_data[m_tail];
00431 Append16 (item->next, buffer);
00432 buffer += 2;
00433 Append16 (item->prev, buffer);
00434 buffer += 2;
00435 AppendValue (typeUid, buffer);
00436 buffer += typeUidSize;
00437 AppendValue (item->size, buffer);
00438 buffer += sizeSize;
00439 Append16 (item->chunkUid, buffer);
00440 buffer += 2;
00441 AppendValue (extraItem->fragmentStart, buffer);
00442 buffer += fragStartSize;
00443 AppendValue (extraItem->fragmentEnd, buffer);
00444 buffer += fragEndSize;
00445 Append32 (extraItem->packetUid, buffer);
00446 m_used = buffer - &m_data->m_data[0];
00447 m_data->m_dirtyEnd = m_used;
00448 return;
00449 }
00450
00451
00452
00453
00454
00455
00456 PacketMetadata h (m_packetUid, 0);
00457 uint16_t current = m_head;
00458 while (current != 0xffff && current != m_tail)
00459 {
00460 struct PacketMetadata::SmallItem tmpItem;
00461 PacketMetadata::ExtraItem tmpExtraItem;
00462 ReadItems (current, &tmpItem, &tmpExtraItem);
00463 uint16_t written = h.AddBig (0xffff, h.m_tail,
00464 &tmpItem, &tmpExtraItem);
00465 h.UpdateTail (written);
00466 current = tmpItem.next;
00467 }
00468
00469 uint16_t written = h.AddBig (0xffff, h.m_tail, item, extraItem);
00470 h.UpdateTail (written);
00471
00472 *this = h;
00473 }
00474
00475
00476
00477
00478
00479
00480
00481 uint32_t
00482 PacketMetadata::ReadItems (uint16_t current,
00483 struct PacketMetadata::SmallItem *item,
00484 struct PacketMetadata::ExtraItem *extraItem) const
00485 {
00486 NS_LOG_FUNCTION (this << current);
00487 const uint8_t *buffer = &m_data->m_data[current];
00488 item->next = buffer[0];
00489 item->next |= (buffer[1]) << 8;
00490 item->prev = buffer[2];
00491 item->prev |= (buffer[3]) << 8;
00492 buffer += 4;
00493 item->typeUid = ReadUleb128 (&buffer);
00494 item->size = ReadUleb128 (&buffer);
00495 item->chunkUid = buffer[0];
00496 item->chunkUid |= (buffer[1]) << 8;
00497 buffer += 2;
00498
00499 bool isExtra = (item->typeUid & 0x1) == 0x1;
00500 if (isExtra)
00501 {
00502 extraItem->fragmentStart = ReadUleb128 (&buffer);
00503 extraItem->fragmentEnd = ReadUleb128 (&buffer);
00504 extraItem->packetUid = buffer[0];
00505 extraItem->packetUid |= buffer[1] << 8;
00506 extraItem->packetUid |= buffer[2] << 16;
00507 extraItem->packetUid |= buffer[3] << 24;
00508 buffer += 4;
00509 }
00510 else
00511 {
00512 extraItem->fragmentStart = 0;
00513 extraItem->fragmentEnd = item->size;
00514 extraItem->packetUid = m_packetUid;
00515 }
00516 NS_ASSERT (buffer <= &m_data->m_data[m_data->m_size]);
00517 return buffer - &m_data->m_data[current];
00518 }
00519
00520 struct PacketMetadata::Data *
00521 PacketMetadata::Create (uint32_t size)
00522 {
00523 NS_LOG_LOGIC ("create size="<<size<<", max="<<m_maxSize);
00524 if (size > m_maxSize)
00525 {
00526 m_maxSize = size;
00527 }
00528 while (!m_freeList.empty ())
00529 {
00530 struct PacketMetadata::Data *data = m_freeList.back ();
00531 m_freeList.pop_back ();
00532 if (data->m_size >= size)
00533 {
00534 NS_LOG_LOGIC ("create found size="<<data->m_size);
00535 data->m_count = 1;
00536 return data;
00537 }
00538 PacketMetadata::Deallocate (data);
00539 NS_LOG_LOGIC ("create dealloc size="<<data->m_size);
00540 }
00541 NS_LOG_LOGIC ("create alloc size="<<m_maxSize);
00542 return PacketMetadata::Allocate (m_maxSize);
00543 }
00544
00545 void
00546 PacketMetadata::Recycle (struct PacketMetadata::Data *data)
00547 {
00548 if (!m_enable)
00549 {
00550 PacketMetadata::Deallocate (data);
00551 return;
00552 }
00553 NS_LOG_LOGIC ("recycle size="<<data->m_size<<", list="<<m_freeList.size ());
00554 NS_ASSERT (data->m_count == 0);
00555 if (m_freeList.size () > 1000 ||
00556 data->m_size < m_maxSize)
00557 {
00558 PacketMetadata::Deallocate (data);
00559 }
00560 else
00561 {
00562 m_freeList.push_back (data);
00563 }
00564 }
00565
00566 struct PacketMetadata::Data *
00567 PacketMetadata::Allocate (uint32_t n)
00568 {
00569 uint32_t size = sizeof (struct Data);
00570 if (n <= 10)
00571 {
00572 n = 10;
00573 }
00574 size += n - 10;
00575 uint8_t *buf = new uint8_t [size];
00576 struct PacketMetadata::Data *data = (struct PacketMetadata::Data *)buf;
00577 data->m_size = n;
00578 data->m_count = 1;
00579 data->m_dirtyEnd = 0;
00580 return data;
00581 }
00582 void
00583 PacketMetadata::Deallocate (struct PacketMetadata::Data *data)
00584 {
00585 uint8_t *buf = (uint8_t *)data;
00586 delete [] buf;
00587 }
00588
00589
00590 PacketMetadata
00591 PacketMetadata::CreateFragment (uint32_t start, uint32_t end) const
00592 {
00593 PacketMetadata fragment = *this;
00594 fragment.RemoveAtStart (start);
00595 fragment.RemoveAtEnd (end);
00596 return fragment;
00597 }
00598
00599 void
00600 PacketMetadata::AddHeader (const Header &header, uint32_t size)
00601 {
00602 uint32_t uid = header.GetInstanceTypeId ().GetUid () << 1;
00603 DoAddHeader (uid, size);
00604 }
00605 void
00606 PacketMetadata::DoAddHeader (uint32_t uid, uint32_t size)
00607 {
00608 NS_LOG_FUNCTION (this << uid << size);
00609 if (!m_enable)
00610 {
00611 m_metadataSkipped = true;
00612 return;
00613 }
00614
00615 struct PacketMetadata::SmallItem item;
00616 item.next = m_head;
00617 item.prev = 0xffff;
00618 item.typeUid = uid;
00619 item.size = size;
00620 item.chunkUid = m_chunkUid;
00621 m_chunkUid++;
00622 uint16_t written = AddSmall (&item);
00623 UpdateHead (written);
00624 }
00625 void
00626 PacketMetadata::RemoveHeader (const Header &header, uint32_t size)
00627 {
00628 uint32_t uid = header.GetInstanceTypeId ().GetUid () << 1;
00629 NS_LOG_FUNCTION (this << uid << size);
00630 if (!m_enable)
00631 {
00632 m_metadataSkipped = true;
00633 return;
00634 }
00635 struct PacketMetadata::SmallItem item;
00636 struct PacketMetadata::ExtraItem extraItem;
00637 uint32_t read = ReadItems (m_head, &item, &extraItem);
00638 if ((item.typeUid & 0xfffffffe) != uid ||
00639 item.size != size)
00640 {
00641 if (m_enableChecking)
00642 {
00643 NS_FATAL_ERROR ("Removing unexpected header.");
00644 }
00645 return;
00646 }
00647 else if (item.typeUid != uid &&
00648 (extraItem.fragmentStart != 0 ||
00649 extraItem.fragmentEnd != size))
00650 {
00651 if (m_enableChecking)
00652 {
00653 NS_FATAL_ERROR ("Removing incomplete header.");
00654 }
00655 return;
00656 }
00657 if (m_head + read == m_used)
00658 {
00659 m_used = m_head;
00660 }
00661 if (m_head == m_tail)
00662 {
00663 m_head = 0xffff;
00664 m_tail = 0xffff;
00665 }
00666 else
00667 {
00668 m_head = item.next;
00669 }
00670 }
00671 void
00672 PacketMetadata::AddTrailer (const Trailer &trailer, uint32_t size)
00673 {
00674 uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
00675 NS_LOG_FUNCTION (this << uid << size);
00676 if (!m_enable)
00677 {
00678 m_metadataSkipped = true;
00679 return;
00680 }
00681 struct PacketMetadata::SmallItem item;
00682 item.next = 0xffff;
00683 item.prev = m_tail;
00684 item.typeUid = uid;
00685 item.size = size;
00686 item.chunkUid = m_chunkUid;
00687 m_chunkUid++;
00688 uint16_t written = AddSmall (&item);
00689 UpdateTail (written);
00690 }
00691 void
00692 PacketMetadata::RemoveTrailer (const Trailer &trailer, uint32_t size)
00693 {
00694 uint32_t uid = trailer.GetInstanceTypeId ().GetUid () << 1;
00695 NS_LOG_FUNCTION (this << uid << size);
00696 if (!m_enable)
00697 {
00698 m_metadataSkipped = true;
00699 return;
00700 }
00701 struct PacketMetadata::SmallItem item;
00702 struct PacketMetadata::ExtraItem extraItem;
00703 uint32_t read = ReadItems (m_tail, &item, &extraItem);
00704 if ((item.typeUid & 0xfffffffe) != uid ||
00705 item.size != size)
00706 {
00707 if (m_enableChecking)
00708 {
00709 NS_FATAL_ERROR ("Removing unexpected trailer.");
00710 }
00711 return;
00712 }
00713 else if (item.typeUid != uid &&
00714 (extraItem.fragmentStart != 0 ||
00715 extraItem.fragmentEnd != size))
00716 {
00717 if (m_enableChecking)
00718 {
00719 NS_FATAL_ERROR ("Removing incomplete trailer.");
00720 }
00721 return;
00722 }
00723 if (m_tail + read == m_used)
00724 {
00725 m_used = m_tail;
00726 }
00727 if (m_head == m_tail)
00728 {
00729 m_head = 0xffff;
00730 m_tail = 0xffff;
00731 }
00732 else
00733 {
00734 m_tail = item.prev;
00735 }
00736 }
00737 void
00738 PacketMetadata::AddAtEnd (PacketMetadata const&o)
00739 {
00740 NS_LOG_FUNCTION (this << &o);
00741 if (!m_enable)
00742 {
00743 m_metadataSkipped = true;
00744 return;
00745 }
00746 if (m_tail == 0xffff)
00747 {
00748
00749
00750 *this = o;
00751 return;
00752 }
00753 if (o.m_head == 0xffff)
00754 {
00755 NS_ASSERT (o.m_tail == 0xffff);
00756
00757 return;
00758 }
00759 NS_ASSERT (m_head != 0xffff && m_tail != 0xffff);
00760
00761
00762
00763 struct PacketMetadata::SmallItem tailItem;
00764 PacketMetadata::ExtraItem tailExtraItem;
00765 uint32_t tailSize = ReadItems (m_tail, &tailItem, &tailExtraItem);
00766
00767 uint16_t current;
00768 struct PacketMetadata::SmallItem item;
00769 PacketMetadata::ExtraItem extraItem;
00770 o.ReadItems (o.m_head, &item, &extraItem);
00771 if (extraItem.packetUid == tailExtraItem.packetUid &&
00772 item.typeUid == tailItem.typeUid &&
00773 item.chunkUid == tailItem.chunkUid &&
00774 item.size == tailItem.size &&
00775 extraItem.fragmentStart == tailExtraItem.fragmentEnd)
00776 {
00777
00778
00779
00780
00781
00782 tailExtraItem.fragmentEnd = extraItem.fragmentEnd;
00783 ReplaceTail (&tailItem, &tailExtraItem, tailSize);
00784 current = item.next;
00785 }
00786 else
00787 {
00788 current = o.m_head;
00789 }
00790
00791
00792
00793
00794
00795 while (current != 0xffff)
00796 {
00797 o.ReadItems (current, &item, &extraItem);
00798 uint16_t written = AddBig (0xffff, m_tail, &item, &extraItem);
00799 UpdateTail (written);
00800 if (current == o.m_tail)
00801 {
00802 break;
00803 }
00804 current = item.next;
00805 }
00806 }
00807 void
00808 PacketMetadata::AddPaddingAtEnd (uint32_t end)
00809 {
00810 if (!m_enable)
00811 {
00812 m_metadataSkipped = true;
00813 return;
00814 }
00815 }
00816 void
00817 PacketMetadata::RemoveAtStart (uint32_t start)
00818 {
00819 NS_LOG_FUNCTION (this << start);
00820 if (!m_enable)
00821 {
00822 m_metadataSkipped = true;
00823 return;
00824 }
00825 NS_ASSERT (m_data != 0);
00826 uint32_t leftToRemove = start;
00827 uint16_t current = m_head;
00828 while (current != 0xffff && leftToRemove > 0)
00829 {
00830 struct PacketMetadata::SmallItem item;
00831 PacketMetadata::ExtraItem extraItem;
00832 ReadItems (current, &item, &extraItem);
00833 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
00834 if (itemRealSize <= leftToRemove)
00835 {
00836
00837 if (m_head == m_tail)
00838 {
00839 m_head = 0xffff;
00840 m_tail = 0xffff;
00841 }
00842 else
00843 {
00844 m_head = item.next;
00845 }
00846 leftToRemove -= itemRealSize;
00847 }
00848 else
00849 {
00850
00851 PacketMetadata fragment (m_packetUid, 0);
00852 extraItem.fragmentStart += leftToRemove;
00853 leftToRemove = 0;
00854 uint16_t written = fragment.AddBig (0xffff, fragment.m_tail,
00855 &item, &extraItem);
00856 fragment.UpdateTail (written);
00857 while (current != 0xffff && current != m_tail)
00858 {
00859 current = item.next;
00860 ReadItems (current, &item, &extraItem);
00861 written = fragment.AddBig (0xffff, fragment.m_tail,
00862 &item, &extraItem);
00863 fragment.UpdateTail (written);
00864 }
00865 *this = fragment;
00866 }
00867 NS_ASSERT (item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
00868 extraItem.fragmentStart <= extraItem.fragmentEnd);
00869 if (current == m_tail)
00870 {
00871 break;
00872 }
00873 current = item.next;
00874 }
00875 NS_ASSERT (leftToRemove == 0);
00876 }
00877 void
00878 PacketMetadata::RemoveAtEnd (uint32_t end)
00879 {
00880 NS_LOG_FUNCTION (this << end);
00881 if (!m_enable)
00882 {
00883 m_metadataSkipped = true;
00884 return;
00885 }
00886 NS_ASSERT (m_data != 0);
00887
00888 uint32_t leftToRemove = end;
00889 uint16_t current = m_tail;
00890 while (current != 0xffff && leftToRemove > 0)
00891 {
00892 struct PacketMetadata::SmallItem item;
00893 PacketMetadata::ExtraItem extraItem;
00894 ReadItems (current, &item, &extraItem);
00895 uint32_t itemRealSize = extraItem.fragmentEnd - extraItem.fragmentStart;
00896 if (itemRealSize <= leftToRemove)
00897 {
00898
00899 if (m_head == m_tail)
00900 {
00901 m_head = 0xffff;
00902 m_tail = 0xffff;
00903 }
00904 else
00905 {
00906 m_tail = item.prev;
00907 }
00908 leftToRemove -= itemRealSize;
00909 }
00910 else
00911 {
00912
00913 PacketMetadata fragment (m_packetUid, 0);
00914 NS_ASSERT (extraItem.fragmentEnd > leftToRemove);
00915 extraItem.fragmentEnd -= leftToRemove;
00916 leftToRemove = 0;
00917 uint16_t written = fragment.AddBig (fragment.m_head, 0xffff,
00918 &item, &extraItem);
00919 fragment.UpdateHead (written);
00920 while (current != 0xffff && current != m_head)
00921 {
00922 current = item.prev;
00923 ReadItems (current, &item, &extraItem);
00924 written = fragment.AddBig (fragment.m_head, 0xffff,
00925 &item, &extraItem);
00926 fragment.UpdateHead (written);
00927 }
00928 *this = fragment;
00929 }
00930 NS_ASSERT (item.size >= extraItem.fragmentEnd - extraItem.fragmentStart &&
00931 extraItem.fragmentStart <= extraItem.fragmentEnd);
00932 if (current == m_head)
00933 {
00934 break;
00935 }
00936 current = item.prev;
00937 }
00938 NS_ASSERT (leftToRemove == 0);
00939 }
00940 uint32_t
00941 PacketMetadata::GetTotalSize (void) const
00942 {
00943 uint32_t totalSize = 0;
00944 uint16_t current = m_head;
00945 uint16_t tail = m_tail;
00946 while (current != 0xffff)
00947 {
00948 struct PacketMetadata::SmallItem item;
00949 PacketMetadata::ExtraItem extraItem;
00950 ReadItems (current, &item, &extraItem);
00951 totalSize += extraItem.fragmentEnd - extraItem.fragmentStart;
00952 if (current == tail)
00953 {
00954 break;
00955 }
00956 NS_ASSERT (current != item.next);
00957 current = item.next;
00958 }
00959 return totalSize;
00960 }
00961
00962 uint32_t
00963 PacketMetadata::GetUid (void) const
00964 {
00965 return m_packetUid;
00966 }
00967 PacketMetadata::ItemIterator
00968 PacketMetadata::BeginItem (Buffer buffer) const
00969 {
00970 return ItemIterator (this, buffer);
00971 }
00972 PacketMetadata::ItemIterator::ItemIterator (const PacketMetadata *metadata, Buffer buffer)
00973 : m_metadata (metadata),
00974 m_buffer (buffer),
00975 m_current (metadata->m_head),
00976 m_offset (0),
00977 m_hasReadTail (false)
00978 {}
00979 bool
00980 PacketMetadata::ItemIterator::HasNext (void) const
00981 {
00982 if (m_current == 0xffff)
00983 {
00984 return false;
00985 }
00986 if (m_hasReadTail)
00987 {
00988 return false;
00989 }
00990 return true;
00991 }
00992 PacketMetadata::Item
00993 PacketMetadata::ItemIterator::Next (void)
00994 {
00995 struct PacketMetadata::Item item;
00996 struct PacketMetadata::SmallItem smallItem;
00997 struct PacketMetadata::ExtraItem extraItem;
00998 m_metadata->ReadItems (m_current, &smallItem, &extraItem);
00999 if (m_current == m_metadata->m_tail)
01000 {
01001 m_hasReadTail = true;
01002 }
01003 m_current = smallItem.next;
01004 uint32_t uid = (smallItem.typeUid & 0xfffffffe) >> 1;
01005 item.tid.SetUid (uid);
01006 item.currentTrimedFromStart = extraItem.fragmentStart;
01007 item.currentTrimedFromEnd = extraItem.fragmentEnd - smallItem.size;
01008 item.currentSize = extraItem.fragmentEnd - extraItem.fragmentStart;
01009 if (extraItem.fragmentStart != 0 || extraItem.fragmentEnd != smallItem.size)
01010 {
01011 item.isFragment = true;
01012 }
01013 else
01014 {
01015 item.isFragment = false;
01016 }
01017 TypeId tid;
01018 tid.SetUid (uid);
01019 if (uid == 0)
01020 {
01021 item.type = PacketMetadata::Item::PAYLOAD;
01022 }
01023 else if (tid.IsChildOf (Header::GetTypeId ()))
01024 {
01025 item.type = PacketMetadata::Item::HEADER;
01026 if (!item.isFragment)
01027 {
01028 ns3::Buffer tmp = m_buffer;
01029 tmp.RemoveAtStart (m_offset);
01030 tmp.RemoveAtEnd (tmp.GetSize () - item.currentSize);
01031 item.current = tmp.Begin ();
01032 }
01033 }
01034 else if (tid.IsChildOf (Trailer::GetTypeId ()))
01035 {
01036 item.type = PacketMetadata::Item::TRAILER;
01037 if (!item.isFragment)
01038 {
01039 ns3::Buffer tmp = m_buffer;
01040 tmp.RemoveAtEnd (tmp.GetSize () - (m_offset + smallItem.size));
01041 tmp.RemoveAtStart (tmp.GetSize () - item.currentSize);
01042 item.current = tmp.End ();
01043 }
01044 }
01045 else
01046 {
01047 NS_ASSERT (false);
01048 }
01049 m_offset += extraItem.fragmentEnd - extraItem.fragmentStart;
01050 return item;
01051 }
01052
01053 uint32_t
01054 PacketMetadata::GetSerializedSize (void) const
01055 {
01056 NS_LOG_FUNCTION (this);
01057 uint32_t totalSize = 0;
01058 totalSize += 4;
01059 if (!m_enable)
01060 {
01061 return totalSize;
01062 }
01063 struct PacketMetadata::SmallItem item;
01064 struct PacketMetadata::ExtraItem extraItem;
01065 uint32_t current = m_head;
01066 while (current != 0xffff)
01067 {
01068 ReadItems (current, &item, &extraItem);
01069 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
01070 if (uid == 0)
01071 {
01072 totalSize += 4;
01073 }
01074 else
01075 {
01076 TypeId tid;
01077 tid.SetUid (uid);
01078 totalSize += 4 + tid.GetName ().size ();
01079 }
01080 totalSize += 1 + 4 + 2 + 4 + 4 + 4;
01081 if (current == m_tail)
01082 {
01083 break;
01084 }
01085 NS_ASSERT (current != item.next);
01086 current = item.next;
01087 }
01088 return totalSize;
01089 }
01090 void
01091 PacketMetadata::Serialize (Buffer::Iterator i, uint32_t size) const
01092 {
01093 NS_LOG_FUNCTION (this);
01094 uint32_t bytesWritten = 0;
01095 i.WriteU32 (size);
01096 bytesWritten += 4;
01097 struct PacketMetadata::SmallItem item;
01098 struct PacketMetadata::ExtraItem extraItem;
01099 uint32_t current = m_head;
01100 while (current != 0xffff)
01101 {
01102 ReadItems (current, &item, &extraItem);
01103 NS_LOG_LOGIC ("bytesWritten=" << bytesWritten << ", typeUid="<<
01104 item.typeUid << ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
01105 ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
01106 extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
01107 uint32_t uid = (item.typeUid & 0xfffffffe) >> 1;
01108 if (uid != 0)
01109 {
01110 TypeId tid;
01111 tid.SetUid (uid);
01112 std::string uidString = tid.GetName ();
01113 i.WriteU32 (uidString.size ());
01114 bytesWritten += 4;
01115 i.Write ((uint8_t *)uidString.c_str (), uidString.size ());
01116 bytesWritten += uidString.size ();
01117 }
01118 else
01119 {
01120 i.WriteU32 (0);
01121 bytesWritten += 4;
01122 }
01123 uint8_t isBig = item.typeUid & 0x1;
01124 i.WriteU8 (isBig);
01125 bytesWritten += 1;
01126 i.WriteU32 (item.size);
01127 bytesWritten += 4;
01128 i.WriteU16 (item.chunkUid);
01129 bytesWritten += 2;
01130 i.WriteU32 (extraItem.fragmentStart);
01131 bytesWritten += 4;
01132 i.WriteU32 (extraItem.fragmentEnd);
01133 bytesWritten += 4;
01134 i.WriteU32 (extraItem.packetUid);
01135 bytesWritten += 4;
01136 if (current == m_tail)
01137 {
01138 break;
01139 }
01140
01141 NS_ASSERT (current != item.next);
01142 current = item.next;
01143 }
01144 NS_ASSERT (bytesWritten == size);
01145 }
01146 uint32_t
01147 PacketMetadata::Deserialize (Buffer::Iterator i)
01148 {
01149 NS_LOG_FUNCTION (this);
01150 struct PacketMetadata::SmallItem item;
01151 struct PacketMetadata::ExtraItem extraItem;
01152 uint32_t totalSize = i.ReadU32 ();
01153 uint32_t size = totalSize;
01154 size -= 4;
01155 while (size > 0)
01156 {
01157 uint32_t uidStringSize = i.ReadU32 ();
01158 size -= 4;
01159 uint32_t uid;
01160 if (uidStringSize == 0)
01161 {
01162
01163 uid = 0;
01164 }
01165 else
01166 {
01167 std::string uidString;
01168 for (uint32_t j = 0; j < uidStringSize; j++)
01169 {
01170 uidString.push_back (i.ReadU8 ());
01171 size --;
01172 }
01173 TypeId tid = TypeId::LookupByName (uidString);
01174 uid = tid.GetUid ();
01175 }
01176 uint8_t isBig = i.ReadU8 ();
01177 size --;
01178 item.typeUid = (uid << 1) | isBig;
01179 item.size = i.ReadU32 ();
01180 size -= 4;
01181 item.chunkUid = i.ReadU16 ();
01182 size -= 2;
01183 extraItem.fragmentStart = i.ReadU32 ();
01184 size -= 4;
01185 extraItem.fragmentEnd = i.ReadU32 ();
01186 size -= 4;
01187 extraItem.packetUid = i.ReadU32 ();
01188 size -= 4;
01189 NS_LOG_LOGIC ("size=" << size << ", typeUid="<<item.typeUid <<
01190 ", size="<<item.size<<", chunkUid="<<item.chunkUid<<
01191 ", fragmentStart="<<extraItem.fragmentStart<<", fragmentEnd="<<
01192 extraItem.fragmentEnd<< ", packetUid="<<extraItem.packetUid);
01193 uint32_t tmp = AddBig (0xffff, m_tail, &item, &extraItem);
01194 UpdateTail (tmp);
01195 }
01196 NS_ASSERT (size == 0);
01197 return totalSize;
01198 }
01199
01200
01201 }
01202