276 namespace ns3 { |
281 namespace ns3 { |
277 |
282 |
278 bool PacketHistory::m_enable = false; |
283 bool PacketHistory::m_enable = false; |
279 uint32_t PacketHistory::m_maxSize = 0; |
284 uint32_t PacketHistory::m_maxSize = 0; |
280 PacketHistory::DataFreeList PacketHistory::m_freeList; |
285 PacketHistory::DataFreeList PacketHistory::m_freeList; |
|
286 uint32_t g_nAllocs = 0; |
|
287 uint32_t g_nDeAllocs = 0; |
|
288 uint32_t g_nRecycle = 0; |
|
289 uint32_t g_nCreate = 0; |
|
290 uint32_t g_one = 0; |
|
291 uint32_t g_two = 0; |
|
292 uint32_t g_three = 0; |
|
293 uint32_t g_four = 0; |
|
294 uint32_t g_five = 0; |
|
295 |
|
296 void |
|
297 PacketHistory::PrintStats (void) |
|
298 { |
|
299 std::cout << "allocs="<<g_nAllocs<<", deallocs="<<g_nDeAllocs |
|
300 <<", recycle="<<g_nRecycle<<", create="<<g_nCreate<<std::endl; |
|
301 std::cout << "one="<<g_one<<", two="<<g_two<<", three="<<g_three<<std::endl; |
|
302 //std::cout << "four="<<g_four<<", five="<<g_five<<std::endl; |
|
303 g_nAllocs = 0; |
|
304 g_nDeAllocs = 0; |
|
305 g_nRecycle = 0; |
|
306 g_nCreate = 0; |
|
307 g_one = 0; |
|
308 g_two = 0; |
|
309 g_three = 0; |
|
310 g_four = 0; |
|
311 g_five = 0; |
|
312 #if 0 |
|
313 PacketHistory h (0, 0); |
|
314 for (uint32_t i = 0; i < 0xffffff; i++) |
|
315 { |
|
316 if (h.GetUleb128Size (i) == 4) |
|
317 { |
|
318 std::cout << i << std::endl; |
|
319 break; |
|
320 } |
|
321 } |
|
322 #endif |
|
323 } |
281 |
324 |
282 void |
325 void |
283 PacketHistory::Enable (void) |
326 PacketHistory::Enable (void) |
284 { |
327 { |
285 m_enable = true; |
328 m_enable = true; |
286 } |
329 } |
287 |
|
288 |
|
289 PacketHistory::PacketHistory () |
|
290 : m_data (0), |
|
291 m_end (0), |
|
292 m_n (0), |
|
293 m_aggregated (false) |
|
294 { |
|
295 Construct (0, 0); |
|
296 } |
|
297 PacketHistory::PacketHistory (uint32_t uid, uint32_t size) |
|
298 : m_data (0), |
|
299 m_end (0), |
|
300 m_n (0), |
|
301 m_aggregated (false) |
|
302 { |
|
303 Construct (uid, size); |
|
304 } |
|
305 void |
|
306 PacketHistory::Construct (uint32_t uid, uint32_t size) |
|
307 { |
|
308 if (m_enable) |
|
309 { |
|
310 m_data = PacketHistory::Create (size); |
|
311 AppendOneCommand (PacketHistory::INIT, |
|
312 size, uid); |
|
313 } |
|
314 } |
|
315 PacketHistory::PacketHistory (PacketHistory const &o) |
|
316 : m_data (o.m_data), |
|
317 m_end (o.m_end), |
|
318 m_n (o.m_n), |
|
319 m_aggregated (o.m_aggregated) |
|
320 { |
|
321 if (m_data != 0) |
|
322 { |
|
323 m_data->m_count++; |
|
324 } |
|
325 } |
|
326 PacketHistory & |
|
327 PacketHistory::operator = (PacketHistory const& o) |
|
328 { |
|
329 if (m_data == o.m_data) |
|
330 { |
|
331 // self assignment |
|
332 return *this; |
|
333 } |
|
334 if (m_data != 0) |
|
335 { |
|
336 m_data->m_count--; |
|
337 if (m_data->m_count == 0) |
|
338 { |
|
339 PacketHistory::Recycle (m_data); |
|
340 } |
|
341 } |
|
342 m_data = o.m_data; |
|
343 m_end = o.m_end; |
|
344 m_n = o.m_n; |
|
345 m_aggregated = o.m_aggregated; |
|
346 if (m_data != 0) |
|
347 { |
|
348 m_data->m_count++; |
|
349 } |
|
350 return *this; |
|
351 } |
|
352 PacketHistory::~PacketHistory () |
|
353 { |
|
354 if (m_data != 0) |
|
355 { |
|
356 m_data->m_count--; |
|
357 if (m_data->m_count == 0) |
|
358 { |
|
359 PacketHistory::Recycle (m_data); |
|
360 } |
|
361 } |
|
362 } |
|
363 |
|
364 |
330 |
365 struct PacketHistory::CommandData * |
331 struct PacketHistory::CommandData * |
366 PacketHistory::Create (uint32_t size) |
332 PacketHistory::Create (uint32_t size) |
367 { |
333 { |
|
334 g_nCreate++; |
|
335 NS_DEBUG ("create size="<<size<<", max="<<m_maxSize); |
368 if (size > m_maxSize) |
336 if (size > m_maxSize) |
369 { |
337 { |
370 m_maxSize = size; |
338 m_maxSize = size; |
371 } |
339 } |
372 while (!m_freeList.empty ()) |
340 while (!m_freeList.empty ()) |
373 { |
341 { |
374 struct PacketHistory::CommandData *data = m_freeList.back (); |
342 struct PacketHistory::CommandData *data = m_freeList.back (); |
375 m_freeList.pop_back (); |
343 m_freeList.pop_back (); |
376 if (data->m_size >= size) |
344 if (data->m_size >= size) |
377 { |
345 { |
|
346 NS_DEBUG ("create found size="<<data->m_size); |
378 data->m_count = 1; |
347 data->m_count = 1; |
379 return data; |
348 return data; |
380 } |
349 } |
381 PacketHistory::Deallocate (data); |
350 PacketHistory::Deallocate (data); |
382 } |
351 NS_DEBUG ("create dealloc size="<<data->m_size); |
383 return PacketHistory::Allocate (size); |
352 } |
|
353 NS_DEBUG ("create alloc size="<<m_maxSize); |
|
354 return PacketHistory::Allocate (m_maxSize); |
384 } |
355 } |
385 |
356 |
386 void |
357 void |
387 PacketHistory::Recycle (struct CommandData *data) |
358 PacketHistory::Recycle (struct CommandData *data) |
388 { |
359 { |
|
360 g_nRecycle++; |
|
361 NS_DEBUG ("recycle size="<<data->m_size<<", list="<<m_freeList.size ()); |
389 NS_ASSERT (data->m_count == 0); |
362 NS_ASSERT (data->m_count == 0); |
390 if (m_freeList.size () > 1000 || |
363 if (m_freeList.size () > 1000 || |
391 data->m_size < m_maxSize) |
364 data->m_size < m_maxSize) |
392 { |
365 { |
393 PacketHistory::Deallocate (data); |
366 PacketHistory::Deallocate (data); |
414 return data; |
388 return data; |
415 } |
389 } |
416 void |
390 void |
417 PacketHistory::Deallocate (struct CommandData *data) |
391 PacketHistory::Deallocate (struct CommandData *data) |
418 { |
392 { |
|
393 g_nDeAllocs++; |
419 uint8_t *buf = (uint8_t *)data; |
394 uint8_t *buf = (uint8_t *)data; |
420 delete [] buf; |
395 delete [] buf; |
421 } |
396 } |
422 |
397 |
423 void |
398 bool |
424 PacketHistory::AppendOneCommand (uint32_t type, uint32_t data0, uint32_t data1) |
399 PacketHistory::TryToAppendSmallValue (uint32_t value, uint8_t **buffer) |
425 { |
400 { |
426 NS_ASSERT (m_data != 0); |
401 uint8_t *start = *buffer; |
427 uint32_t n = GetUleb128Size (type); |
402 uint8_t *end = &m_data->m_data[m_data->m_size]; |
428 n += GetUleb128Size (data0); |
403 if (value < 0x80 && start < end) |
429 n += GetUleb128Size (data1); |
404 { |
430 |
405 start[0] = value; |
431 if (m_data->m_size > m_end + n) |
406 *buffer = start + 1; |
432 { |
407 return true; |
433 if (m_data->m_count == 1 || |
408 } |
434 m_data->m_dirtyEnd == m_end) |
409 if (value < 0x4000 && start + 1 < end) |
435 { |
410 { |
436 AppendValue (type); |
411 uint8_t byte = value & (~0x80); |
437 AppendValue (data0); |
412 start[0] = 0x80 | byte; |
438 AppendValue (data1); |
413 value >>= 7; |
439 m_n++; |
414 start[1] = value; |
440 return; |
415 *buffer = start + 2; |
441 } |
416 return true; |
442 else |
417 } |
443 { |
418 return false; |
444 uint8_t *buffer = &(m_data->m_data[m_end]); |
419 } |
445 uint32_t lastType = ReadForwardValue (&buffer); |
420 bool |
446 if (lastType == type) |
421 PacketHistory::TryToAppendValue (uint32_t value, uint8_t **buffer) |
447 { |
422 { |
448 uint32_t lastData = ReadForwardValue (&buffer); |
423 uint8_t *start = *buffer; |
449 if (lastData == data0) |
424 uint8_t *end = &m_data->m_data[m_data->m_size]; |
450 { |
425 if (value < 0x80 && start < end) |
451 lastData = ReadForwardValue (&buffer); |
426 { |
452 if (lastData == data1) |
427 start[0] = value; |
453 { |
428 *buffer = start + 1; |
454 return; |
429 return true; |
455 } |
430 } |
456 } |
431 if (value < 0x4000 && start + 1 < end) |
457 } |
432 { |
458 } |
433 uint8_t byte = value & (~0x80); |
459 } |
434 start[0] = 0x80 | byte; |
460 Reserve (n); |
435 value >>= 7; |
461 AppendValue (type); |
436 start[1] = value; |
462 AppendValue (data0); |
437 *buffer = start + 2; |
463 AppendValue (data1); |
438 return true; |
464 m_n++; |
439 } |
465 } |
440 if (value < 0x200000 && start + 2 < end) |
466 |
441 { |
467 void |
442 uint8_t byte = value & (~0x80); |
468 PacketHistory::AppendOneCommand (uint32_t type, uint32_t data) |
443 start[0] = 0x80 | byte; |
469 { |
444 value >>= 7; |
470 NS_ASSERT (m_data != 0); |
445 start[1] = 0x80 | byte; |
471 uint32_t n = GetUleb128Size (data); |
446 value >>= 7; |
472 n += GetUleb128Size (type); |
447 start[2] = value; |
473 |
448 *buffer = start + 3; |
474 if (m_data->m_size > m_end + n) |
449 return true; |
475 { |
450 } |
476 if (m_data->m_count == 1 || |
451 if (start + 3 < end) |
477 m_data->m_dirtyEnd == m_end) |
452 { |
478 { |
453 uint8_t byte = value & (~0x80); |
479 AppendValue (type); |
454 start[0] = 0x80 | byte; |
480 AppendValue (data); |
455 value >>= 7; |
481 m_n++; |
456 start[1] = 0x80 | byte; |
482 return; |
457 value >>= 7; |
483 } |
458 start[2] = 0x80 | byte; |
484 else |
459 value >>= 7; |
485 { |
460 start[3] = value; |
486 uint8_t *buffer = &(m_data->m_data[m_end]); |
461 *buffer = start + 4; |
487 uint32_t lastType = ReadForwardValue (&buffer); |
462 return true; |
488 if (lastType == type) |
463 } |
489 { |
464 return false; |
490 uint32_t lastData = ReadForwardValue (&buffer); |
465 #if 0 |
491 if (lastData == data) |
466 // more generic version of the above. |
492 { |
467 do { |
493 return; |
468 uint8_t byte = value & (~0x80); |
494 } |
469 value >>= 7; |
495 } |
470 if (value != 0) |
496 } |
471 { |
497 } |
472 /* more bytes to come */ |
498 Reserve (n); |
473 byte |= 0x80; |
499 AppendValue (type); |
474 } |
500 AppendValue (data); |
475 *current = byte; |
501 m_n++; |
476 current++; |
502 } |
477 } while (value != 0 && current != end); |
503 void |
478 if (value != 0 && current == end) |
504 PacketHistory::ReserveCopy (uint32_t size) |
479 { |
505 { |
480 return false; |
506 struct CommandData *newData = PacketHistory::Create (m_end + size); |
481 } |
507 memcpy (newData->m_data, m_data->m_data, m_end); |
482 *buffer = current; |
508 newData->m_dirtyEnd = m_end; |
483 return true; |
509 m_data->m_count--; |
484 #endif |
510 if (m_data->m_count == 0) |
|
511 { |
|
512 PacketHistory::Recycle (m_data); |
|
513 } |
|
514 m_data = newData; |
|
515 } |
|
516 void |
|
517 PacketHistory::Reserve (uint32_t size) |
|
518 { |
|
519 NS_ASSERT (m_data != 0); |
|
520 if (m_data->m_size > m_end + size && |
|
521 (m_data->m_count == 1 || |
|
522 m_data->m_dirtyEnd == m_end)) |
|
523 { |
|
524 /* enough room, not dirty. */ |
|
525 } |
|
526 else |
|
527 { |
|
528 /* (enough room and dirty) or (not enough room) */ |
|
529 ReserveCopy (size); |
|
530 } |
|
531 } |
485 } |
532 |
486 |
533 uint32_t |
487 uint32_t |
534 PacketHistory::GetUleb128Size (uint32_t value) const |
488 PacketHistory::GetUleb128Size (uint32_t value) const |
535 { |
489 { |
607 * ie: the last (5th) byte did not have the high-order bit zeroed. |
543 * ie: the last (5th) byte did not have the high-order bit zeroed. |
608 */ |
544 */ |
609 result = 0xffffffff; |
545 result = 0xffffffff; |
610 } |
546 } |
611 return result; |
547 return result; |
|
548 #else |
|
549 uint32_t *start = (uint32_t *)buffer; |
|
550 *n = *n + 4; |
|
551 return *start; |
|
552 #endif |
|
553 } |
|
554 |
|
555 |
|
556 void |
|
557 PacketHistory::AppendOneCommand (uint32_t type, uint32_t data0, uint32_t data1) |
|
558 { |
|
559 NS_ASSERT (m_data != 0); |
|
560 #ifdef USE_ULEB |
|
561 if (m_data->m_count == 1 || |
|
562 m_data->m_dirtyEnd == m_end) |
|
563 { |
|
564 uint8_t *start = &m_data->m_data[m_end]; |
|
565 uint8_t *current = start; |
|
566 if (TryToAppendSmallValue (type, ¤t) && |
|
567 TryToAppendSmallValue (data0, ¤t) && |
|
568 TryToAppendValue (data1, ¤t)) |
|
569 { |
|
570 uintptr_t written = current - start; |
|
571 m_end += written; |
|
572 m_data->m_dirtyEnd = m_end; |
|
573 m_n++; |
|
574 g_one++; |
|
575 return; |
|
576 } |
|
577 } |
|
578 |
|
579 g_two++; |
|
580 uint32_t n = GetUleb128Size (type); |
|
581 n += GetUleb128Size (data0); |
|
582 n += GetUleb128Size (data1); |
|
583 Reserve (n); |
|
584 AppendValue (type); |
|
585 AppendValue (data0); |
|
586 AppendValue (data1); |
|
587 m_n++; |
|
588 |
|
589 #else |
|
590 restart: |
|
591 if (m_data->m_count == 1 || |
|
592 m_data->m_dirtyEnd == m_end) |
|
593 { |
|
594 uint32_t *start = (uint32_t *)&m_data->m_data[m_end]; |
|
595 uint32_t *end = (uint32_t *)&m_data->m_data[m_data->m_size]; |
|
596 if (start + 2 < end) |
|
597 { |
|
598 start[0] = type; |
|
599 start[1] = data0; |
|
600 start[2] = data1; |
|
601 m_end += 12; |
|
602 m_data->m_dirtyEnd = m_end; |
|
603 m_n++; |
|
604 g_one++; |
|
605 return; |
|
606 } |
|
607 } |
|
608 g_two++; |
|
609 Reserve (12); |
|
610 goto restart; |
|
611 #endif |
|
612 } |
|
613 |
|
614 void |
|
615 PacketHistory::AppendOneCommand (uint32_t type, uint32_t data) |
|
616 { |
|
617 NS_ASSERT (m_data != 0); |
|
618 #ifdef USE_ULEB |
|
619 if (m_data->m_count == 1 || |
|
620 m_data->m_dirtyEnd == m_end) |
|
621 { |
|
622 uint8_t *start = &m_data->m_data[m_end]; |
|
623 uint8_t *current = start; |
|
624 if (TryToAppendSmallValue (type, ¤t) && |
|
625 TryToAppendSmallValue (data, ¤t)) |
|
626 { |
|
627 uintptr_t written = current - start; |
|
628 m_end += written; |
|
629 m_data->m_dirtyEnd = m_end; |
|
630 m_n++; |
|
631 g_one++; |
|
632 return; |
|
633 } |
|
634 } |
|
635 |
|
636 g_two++; |
|
637 uint32_t n = GetUleb128Size (data); |
|
638 n += GetUleb128Size (type); |
|
639 Reserve (n); |
|
640 AppendValue (type); |
|
641 AppendValue (data); |
|
642 m_n++; |
|
643 #else |
|
644 restart: |
|
645 if (m_data->m_count == 1 || |
|
646 m_data->m_dirtyEnd == m_end) |
|
647 { |
|
648 uint32_t *start = (uint32_t *)&m_data->m_data[m_end]; |
|
649 uint32_t *end = (uint32_t *)&m_data->m_data[m_data->m_size]; |
|
650 if (start + 1 < end) |
|
651 { |
|
652 start[0] = type; |
|
653 start[1] = data; |
|
654 m_end += 8; |
|
655 m_data->m_dirtyEnd = m_end; |
|
656 m_n++; |
|
657 g_one++; |
|
658 return; |
|
659 } |
|
660 } |
|
661 g_two++; |
|
662 Reserve (8); |
|
663 goto restart; |
|
664 #endif |
|
665 } |
|
666 void |
|
667 PacketHistory::ReserveCopy (uint32_t size) |
|
668 { |
|
669 struct CommandData *newData = PacketHistory::Create (m_end + size); |
|
670 memcpy (newData->m_data, m_data->m_data, m_end); |
|
671 newData->m_dirtyEnd = m_end; |
|
672 m_data->m_count--; |
|
673 if (m_data->m_count == 0) |
|
674 { |
|
675 PacketHistory::Recycle (m_data); |
|
676 } |
|
677 m_data = newData; |
|
678 } |
|
679 void |
|
680 PacketHistory::Reserve (uint32_t size) |
|
681 { |
|
682 NS_ASSERT (m_data != 0); |
|
683 if (m_data->m_size >= m_end + size && |
|
684 (m_data->m_count == 1 || |
|
685 m_data->m_dirtyEnd == m_end)) |
|
686 { |
|
687 /* enough room, not dirty. */ |
|
688 g_four++; |
|
689 } |
|
690 else |
|
691 { |
|
692 /* (enough room and dirty) or (not enough room) */ |
|
693 ReserveCopy (size); |
|
694 g_five++; |
|
695 } |
612 } |
696 } |
613 |
697 |
614 uint32_t |
698 uint32_t |
615 PacketHistory::ReadForwardValue (uint8_t **pBuffer) const |
699 PacketHistory::ReadForwardValue (uint8_t **pBuffer) const |
616 { |
700 { |