A Discrete-Event Network Simulator
API
packet-test-suite.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2005,2006 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 "ns3/packet.h"
21#include "ns3/packet-tag-list.h"
22#include "ns3/test.h"
23#include <limits> // std:numeric_limits
24#include <string>
25#include <cstdarg>
26#include <iostream>
27#include <iomanip>
28#include <ctime>
29
30using namespace ns3;
31
32//-----------------------------------------------------------------------------
33// Unit tests
34//-----------------------------------------------------------------------------
35namespace {
36
45class ATestTagBase : public Tag
46{
47public:
48 ATestTagBase () : m_error (false), m_data (0) {}
51 ATestTagBase (uint8_t data) : m_error (false), m_data (data) {}
56 static TypeId GetTypeId (void)
57 {
58 static TypeId tid = TypeId ("ATestTagBase")
59 .SetParent<Tag> ()
60 .SetGroupName ("Network")
61 .HideFromDocumentation ()
62 // No AddConstructor because this is an abstract class.
63 ;
64 return tid;
65 }
68 int GetData () const {
69 int result = (int)m_data;
70 return result;
71 }
72 bool m_error;
73 uint8_t m_data;
74};
75
84template <int N>
85class ATestTag : public ATestTagBase
86{
87public:
92 static TypeId GetTypeId (void) {
93 std::ostringstream oss;
94 oss << "anon::ATestTag<" << N << ">";
95 static TypeId tid = TypeId (oss.str ())
97 .SetGroupName ("Network")
98 .HideFromDocumentation ()
99 .AddConstructor<ATestTag<N> > ()
100 ;
101 return tid;
102 }
103 virtual TypeId GetInstanceTypeId (void) const {
104 return GetTypeId ();
105 }
106 virtual uint32_t GetSerializedSize (void) const {
107 return N + sizeof(m_data);
108 }
109 virtual void Serialize (TagBuffer buf) const {
110 buf.WriteU8 (m_data);
111 for (uint32_t i = 0; i < N; ++i)
112 {
113 buf.WriteU8 (N);
114 }
115 }
116 virtual void Deserialize (TagBuffer buf) {
117 m_data = buf.ReadU8 ();
118 for (uint32_t i = 0; i < N; ++i)
119 {
120 uint8_t v = buf.ReadU8 ();
121 if (v != N)
122 {
123 m_error = true;
124 }
125 }
126 }
127 virtual void Print (std::ostream &os) const {
128 os << N << "(" << m_data << ")";
129 }
131 : ATestTagBase () {}
134 ATestTag (uint8_t data)
135 : ATestTagBase (data) {}
136};
137
138// Previous versions of ns-3 limited the tag size to 20 bytes or less
139// static const uint8_t LARGE_TAG_BUFFER_SIZE = 64;
140#define LARGE_TAG_BUFFER_SIZE 64
141
152class ALargeTestTag : public Tag
153{
154public:
156 for (uint8_t i = 0; i < (LARGE_TAG_BUFFER_SIZE - 1); i++)
157 {
158 m_data.push_back (i);
159 }
160 m_size = LARGE_TAG_BUFFER_SIZE;
161 }
166 static TypeId GetTypeId (void)
167 {
168 static TypeId tid = TypeId ("ALargeTestTag")
169 .SetParent<Tag> ()
170 .SetGroupName ("Network")
171 .HideFromDocumentation ()
172 .AddConstructor<ALargeTestTag> ()
173 ;
174 return tid;
175 }
176 virtual TypeId GetInstanceTypeId (void) const {
177 return GetTypeId ();
178 }
179 virtual uint32_t GetSerializedSize (void) const {
180 return (uint32_t) m_size;
181 }
182 virtual void Serialize (TagBuffer buf) const {
183 buf.WriteU8 (m_size);
184 for (uint8_t i = 0; i < (m_size - 1); ++i)
185 {
186 buf.WriteU8 (m_data[i]);
187 }
188 }
189 virtual void Deserialize (TagBuffer buf) {
190 m_size = buf.ReadU8 ();
191 for (uint8_t i = 0; i < (m_size - 1); ++i)
192 {
193 uint8_t v = buf.ReadU8 ();
194 m_data.push_back (v);
195 }
196 }
197 virtual void Print (std::ostream &os) const {
198 os << "(" << (uint16_t) m_size << ")";
199 }
200private:
201 uint8_t m_size;
202 std::vector<uint8_t> m_data;
203};
204
214{
215public:
216 ATestHeaderBase () : Header (), m_error (false) {}
221 static TypeId GetTypeId (void)
222 {
223 static TypeId tid = TypeId ("ATestHeaderBase")
224 .SetParent<Header> ()
225 .SetGroupName ("Network")
226 .HideFromDocumentation ()
227 // No AddConstructor because this is an abstract class.
228 ;
229 return tid;
230 }
231 bool m_error;
232};
233
242template <int N>
244{
245public:
250 static TypeId GetTypeId (void) {
251 std::ostringstream oss;
252 oss << "anon::ATestHeader<" << N << ">";
253 static TypeId tid = TypeId (oss.str ())
255 .SetGroupName ("Network")
256 .HideFromDocumentation ()
257 .AddConstructor<ATestHeader<N> > ()
258 ;
259 return tid;
260 }
261 virtual TypeId GetInstanceTypeId (void) const {
262 return GetTypeId ();
263 }
264 virtual uint32_t GetSerializedSize (void) const {
265 return N;
266 }
267 virtual void Serialize (Buffer::Iterator iter) const {
268 for (uint32_t i = 0; i < N; ++i)
269 {
270 iter.WriteU8 (N);
271 }
272 }
274 for (uint32_t i = 0; i < N; ++i)
275 {
276 uint8_t v = iter.ReadU8 ();
277 if (v != N)
278 {
279 m_error = true;
280 }
281 }
282 return N;
283 }
284 virtual void Print (std::ostream &os) const {
285 }
287 : ATestHeaderBase () {}
288
289};
290
300{
301public:
302 ATestTrailerBase () : Trailer (), m_error (false) {}
307 static TypeId GetTypeId (void)
308 {
309 static TypeId tid = TypeId ("ATestTrailerBase")
310 .SetParent<Trailer> ()
311 .SetGroupName ("Network")
312 .HideFromDocumentation ()
313 // No AddConstructor because this is an abstract class.
314 ;
315 return tid;
316 }
317 bool m_error;
318};
319
328template <int N>
330{
331public:
336 static TypeId GetTypeId (void) {
337 std::ostringstream oss;
338 oss << "anon::ATestTrailer<" << N << ">";
339 static TypeId tid = TypeId (oss.str ())
341 .SetGroupName ("Network")
342 .HideFromDocumentation ()
343 .AddConstructor<ATestTrailer<N> > ()
344 ;
345 return tid;
346 }
347 virtual TypeId GetInstanceTypeId (void) const {
348 return GetTypeId ();
349 }
350 virtual uint32_t GetSerializedSize (void) const {
351 return N;
352 }
353 virtual void Serialize (Buffer::Iterator iter) const {
354 iter.Prev (N);
355 for (uint32_t i = 0; i < N; ++i)
356 {
357 iter.WriteU8 (N);
358 }
359 }
361 iter.Prev (N);
362 for (uint32_t i = 0; i < N; ++i)
363 {
364 uint8_t v = iter.ReadU8 ();
365 if (v != N)
366 {
367 m_error = true;
368 }
369 }
370 return N;
371 }
372 virtual void Print (std::ostream &os) const {
373 }
375 : ATestTrailerBase () {}
376
377};
378
388{
396 : n (n_), start (start_), end (end_), data(0) {}
397
405 Expected (uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
406 : n (n_), start (start_), end (end_), data(data_) {}
407
411 uint8_t data;
412};
413
414}
415
416// tag name, start, end
417#define E(name,start,end) name,start,end
418
419// tag name, start, end, data
420#define E_DATA(name,start,end,data) name,start,end,data
421
422// Check byte tags on a packet, checks name, start, end
423#define CHECK(p, n, ...) \
424 DoCheck (p, n, __VA_ARGS__)
425
426// Check byte tags on a packet, checks name, start, end, data
427#define CHECK_DATA(p, n, ...) \
428 DoCheckData (p, n, __VA_ARGS__)
429
436class PacketTest : public TestCase
437{
438public:
439 PacketTest ();
440 virtual void DoRun (void);
441private:
448 void DoCheck (Ptr<const Packet> p, uint32_t n, ...);
455 void DoCheckData (Ptr<const Packet> p, uint32_t n, ...);
456};
457
458
460 : TestCase ("Packet") {
461}
462
463void
465{
466 std::vector<struct Expected> expected;
467 va_list ap;
468 va_start (ap, n);
469 for (uint32_t k = 0; k < n; ++k)
470 {
471 uint32_t N = va_arg (ap, uint32_t);
472 uint32_t start = va_arg (ap, uint32_t);
473 uint32_t end = va_arg (ap, uint32_t);
474 expected.push_back (Expected (N, start, end));
475 }
476 va_end (ap);
477
479 uint32_t j = 0;
480 while (i.HasNext () && j < expected.size ())
481 {
482 ByteTagIterator::Item item = i.Next ();
483 struct Expected e = expected[j];
484 std::ostringstream oss;
485 oss << "anon::ATestTag<" << e.n << ">";
486 NS_TEST_EXPECT_MSG_EQ (item.GetTypeId ().GetName (), oss.str (), "trivial");
487 NS_TEST_EXPECT_MSG_EQ (item.GetStart (), e.start, "trivial");
488 NS_TEST_EXPECT_MSG_EQ (item.GetEnd (), e.end, "trivial");
489 ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
490 NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
491 item.GetTag (*tag);
492 NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
493 delete tag;
494 j++;
495 }
496 NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
497 NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
498}
499
500void
502{
503 std::vector<struct Expected> expected;
504 va_list ap;
505 va_start (ap, n);
506 for (uint32_t k = 0; k < n; ++k)
507 {
508 uint32_t N = va_arg (ap, uint32_t);
509 uint32_t start = va_arg (ap, uint32_t);
510 uint32_t end = va_arg (ap, uint32_t);
511 int data = va_arg (ap, int);
512 expected.push_back (Expected (N, start, end, data));
513 }
514 va_end (ap);
515
517 uint32_t j = 0;
518 while (i.HasNext () && j < expected.size ())
519 {
520 ByteTagIterator::Item item = i.Next ();
521 struct Expected e = expected[j];
522 std::ostringstream oss;
523 oss << "anon::ATestTag<" << e.n << ">";
524 NS_TEST_EXPECT_MSG_EQ (item.GetTypeId ().GetName (), oss.str (), "trivial");
525 NS_TEST_EXPECT_MSG_EQ (item.GetStart (), e.start, "trivial");
526 NS_TEST_EXPECT_MSG_EQ (item.GetEnd (), e.end, "trivial");
527 ATestTagBase *tag = dynamic_cast<ATestTagBase *> (item.GetTypeId ().GetConstructor () ());
528 NS_TEST_EXPECT_MSG_NE (tag, 0, "trivial");
529 item.GetTag (*tag);
530 NS_TEST_EXPECT_MSG_EQ (tag->m_error, false, "trivial");
531 NS_TEST_EXPECT_MSG_EQ (tag->GetData (), e.data, "trivial");
532 delete tag;
533 j++;
534 }
535 NS_TEST_EXPECT_MSG_EQ (i.HasNext (), false, "Nothing left");
536 NS_TEST_EXPECT_MSG_EQ (j, expected.size (), "Size match");
537}
538
539void
541{
542 Ptr<Packet> pkt1 = Create<Packet> (reinterpret_cast<const uint8_t*> ("hello"), 5);
543 Ptr<Packet> pkt2 = Create<Packet> (reinterpret_cast<const uint8_t*> (" world"), 6);
544 Ptr<Packet> packet = Create<Packet> ();
545 packet->AddAtEnd (pkt1);
546 packet->AddAtEnd (pkt2);
547
548 NS_TEST_EXPECT_MSG_EQ (packet->GetSize (), 11, "trivial");
549
550 uint8_t *buf = new uint8_t[packet->GetSize ()];
551 packet->CopyData (buf, packet->GetSize ());
552
553 std::string msg = std::string (reinterpret_cast<const char *>(buf),
554 packet->GetSize ());
555 delete [] buf;
556
557 NS_TEST_EXPECT_MSG_EQ (msg, "hello world", "trivial");
558
559
560 Ptr<const Packet> p = Create<Packet> (1000);
561
562 p->AddByteTag (ATestTag<1> ());
563 CHECK (p, 1, E (1, 0, 1000));
564 Ptr<const Packet> copy = p->Copy ();
565 CHECK (copy, 1, E (1, 0, 1000));
566
567 p->AddByteTag (ATestTag<2> ());
568 CHECK (p, 2, E (1, 0, 1000), E (2, 0, 1000));
569 CHECK (copy, 1, E (1, 0, 1000));
570
571 {
572 Packet c0 = *copy;
573 Packet c1 = *copy;
574 c0 = c1;
575 CHECK (&c0, 1, E (1, 0, 1000));
576 CHECK (&c1, 1, E (1, 0, 1000));
577 CHECK (copy, 1, E (1, 0, 1000));
578 c0.AddByteTag (ATestTag<10> ());
579 CHECK (&c0, 2, E (1, 0, 1000), E (10, 0, 1000));
580 CHECK (&c1, 1, E (1, 0, 1000));
581 CHECK (copy, 1, E (1, 0, 1000));
582 }
583
584 Ptr<Packet> frag0 = p->CreateFragment (0, 10);
585 Ptr<Packet> frag1 = p->CreateFragment (10, 90);
586 Ptr<const Packet> frag2 = p->CreateFragment (100, 900);
587 frag0->AddByteTag (ATestTag<3> ());
588 CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
589 frag1->AddByteTag (ATestTag<4> ());
590 CHECK (frag1, 3, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90));
591 frag2->AddByteTag (ATestTag<5> ());
592 CHECK (frag2, 3, E (1, 0, 900), E (2, 0, 900), E (5, 0, 900));
593
594 frag1->AddAtEnd (frag2);
595 CHECK (frag1, 6, E (1, 0, 90), E (2, 0, 90), E (4, 0, 90), E (1, 90, 990), E (2, 90, 990), E (5, 90, 990));
596
597 CHECK (frag0, 3, E (1, 0, 10), E (2, 0, 10), E (3, 0, 10));
598 frag0->AddAtEnd (frag1);
599 CHECK (frag0, 9,
600 E (1, 0, 10), E (2, 0, 10), E (3, 0, 10),
601 E (1, 10, 100), E (2, 10, 100), E (4, 10, 100),
602 E (1, 100, 1000), E (2, 100, 1000), E (5, 100, 1000));
603
604
605 // force caching a buffer of the right size.
606 frag0 = Create<Packet> (1000);
607 frag0->AddHeader (ATestHeader<10> ());
608 frag0 = 0;
609
610 p = Create<Packet> (1000);
611 p->AddByteTag (ATestTag<20> ());
612 CHECK (p, 1, E (20, 0, 1000));
613 frag0 = p->CreateFragment (10, 90);
614 CHECK (p, 1, E (20, 0, 1000));
615 CHECK (frag0, 1, E (20, 0, 90));
616 p = 0;
617 frag0->AddHeader (ATestHeader<10> ());
618 CHECK (frag0, 1, E (20, 10, 100));
619
620 {
621 Ptr<Packet> tmp = Create<Packet> (100);
622 tmp->AddByteTag (ATestTag<20> ());
623 CHECK (tmp, 1, E (20, 0, 100));
624 tmp->AddHeader (ATestHeader<10> ());
625 CHECK (tmp, 1, E (20, 10, 110));
626 ATestHeader<10> h;
627 tmp->RemoveHeader (h);
628 CHECK (tmp, 1, E (20, 0, 100));
629 tmp->AddHeader (ATestHeader<10> ());
630 CHECK (tmp, 1, E (20, 10, 110));
631
632 tmp = Create<Packet> (100);
633 tmp->AddByteTag (ATestTag<20> ());
634 CHECK (tmp, 1, E (20, 0, 100));
635 tmp->AddTrailer (ATestTrailer<10> ());
636 CHECK (tmp, 1, E (20, 0, 100));
637 ATestTrailer<10> t;
638 tmp->RemoveTrailer (t);
639 CHECK (tmp, 1, E (20, 0, 100));
640 tmp->AddTrailer (ATestTrailer<10> ());
641 CHECK (tmp, 1, E (20, 0, 100));
642
643 }
644
645 {
646 Ptr<Packet> tmp = Create<Packet> (0);
647 tmp->AddHeader (ATestHeader<156> ());
648 tmp->AddByteTag (ATestTag<20> ());
649 CHECK (tmp, 1, E (20, 0, 156));
650 tmp->RemoveAtStart (120);
651 CHECK (tmp, 1, E (20, 0, 36));
652 Ptr<Packet> a = Create<Packet> (0);
653 a->AddAtEnd (tmp);
654 CHECK (a, 1, E (20, 0, 36));
655 }
656
657 {
658 Ptr<Packet> tmp = Create<Packet> (0);
659 tmp->AddByteTag (ATestTag<20> ());
660 CHECK (tmp, 0, E (20, 0, 0));
661 }
662 {
663 Ptr<Packet> tmp = Create<Packet> (1000);
664 tmp->AddByteTag (ATestTag<20> ());
665 CHECK (tmp, 1, E (20, 0, 1000));
666 tmp->RemoveAtStart (1000);
667 CHECK (tmp, 0, E (0,0,0));
668 Ptr<Packet> a = Create<Packet> (10);
669 a->AddByteTag (ATestTag<10> ());
670 CHECK (a, 1, E (10, 0, 10));
671 tmp->AddAtEnd (a);
672 CHECK (tmp, 1, E (10, 0, 10));
673 }
674
675 {
676 Packet p;
677 ATestTag<10> a;
678 p.AddPacketTag (a);
679 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
680 ATestTag<11> b;
681 p.AddPacketTag (b);
682 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
683 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), true, "trivial");
684 Packet copy = p;
685 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
686 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
687 ATestTag<12> c;
688 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), false, "trivial");
689 copy.AddPacketTag (c);
690 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
691 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), true, "trivial");
692 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
693 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
694 copy.RemovePacketTag (b);
695 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (b), false, "trivial");
696 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), true, "trivial");
697 p.RemovePacketTag (a);
698 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (a), false, "trivial");
699 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (a), true, "trivial");
700 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (c), false, "trivial");
701 NS_TEST_EXPECT_MSG_EQ (copy.PeekPacketTag (c), true, "trivial");
703 NS_TEST_EXPECT_MSG_EQ (p.PeekPacketTag (b), false, "trivial");
704 }
705
706 /* Test Serialization and Deserialization of Packet with PacketTag data */
707 {
708 Ptr<Packet> p1 = Create<Packet> (1000);;
709 ATestTag<10> a1(65);
710 ATestTag<11> b1(66);
711 ATestTag<12> c1(67);
712
713 p1->AddPacketTag (a1);
714 p1->AddPacketTag (b1);
715 p1->AddPacketTag (c1);
716
717 uint32_t serializedSize = p1->GetSerializedSize ();
718 uint8_t* buffer = new uint8_t[serializedSize + 16];
719 p1->Serialize (buffer, serializedSize);
720
721 Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
722
723 delete [] buffer;
724
725 ATestTag<10> a2;
726 ATestTag<11> b2;
727 ATestTag<12> c2;
728
729 NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(a2), true, "trivial");
730 NS_TEST_EXPECT_MSG_EQ (a2.GetData (), 65, "trivial");
731 NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(b2), true, "trivial");
732 NS_TEST_EXPECT_MSG_EQ (b2.GetData (), 66, "trivial");
733 NS_TEST_EXPECT_MSG_EQ (p2 -> PeekPacketTag(c2), true, "trivial");
734 NS_TEST_EXPECT_MSG_EQ (c2.GetData (), 67, "trivial");
735 }
736
737 /* Test Serialization and Deserialization of Packet with ByteTag data */
738 {
739 Ptr<Packet> p1 = Create<Packet> (1000);;
740
741 ATestTag<10> a1(65);
742 ATestTag<11> b1(66);
743 ATestTag<12> c1(67);
744
745 p1->AddByteTag (a1);
746 p1->AddByteTag (b1);
747 p1->AddByteTag (c1);
748
749 CHECK (p1, 3, E (10, 0, 1000), E (11, 0, 1000), E (12, 0, 1000));
750
751 uint32_t serializedSize = p1->GetSerializedSize ();
752 uint8_t* buffer = new uint8_t[serializedSize];
753 p1->Serialize (buffer, serializedSize);
754
755 Ptr<Packet> p2 = Create<Packet> (buffer, serializedSize, true);
756
757 delete [] buffer;
758
759 CHECK_DATA (p2, 3, E_DATA (10, 0, 1000, 65), E_DATA (11, 0, 1000, 66), E_DATA (12, 0, 1000, 67));
760 }
761
762 {
765 Ptr<Packet> tmp = Create<Packet> (1000);
766 tmp->AddByteTag (ATestTag<20> ());
767 CHECK (tmp, 1, E (20, 0, 1000));
768 tmp->AddHeader (ATestHeader<2> ());
769 CHECK (tmp, 1, E (20, 2, 1002));
770 tmp->RemoveAtStart (1);
771 CHECK (tmp, 1, E (20, 1, 1001));
772#if 0
773 tmp->PeekData ();
774 CHECK (tmp, 1, E (20, 1, 1001));
775#endif
776 }
777
778 /* Test reducing tagged packet size and increasing it back. */
779 {
780 Ptr<Packet> tmp = Create<Packet> (0);
781 tmp->AddHeader (ATestHeader<100> ());
782 tmp->AddByteTag (ATestTag<25> ());
783 CHECK (tmp, 1, E (25, 0, 100));
784 tmp->RemoveAtStart (50);
785 CHECK (tmp, 1, E (25, 0, 50));
786 tmp->AddHeader (ATestHeader<50> ());
787 CHECK (tmp, 1, E (25, 50, 100));
788 }
789
790 /* Similar test case, but using trailer instead of header. */
791 {
792 Ptr<Packet> tmp = Create<Packet> (0);
793 tmp->AddTrailer (ATestTrailer<100> ());
794 tmp->AddByteTag (ATestTag<25> ());
795 CHECK (tmp, 1, E (25, 0, 100));
796 tmp->RemoveAtEnd (50);
797 CHECK (tmp, 1, E (25, 0, 50));
798 tmp->AddTrailer (ATestTrailer<50> ());
799 CHECK (tmp, 1, E (25, 0, 50));
800 }
801
802 /* Test reducing tagged packet size and increasing it by half. */
803 {
804 Ptr<Packet> tmp = Create<Packet> (0);
805 tmp->AddHeader (ATestHeader<100> ());
806 tmp->AddByteTag (ATestTag<25> ());
807 CHECK (tmp, 1, E (25, 0, 100));
808 tmp->RemoveAtStart (50);
809 CHECK (tmp, 1, E (25, 0, 50));
810 tmp->AddHeader (ATestHeader<25> ());
811 CHECK (tmp, 1, E (25, 25, 75));
812 }
813
814 /* Similar test case, but using trailer instead of header. */
815 {
816 Ptr<Packet> tmp = Create<Packet> (0);
817 tmp->AddTrailer (ATestTrailer<100> ());
818 tmp->AddByteTag (ATestTag<25> ());
819 CHECK (tmp, 1, E (25, 0, 100));
820 tmp->RemoveAtEnd (50);
821 CHECK (tmp, 1, E (25, 0, 50));
822 tmp->AddTrailer (ATestTrailer<25> ());
823 CHECK (tmp, 1, E (25, 0, 50));
824 }
825
826 /* Test AddPaddingAtEnd. */
827 {
828 Ptr<Packet> tmp = Create<Packet> (0);
829 tmp->AddTrailer (ATestTrailer<100> ());
830 tmp->AddByteTag (ATestTag<25> ());
831 CHECK (tmp, 1, E (25, 0, 100));
832 tmp->RemoveAtEnd (50);
833 CHECK (tmp, 1, E (25, 0, 50));
834 tmp->AddPaddingAtEnd (50);
835 CHECK (tmp, 1, E (25, 0, 50));
836 }
837
838 /* Test reducing tagged packet size and increasing it back,
839 * now using padding bytes to avoid triggering dirty state
840 * in virtual buffer
841 */
842 {
843 Ptr<Packet> tmp = Create<Packet> (100);
844 tmp->AddByteTag (ATestTag<25> ());
845 CHECK (tmp, 1, E (25, 0, 100));
846 tmp->RemoveAtEnd (50);
847 CHECK (tmp, 1, E (25, 0, 50));
848 tmp->AddPaddingAtEnd (50);
849 CHECK (tmp, 1, E (25, 0, 50));
850 }
851
852 /* Test ALargeTestTag */
853 {
854 Ptr<Packet> tmp = Create<Packet> (0);
855 ALargeTestTag a;
856 tmp->AddPacketTag (a);
857 }
858}
859
867{
868public:
870 virtual ~PacketTagListTest ();
871private:
872 void DoRun (void);
880 void CheckRef (const PacketTagList & ref,
881 ATestTagBase & t,
882 const char * msg,
883 bool miss = false);
890 void CheckRefList (const PacketTagList & ref,
891 const char * msg,
892 int miss = 0);
893
901 int RemoveTime (const PacketTagList & ref,
902 ATestTagBase & t,
903 const char * msg = 0);
904
910 int AddRemoveTime (const bool verbose = false);
911};
912
914 : TestCase ("PacketTagListTest: ")
915{
916}
917
919{
920}
921
922void
924 ATestTagBase & t,
925 const char * msg,
926 bool miss)
927{
928 int expect = t.GetData (); // the value we should find
929 bool found = ref.Peek (t); // rewrites t with actual value
930 NS_TEST_EXPECT_MSG_EQ (found, !miss,
931 msg << ": ref contains "
932 << t.GetTypeId ().GetName ());
933 if (found) {
934 NS_TEST_EXPECT_MSG_EQ (t.GetData (), expect,
935 msg << ": ref " << t.GetTypeId ().GetName ()
936 << " = " << expect);
937 }
938}
939
940 // A set of tags with data value 1, to check COW
941#define MAKE_TEST_TAGS \
942 ATestTag<1> t1 (1); \
943 ATestTag<2> t2 (1); \
944 ATestTag<3> t3 (1); \
945 ATestTag<4> t4 (1); \
946 ATestTag<5> t5 (1); \
947 ATestTag<6> t6 (1); \
948 ATestTag<7> t7 (1); \
949 [[maybe_unused]] const int tagLast = 7; /* length of ref PacketTagList */
950
951void
953 const char * msg,
954 int miss /* = 0 */)
955{
957 CheckRef (ptl, t1, msg, miss == 1);
958 CheckRef (ptl, t2, msg, miss == 2);
959 CheckRef (ptl, t3, msg, miss == 3);
960 CheckRef (ptl, t4, msg, miss == 4);
961 CheckRef (ptl, t5, msg, miss == 5);
962 CheckRef (ptl, t6, msg, miss == 6);
963 CheckRef (ptl, t7, msg, miss == 7);
964}
965
966int
968 ATestTagBase & t,
969 const char * msg /* = 0 */)
970{
971 const int reps = 10000;
972 std::vector< PacketTagList > ptv(reps, ref);
973 int start = clock ();
974 for (int i = 0; i < reps; ++i) {
975 ptv[i].Remove (t);
976 }
977 int stop = clock ();
978 int delta = stop - start;
979 if (msg) {
980 std::cout << GetName () << "remove time: " << msg << ": " << std::setw (8)
981 << delta << " ticks to remove "
982 << reps << " times"
983 << std::endl;
984 }
985 return delta;
986}
987
988int
990{
991 const int reps = 100000;
992 PacketTagList ptl;
993 ATestTag <2> t(2);
994 int start = clock ();
995 for (int i = 0; i < reps; ++i) {
996 ptl.Add (t);
997 ptl.Remove (t);
998 }
999 int stop = clock ();
1000 int delta = stop - start;
1001 if (verbose) {
1002 std::cout << GetName () << "add/remove time: " << std::setw (8)
1003 << delta << " ticks to add+remove "
1004 << reps << " times"
1005 << std::endl;
1006 }
1007 return delta;
1008}
1009
1010void
1012{
1013 std::cout << GetName () << "begin" << std::endl;
1014
1016
1017 PacketTagList ref; // empty list
1018 ref.Add (t1); // last
1019 ref.Add (t2); // post merge
1020 ref.Add (t3); // merge successor
1021 ref.Add (t4); // merge
1022 ref.Add (t5); // merge precursor
1023 ref.Add (t6); // pre-merge
1024 ref.Add (t7); // first
1025
1026 { // Peek
1027 std::cout << GetName () << "check Peek (missing tag) returns false"
1028 << std::endl;
1029 ATestTag<10> t10;
1030 NS_TEST_EXPECT_MSG_EQ (ref.Peek (t10), false, "missing tag");
1031 }
1032
1033 { // Copy ctor, assignment
1034 std::cout << GetName () << "check copy and assignment" << std::endl;
1035 { PacketTagList ptl (ref);
1036 CheckRefList (ref, "copy ctor orig");
1037 CheckRefList (ptl, "copy ctor copy");
1038 }
1039 { PacketTagList ptl = ref;
1040 CheckRefList (ref, "assignment orig");
1041 CheckRefList (ptl, "assignment copy");
1042 }
1043 }
1044
1045 { // Removal
1046# define RemoveCheck(n) \
1047 { PacketTagList p ## n = ref; \
1048 p ## n .Remove ( t ## n ); \
1049 CheckRefList (ref, "remove " #n " orig"); \
1050 CheckRefList (p ## n, "remove " #n " copy", n); \
1051 }
1052
1053 { // Remove single tags from list
1054 std::cout << GetName () << "check removal of each tag" << std::endl;
1055 RemoveCheck (1);
1056 RemoveCheck (2);
1057 RemoveCheck (3);
1058 RemoveCheck (4);
1059 RemoveCheck (5);
1060 RemoveCheck (6);
1061 RemoveCheck (7);
1062 }
1063
1064 { // Remove in the presence of a merge
1065 std::cout << GetName () << "check removal doesn't disturb merge "
1066 << std::endl;
1067 PacketTagList ptl = ref;
1068 ptl.Remove (t7);
1069 ptl.Remove (t6);
1070 ptl.Remove (t5);
1071
1072 PacketTagList mrg = ptl; // merged list
1073 ATestTag<8> m5 (1);
1074 mrg.Add (m5); // ptl and mrg differ
1075 ptl.Add (t5);
1076 ptl.Add (t6);
1077 ptl.Add (t7);
1078
1079 CheckRefList (ref, "post merge, orig");
1080 CheckRefList (ptl, "post merge, long chain");
1081 const char * msg = "post merge, short chain";
1082 CheckRef (mrg, t1, msg, false);
1083 CheckRef (mrg, t2, msg, false);
1084 CheckRef (mrg, t3, msg, false);
1085 CheckRef (mrg, t4, msg, false);
1086 CheckRef (mrg, m5, msg, false);
1087 }
1088# undef RemoveCheck
1089 } // Removal
1090
1091 { // Replace
1092
1093 std::cout << GetName () << "check replacing each tag" << std::endl;
1094
1095# define ReplaceCheck(n) \
1096 t ## n .m_data = 2; \
1097 { PacketTagList p ## n = ref; \
1098 p ## n .Replace ( t ## n ); \
1099 CheckRefList (ref, "replace " #n " orig"); \
1100 CheckRef (p ## n, t ## n, "replace " #n " copy"); \
1101 }
1102
1103 ReplaceCheck (1);
1104 ReplaceCheck (2);
1105 ReplaceCheck (3);
1106 ReplaceCheck (4);
1107 ReplaceCheck (5);
1108 ReplaceCheck (6);
1109 ReplaceCheck (7);
1110 }
1111
1112 { // Timing
1113 std::cout << GetName () << "add+remove timing" << std::endl;
1114 int flm = std::numeric_limits<int>::max ();
1115 const int nIterations = 100;
1116 for (int i = 0; i < nIterations; ++i) {
1117 int now = AddRemoveTime ();
1118 if (now < flm) flm = now;
1119 }
1120 std::cout << GetName () << "min add+remove time: "
1121 << std::setw (8) << flm << " ticks"
1122 << std::endl;
1123
1124 std::cout << GetName () << "remove timing" << std::endl;
1125 // tags numbered from 1, so add one for (unused) entry at 0
1126 std::vector <int> rmn (tagLast + 1, std::numeric_limits<int>::max ());
1127 for (int i = 0; i < nIterations; ++i) {
1128 for (int j = 1; j <= tagLast; ++j) {
1129 int now = 0;
1130 switch (j) {
1131 case 7: now = RemoveTime (ref, t7); break;
1132 case 6: now = RemoveTime (ref, t6); break;
1133 case 5: now = RemoveTime (ref, t5); break;
1134 case 4: now = RemoveTime (ref, t4); break;
1135 case 3: now = RemoveTime (ref, t3); break;
1136 case 2: now = RemoveTime (ref, t2); break;
1137 case 1: now = RemoveTime (ref, t1); break;
1138 } // switch
1139
1140 if (now < rmn[j]) rmn[j] = now;
1141 } // for tag j
1142 } // for iteration i
1143 for (int j = tagLast; j > 0; --j) {
1144 std::cout << GetName () << "min remove time: t"
1145 << j << ": "
1146 << std::setw (8) << rmn[j] << " ticks"
1147 << std::endl;
1148 }
1149 } // Timing
1150
1151}
1152
1160{
1161public:
1162 PacketTestSuite ();
1163};
1164
1166 : TestSuite ("packet", UNIT)
1167{
1168 AddTestCase (new PacketTest, TestCase::QUICK);
1169 AddTestCase (new PacketTagListTest, TestCase::QUICK);
1170}
1171
#define max(a, b)
Definition: 80211b.c:43
Packet Tag list unit tests.
void CheckRefList(const PacketTagList &ref, const char *msg, int miss=0)
Checks against a reference PacketTagList.
int AddRemoveTime(const bool verbose=false)
Prints the remove time.
void CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
Checks against a reference PacketTagList.
void DoRun(void)
Implementation to actually run this TestCase.
int RemoveTime(const PacketTagList &ref, ATestTagBase &t, const char *msg=0)
Prints the remove time.
Packet unit tests.
void DoCheckData(Ptr< const Packet > p, uint32_t n,...)
Checks the packet and its data.
virtual void DoRun(void)
Implementation to actually run this TestCase.
void DoCheck(Ptr< const Packet > p, uint32_t n,...)
Checks the packet.
Packet TestSuite.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual uint32_t Deserialize(Buffer::Iterator iter)
virtual void Serialize(Buffer::Iterator iter) const
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
static TypeId GetTypeId(void)
Register this type.
virtual TypeId GetInstanceTypeId(void) const
Get the most derived TypeId for this Object.
virtual void Serialize(Buffer::Iterator iter) const
virtual uint32_t Deserialize(Buffer::Iterator iter)
static TypeId GetTypeId(void)
Register this type.
iterator in a Buffer instance
Definition: buffer.h:99
void WriteU8(uint8_t data)
Definition: buffer.h:869
uint8_t ReadU8(void)
Definition: buffer.h:1021
void Prev(void)
go backward by one byte
Definition: buffer.h:851
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:62
uint32_t GetEnd(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:44
TypeId GetTypeId(void) const
Definition: packet.cc:34
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:49
uint32_t GetStart(void) const
The index is an offset from the start of the packet.
Definition: packet.cc:39
Iterator over the set of byte tags in a packet.
Definition: packet.h:55
bool HasNext(void) const
Definition: packet.cc:65
Item Next(void)
Definition: packet.cc:70
Protocol header serialization and deserialization.
Definition: header.h:43
network packets
Definition: packet.h:232
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:318
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
void RemoveAllPacketTags(void)
Remove all packet tags.
Definition: packet.cc:984
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:362
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialize a packet, tags, and metadata into a byte buffer.
Definition: packet.cc:638
ByteTagIterator GetByteTagIterator(void) const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:933
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Create a new packet which contains a fragment of the original packet.
Definition: packet.cc:227
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:912
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:307
void AddPaddingAtEnd(uint32_t size)
Add a zero-filled padding to the packet.
Definition: packet.cc:347
uint32_t GetSerializedSize(void) const
Returns number of bytes required for packet serialization.
Definition: packet.cc:585
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:978
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
List of the packet tags stored in a packet.
bool Remove(Tag &tag)
Remove (the first instance of) tag from the list.
bool Peek(Tag &tag) const
Find a tag and return its value.
void Add(Tag const &tag) const
Add a tag to the head of this branch.
read and write tag data
Definition: tag-buffer.h:52
TAG_BUFFER_INLINE void WriteU8(uint8_t v)
Definition: tag-buffer.h:172
TAG_BUFFER_INLINE uint8_t ReadU8(void)
Definition: tag-buffer.h:195
tag a set of bytes in a packet
Definition: tag.h:37
encapsulates test code
Definition: test.h:994
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:299
std::string GetName(void) const
Definition: test.cc:370
A suite of tests to run.
Definition: test.h:1188
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
a unique identifier for an interface.
Definition: type-id.h:59
Callback< ObjectBase * > GetConstructor(void) const
Get the constructor callback.
Definition: type-id.cc:1060
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
std::string GetName(void) const
Get the name.
Definition: type-id.cc:976
#define NS_TEST_EXPECT_MSG_NE(actual, limit, msg)
Test that an actual and expected (limit) value are not equal and report if not.
Definition: test.h:636
#define NS_TEST_EXPECT_MSG_EQ(actual, limit, msg)
Test that an actual and expected (limit) value are equal and report if not.
Definition: test.h:240
Every class exported by the ns3 library is enclosed in the ns3 namespace.
def start()
Definition: core.py:1852
bool verbose
#define LARGE_TAG_BUFFER_SIZE
static PacketTestSuite g_packetTestSuite
Static variable for test initialization.
#define CHECK(p, n,...)
#define E_DATA(name, start, end, data)
#define ReplaceCheck(n)
#define E(name, start, end)
#define CHECK_DATA(p, n,...)
#define RemoveCheck(n)
#define MAKE_TEST_TAGS
uint8_t data[writeSize]
Struct to hold the expected data in the packet.
Expected(uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
Constructor.
Expected(uint32_t n_, uint32_t start_, uint32_t end_)
Constructor.