A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
packet-test-suite.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005,2006 INRIA
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
18 */
19#include "ns3/packet-tag-list.h"
20#include "ns3/packet.h"
21#include "ns3/test.h"
22
23#include <cstdarg>
24#include <ctime>
25#include <iomanip>
26#include <iostream>
27#include <limits> // std:numeric_limits
28#include <string>
29
30using namespace ns3;
31
32//-----------------------------------------------------------------------------
33// Unit tests
34//-----------------------------------------------------------------------------
35namespace
36{
37
46class ATestTagBase : public Tag
47{
48 public:
50 : m_error(false),
51 m_data(0)
52 {
53 }
54
58 : m_error(false),
59 m_data(data)
60 {
61 }
62
68 {
69 static TypeId tid =
70 TypeId("ATestTagBase").SetParent<Tag>().SetGroupName("Network").HideFromDocumentation()
71 // No AddConstructor because this is an abstract class.
72 ;
73 return tid;
74 }
75
78 int GetData() const
79 {
80 int result = (int)m_data;
81 return result;
82 }
83
84 bool m_error;
85 uint8_t m_data;
86};
87
96template <int N>
97class ATestTag : public ATestTagBase
98{
99 public:
105 {
106 std::ostringstream oss;
107 oss << "anon::ATestTag<" << N << ">";
108 static TypeId tid = TypeId(oss.str())
110 .SetGroupName("Network")
111 .HideFromDocumentation()
112 .AddConstructor<ATestTag<N>>();
113 return tid;
114 }
115
116 TypeId GetInstanceTypeId() const override
117 {
118 return GetTypeId();
119 }
120
122 {
123 return N + sizeof(m_data);
124 }
125
126 void Serialize(TagBuffer buf) const override
127 {
128 buf.WriteU8(m_data);
129 for (uint32_t i = 0; i < N; ++i)
130 {
131 buf.WriteU8(N);
132 }
133 }
134
135 void Deserialize(TagBuffer buf) override
136 {
137 m_data = buf.ReadU8();
138 for (uint32_t i = 0; i < N; ++i)
139 {
140 uint8_t v = buf.ReadU8();
141 if (v != N)
142 {
143 m_error = true;
144 }
145 }
146 }
147
148 void Print(std::ostream& os) const override
149 {
150 os << N << "(" << m_data << ")";
151 }
152
154 : ATestTagBase()
155 {
156 }
157
160 ATestTag(uint8_t data)
162 {
163 }
164};
165
166// Previous versions of ns-3 limited the tag size to 20 bytes or less
167// static const uint8_t LARGE_TAG_BUFFER_SIZE = 64;
168#define LARGE_TAG_BUFFER_SIZE 64
169
180class ALargeTestTag : public Tag
181{
182 public:
184 {
185 for (uint8_t i = 0; i < (LARGE_TAG_BUFFER_SIZE - 1); i++)
186 {
187 m_data.push_back(i);
188 }
189 m_size = LARGE_TAG_BUFFER_SIZE;
190 }
191
197 {
198 static TypeId tid = TypeId("ALargeTestTag")
199 .SetParent<Tag>()
200 .SetGroupName("Network")
201 .HideFromDocumentation()
202 .AddConstructor<ALargeTestTag>();
203 return tid;
204 }
205
206 TypeId GetInstanceTypeId() const override
207 {
208 return GetTypeId();
209 }
210
212 {
213 return (uint32_t)m_size;
214 }
215
216 void Serialize(TagBuffer buf) const override
217 {
218 buf.WriteU8(m_size);
219 for (uint8_t i = 0; i < (m_size - 1); ++i)
220 {
221 buf.WriteU8(m_data[i]);
222 }
223 }
224
225 void Deserialize(TagBuffer buf) override
226 {
227 m_size = buf.ReadU8();
228 for (uint8_t i = 0; i < (m_size - 1); ++i)
229 {
230 uint8_t v = buf.ReadU8();
231 m_data.push_back(v);
232 }
233 }
234
235 void Print(std::ostream& os) const override
236 {
237 os << "(" << (uint16_t)m_size << ")";
238 }
239
240 private:
241 uint8_t m_size;
242 std::vector<uint8_t> m_data;
243};
244
254{
255 public:
257 : Header(),
258 m_error(false)
259 {
260 }
261
267 {
268 static TypeId tid = TypeId("ATestHeaderBase")
269 .SetParent<Header>()
270 .SetGroupName("Network")
271 .HideFromDocumentation()
272 // No AddConstructor because this is an abstract class.
273 ;
274 return tid;
275 }
276
277 bool m_error;
278};
279
288template <int N>
290{
291 public:
297 {
298 std::ostringstream oss;
299 oss << "anon::ATestHeader<" << N << ">";
300 static TypeId tid = TypeId(oss.str())
302 .SetGroupName("Network")
303 .HideFromDocumentation()
304 .AddConstructor<ATestHeader<N>>();
305 return tid;
306 }
307
308 TypeId GetInstanceTypeId() const override
309 {
310 return GetTypeId();
311 }
312
314 {
315 return N;
316 }
317
318 void Serialize(Buffer::Iterator iter) const override
319 {
320 for (uint32_t i = 0; i < N; ++i)
321 {
322 iter.WriteU8(N);
323 }
324 }
325
327 {
328 for (uint32_t i = 0; i < N; ++i)
329 {
330 uint8_t v = iter.ReadU8();
331 if (v != N)
332 {
333 m_error = true;
334 }
335 }
336 return N;
337 }
338
339 void Print(std::ostream& os) const override
340 {
341 }
342
345 {
346 }
347};
348
358{
359 public:
361 : Trailer(),
362 m_error(false)
363 {
364 }
365
371 {
372 static TypeId tid = TypeId("ATestTrailerBase")
374 .SetGroupName("Network")
375 .HideFromDocumentation()
376 // No AddConstructor because this is an abstract class.
377 ;
378 return tid;
379 }
380
381 bool m_error;
382};
383
392template <int N>
394{
395 public:
401 {
402 std::ostringstream oss;
403 oss << "anon::ATestTrailer<" << N << ">";
404 static TypeId tid = TypeId(oss.str())
406 .SetGroupName("Network")
407 .HideFromDocumentation()
408 .AddConstructor<ATestTrailer<N>>();
409 return tid;
410 }
411
412 TypeId GetInstanceTypeId() const override
413 {
414 return GetTypeId();
415 }
416
418 {
419 return N;
420 }
421
422 void Serialize(Buffer::Iterator iter) const override
423 {
424 iter.Prev(N);
425 for (uint32_t i = 0; i < N; ++i)
426 {
427 iter.WriteU8(N);
428 }
429 }
430
432 {
433 iter.Prev(N);
434 for (uint32_t i = 0; i < N; ++i)
435 {
436 uint8_t v = iter.ReadU8();
437 if (v != N)
438 {
439 m_error = true;
440 }
441 }
442 return N;
443 }
444
445 void Print(std::ostream& os) const override
446 {
447 }
448
451 {
452 }
453};
454
464{
472 : n(n_),
473 start(start_),
474 end(end_),
475 data(0)
476 {
477 }
478
486 Expected(uint32_t n_, uint32_t start_, uint32_t end_, uint8_t data_)
487 : n(n_),
488 start(start_),
489 end(end_),
490 data(data_)
491 {
492 }
493
497 uint8_t data;
498};
499
500} // namespace
501
502// tag name, start, end
503#define E(name, start, end) name, start, end
504
505// tag name, start, end, data
506#define E_DATA(name, start, end, data) name, start, end, data
507
508// Check byte tags on a packet, checks name, start, end
509#define CHECK(p, n, ...) DoCheck(p, n, __VA_ARGS__)
510
511// Check byte tags on a packet, checks name, start, end, data
512#define CHECK_DATA(p, n, ...) DoCheckData(p, n, __VA_ARGS__)
513
520class PacketTest : public TestCase
521{
522 public:
523 PacketTest();
524 void DoRun() override;
525
526 private:
533 void DoCheck(Ptr<const Packet> p, uint32_t n, ...);
540 void DoCheckData(Ptr<const Packet> p, uint32_t n, ...);
541};
542
544 : TestCase("Packet")
545{
546}
547
548void
550{
551 std::vector<Expected> expected;
552 va_list ap;
553 va_start(ap, n);
554 for (uint32_t k = 0; k < n; ++k)
555 {
556 uint32_t N = va_arg(ap, uint32_t);
557 uint32_t start = va_arg(ap, uint32_t);
558 uint32_t end = va_arg(ap, uint32_t);
559 expected.emplace_back(N, start, end);
560 }
561 va_end(ap);
562
563 ByteTagIterator i = p->GetByteTagIterator();
564 uint32_t j = 0;
565 while (i.HasNext() && j < expected.size())
566 {
567 ByteTagIterator::Item item = i.Next();
568 Expected e = expected[j];
569 std::ostringstream oss;
570 oss << "anon::ATestTag<" << e.n << ">";
571 NS_TEST_EXPECT_MSG_EQ(item.GetTypeId().GetName(), oss.str(), "trivial");
572 NS_TEST_EXPECT_MSG_EQ(item.GetStart(), e.start, "trivial");
573 NS_TEST_EXPECT_MSG_EQ(item.GetEnd(), e.end, "trivial");
574 ATestTagBase* tag = dynamic_cast<ATestTagBase*>(item.GetTypeId().GetConstructor()());
575 NS_TEST_EXPECT_MSG_NE(tag, 0, "trivial");
576 item.GetTag(*tag);
577 NS_TEST_EXPECT_MSG_EQ(tag->m_error, false, "trivial");
578 delete tag;
579 j++;
580 }
581 NS_TEST_EXPECT_MSG_EQ(i.HasNext(), false, "Nothing left");
582 NS_TEST_EXPECT_MSG_EQ(j, expected.size(), "Size match");
583}
584
585void
587{
588 std::vector<Expected> expected;
589 va_list ap;
590 va_start(ap, n);
591 for (uint32_t k = 0; k < n; ++k)
592 {
593 uint32_t N = va_arg(ap, uint32_t);
594 uint32_t start = va_arg(ap, uint32_t);
595 uint32_t end = va_arg(ap, uint32_t);
596 int data = va_arg(ap, int);
597 expected.emplace_back(N, start, end, data);
598 }
599 va_end(ap);
600
601 ByteTagIterator i = p->GetByteTagIterator();
602 uint32_t j = 0;
603 while (i.HasNext() && j < expected.size())
604 {
605 ByteTagIterator::Item item = i.Next();
606 Expected e = expected[j];
607 std::ostringstream oss;
608 oss << "anon::ATestTag<" << e.n << ">";
609 NS_TEST_EXPECT_MSG_EQ(item.GetTypeId().GetName(), oss.str(), "trivial");
610 NS_TEST_EXPECT_MSG_EQ(item.GetStart(), e.start, "trivial");
611 NS_TEST_EXPECT_MSG_EQ(item.GetEnd(), e.end, "trivial");
612 ATestTagBase* tag = dynamic_cast<ATestTagBase*>(item.GetTypeId().GetConstructor()());
613 NS_TEST_EXPECT_MSG_NE(tag, 0, "trivial");
614 item.GetTag(*tag);
615 NS_TEST_EXPECT_MSG_EQ(tag->m_error, false, "trivial");
616 NS_TEST_EXPECT_MSG_EQ(tag->GetData(), e.data, "trivial");
617 delete tag;
618 j++;
619 }
620 NS_TEST_EXPECT_MSG_EQ(i.HasNext(), false, "Nothing left");
621 NS_TEST_EXPECT_MSG_EQ(j, expected.size(), "Size match");
622}
623
624void
626{
627 Ptr<Packet> pkt1 = Create<Packet>(reinterpret_cast<const uint8_t*>("hello"), 5);
628 Ptr<Packet> pkt2 = Create<Packet>(reinterpret_cast<const uint8_t*>(" world"), 6);
629 Ptr<Packet> packet = Create<Packet>();
630 packet->AddAtEnd(pkt1);
631 packet->AddAtEnd(pkt2);
632
633 NS_TEST_EXPECT_MSG_EQ(packet->GetSize(), 11, "trivial");
634
635 uint8_t* buf = new uint8_t[packet->GetSize()];
636 packet->CopyData(buf, packet->GetSize());
637
638 std::string msg = std::string(reinterpret_cast<const char*>(buf), packet->GetSize());
639 delete[] buf;
640
641 NS_TEST_EXPECT_MSG_EQ(msg, "hello world", "trivial");
642
643 Ptr<const Packet> p = Create<Packet>(1000);
644
645 p->AddByteTag(ATestTag<1>());
646 CHECK(p, 1, E(1, 0, 1000));
647 Ptr<const Packet> copy = p->Copy();
648 CHECK(copy, 1, E(1, 0, 1000));
649
650 p->AddByteTag(ATestTag<2>());
651 CHECK(p, 2, E(1, 0, 1000), E(2, 0, 1000));
652 CHECK(copy, 1, E(1, 0, 1000));
653
654 {
655 Packet c0 = *copy;
656 Packet c1 = *copy;
657 c0 = c1;
658 CHECK(&c0, 1, E(1, 0, 1000));
659 CHECK(&c1, 1, E(1, 0, 1000));
660 CHECK(copy, 1, E(1, 0, 1000));
662 CHECK(&c0, 2, E(1, 0, 1000), E(10, 0, 1000));
663 CHECK(&c1, 1, E(1, 0, 1000));
664 CHECK(copy, 1, E(1, 0, 1000));
665 }
666
667 Ptr<Packet> frag0 = p->CreateFragment(0, 10);
668 Ptr<Packet> frag1 = p->CreateFragment(10, 90);
669 Ptr<const Packet> frag2 = p->CreateFragment(100, 900);
670 frag0->AddByteTag(ATestTag<3>());
671 CHECK(frag0, 3, E(1, 0, 10), E(2, 0, 10), E(3, 0, 10));
672 frag1->AddByteTag(ATestTag<4>());
673 CHECK(frag1, 3, E(1, 0, 90), E(2, 0, 90), E(4, 0, 90));
674 frag2->AddByteTag(ATestTag<5>());
675 CHECK(frag2, 3, E(1, 0, 900), E(2, 0, 900), E(5, 0, 900));
676
677 frag1->AddAtEnd(frag2);
678 CHECK(frag1,
679 6,
680 E(1, 0, 90),
681 E(2, 0, 90),
682 E(4, 0, 90),
683 E(1, 90, 990),
684 E(2, 90, 990),
685 E(5, 90, 990));
686
687 CHECK(frag0, 3, E(1, 0, 10), E(2, 0, 10), E(3, 0, 10));
688 frag0->AddAtEnd(frag1);
689 CHECK(frag0,
690 9,
691 E(1, 0, 10),
692 E(2, 0, 10),
693 E(3, 0, 10),
694 E(1, 10, 100),
695 E(2, 10, 100),
696 E(4, 10, 100),
697 E(1, 100, 1000),
698 E(2, 100, 1000),
699 E(5, 100, 1000));
700
701 // force caching a buffer of the right size.
702 frag0 = Create<Packet>(1000);
703 frag0->AddHeader(ATestHeader<10>());
704 frag0 = nullptr;
705
706 p = Create<Packet>(1000);
707 p->AddByteTag(ATestTag<20>());
708 CHECK(p, 1, E(20, 0, 1000));
709 frag0 = p->CreateFragment(10, 90);
710 CHECK(p, 1, E(20, 0, 1000));
711 CHECK(frag0, 1, E(20, 0, 90));
712 p = nullptr;
713 frag0->AddHeader(ATestHeader<10>());
714 CHECK(frag0, 1, E(20, 10, 100));
715
716 {
717 Ptr<Packet> tmp = Create<Packet>(100);
718 tmp->AddByteTag(ATestTag<20>());
719 CHECK(tmp, 1, E(20, 0, 100));
720 tmp->AddHeader(ATestHeader<10>());
721 CHECK(tmp, 1, E(20, 10, 110));
723 tmp->RemoveHeader(h);
724 CHECK(tmp, 1, E(20, 0, 100));
725 tmp->AddHeader(ATestHeader<10>());
726 CHECK(tmp, 1, E(20, 10, 110));
727
728 tmp = Create<Packet>(100);
729 tmp->AddByteTag(ATestTag<20>());
730 CHECK(tmp, 1, E(20, 0, 100));
731 tmp->AddTrailer(ATestTrailer<10>());
732 CHECK(tmp, 1, E(20, 0, 100));
734 tmp->RemoveTrailer(t);
735 CHECK(tmp, 1, E(20, 0, 100));
736 tmp->AddTrailer(ATestTrailer<10>());
737 CHECK(tmp, 1, E(20, 0, 100));
738 }
739
740 {
741 Ptr<Packet> tmp = Create<Packet>(0);
742 tmp->AddHeader(ATestHeader<156>());
743 tmp->AddByteTag(ATestTag<20>());
744 CHECK(tmp, 1, E(20, 0, 156));
745 tmp->RemoveAtStart(120);
746 CHECK(tmp, 1, E(20, 0, 36));
747 Ptr<Packet> a = Create<Packet>(0);
748 a->AddAtEnd(tmp);
749 CHECK(a, 1, E(20, 0, 36));
750 }
751
752 {
753 Ptr<Packet> tmp = Create<Packet>(0);
754 tmp->AddByteTag(ATestTag<20>());
755 CHECK(tmp, 0, E(20, 0, 0));
756 }
757 {
758 Ptr<Packet> tmp = Create<Packet>(1000);
759 tmp->AddByteTag(ATestTag<20>());
760 CHECK(tmp, 1, E(20, 0, 1000));
761 tmp->RemoveAtStart(1000);
762 CHECK(tmp, 0, E(0, 0, 0));
763 Ptr<Packet> a = Create<Packet>(10);
764 a->AddByteTag(ATestTag<10>());
765 CHECK(a, 1, E(10, 0, 10));
766 tmp->AddAtEnd(a);
767 CHECK(tmp, 1, E(10, 0, 10));
768 }
769
770 {
771 Packet p;
772 ATestTag<10> a;
773 p.AddPacketTag(a);
774 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), true, "trivial");
775 ATestTag<11> b;
776 p.AddPacketTag(b);
777 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), true, "trivial");
778 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), true, "trivial");
779 Packet copy = p;
780 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), true, "trivial");
781 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
782 ATestTag<12> c;
783 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), false, "trivial");
784 copy.AddPacketTag(c);
785 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), true, "trivial");
786 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), true, "trivial");
787 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
788 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(c), false, "trivial");
789 copy.RemovePacketTag(b);
790 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(b), false, "trivial");
791 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), true, "trivial");
792 p.RemovePacketTag(a);
793 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(a), false, "trivial");
794 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(a), true, "trivial");
795 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(c), false, "trivial");
796 NS_TEST_EXPECT_MSG_EQ(copy.PeekPacketTag(c), true, "trivial");
798 NS_TEST_EXPECT_MSG_EQ(p.PeekPacketTag(b), false, "trivial");
799 }
800
801 /* Test Serialization and Deserialization of Packet with PacketTag data */
802 {
803 Ptr<Packet> p1 = Create<Packet>(1000);
804 ;
805 ATestTag<10> a1(65);
806 ATestTag<11> b1(66);
807 ATestTag<12> c1(67);
808
809 p1->AddPacketTag(a1);
810 p1->AddPacketTag(b1);
811 p1->AddPacketTag(c1);
812
813 uint32_t serializedSize = p1->GetSerializedSize();
814 uint8_t* buffer = new uint8_t[serializedSize + 16];
815 p1->Serialize(buffer, serializedSize);
816
817 Ptr<Packet> p2 = Create<Packet>(buffer, serializedSize, true);
818
819 delete[] buffer;
820
821 ATestTag<10> a2;
822 ATestTag<11> b2;
823 ATestTag<12> c2;
824
825 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(a2), true, "trivial");
826 NS_TEST_EXPECT_MSG_EQ(a2.GetData(), 65, "trivial");
827 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(b2), true, "trivial");
828 NS_TEST_EXPECT_MSG_EQ(b2.GetData(), 66, "trivial");
829 NS_TEST_EXPECT_MSG_EQ(p2->PeekPacketTag(c2), true, "trivial");
830 NS_TEST_EXPECT_MSG_EQ(c2.GetData(), 67, "trivial");
831 }
832
833 /* Test Serialization and Deserialization of Packet with ByteTag data */
834 {
835 Ptr<Packet> p1 = Create<Packet>(1000);
836 ;
837
838 ATestTag<10> a1(65);
839 ATestTag<11> b1(66);
840 ATestTag<12> c1(67);
841
842 p1->AddByteTag(a1);
843 p1->AddByteTag(b1);
844 p1->AddByteTag(c1);
845
846 CHECK(p1, 3, E(10, 0, 1000), E(11, 0, 1000), E(12, 0, 1000));
847
848 uint32_t serializedSize = p1->GetSerializedSize();
849 uint8_t* buffer = new uint8_t[serializedSize];
850 p1->Serialize(buffer, serializedSize);
851
852 Ptr<Packet> p2 = Create<Packet>(buffer, serializedSize, true);
853
854 delete[] buffer;
855
856 CHECK_DATA(p2,
857 3,
858 E_DATA(10, 0, 1000, 65),
859 E_DATA(11, 0, 1000, 66),
860 E_DATA(12, 0, 1000, 67));
861 }
862
863 {
866 Ptr<Packet> tmp = Create<Packet>(1000);
867 tmp->AddByteTag(ATestTag<20>());
868 CHECK(tmp, 1, E(20, 0, 1000));
869 tmp->AddHeader(ATestHeader<2>());
870 CHECK(tmp, 1, E(20, 2, 1002));
871 tmp->RemoveAtStart(1);
872 CHECK(tmp, 1, E(20, 1, 1001));
873#if 0
874 tmp->PeekData ();
875 CHECK (tmp, 1, E (20, 1, 1001));
876#endif
877 }
878
879 /* Test reducing tagged packet size and increasing it back. */
880 {
881 Ptr<Packet> tmp = Create<Packet>(0);
882 tmp->AddHeader(ATestHeader<100>());
883 tmp->AddByteTag(ATestTag<25>());
884 CHECK(tmp, 1, E(25, 0, 100));
885 tmp->RemoveAtStart(50);
886 CHECK(tmp, 1, E(25, 0, 50));
887 tmp->AddHeader(ATestHeader<50>());
888 CHECK(tmp, 1, E(25, 50, 100));
889 }
890
891 /* Similar test case, but using trailer instead of header. */
892 {
893 Ptr<Packet> tmp = Create<Packet>(0);
894 tmp->AddTrailer(ATestTrailer<100>());
895 tmp->AddByteTag(ATestTag<25>());
896 CHECK(tmp, 1, E(25, 0, 100));
897 tmp->RemoveAtEnd(50);
898 CHECK(tmp, 1, E(25, 0, 50));
899 tmp->AddTrailer(ATestTrailer<50>());
900 CHECK(tmp, 1, E(25, 0, 50));
901 }
902
903 /* Test reducing tagged packet size and increasing it by half. */
904 {
905 Ptr<Packet> tmp = Create<Packet>(0);
906 tmp->AddHeader(ATestHeader<100>());
907 tmp->AddByteTag(ATestTag<25>());
908 CHECK(tmp, 1, E(25, 0, 100));
909 tmp->RemoveAtStart(50);
910 CHECK(tmp, 1, E(25, 0, 50));
911 tmp->AddHeader(ATestHeader<25>());
912 CHECK(tmp, 1, E(25, 25, 75));
913 }
914
915 /* Similar test case, but using trailer instead of header. */
916 {
917 Ptr<Packet> tmp = Create<Packet>(0);
918 tmp->AddTrailer(ATestTrailer<100>());
919 tmp->AddByteTag(ATestTag<25>());
920 CHECK(tmp, 1, E(25, 0, 100));
921 tmp->RemoveAtEnd(50);
922 CHECK(tmp, 1, E(25, 0, 50));
923 tmp->AddTrailer(ATestTrailer<25>());
924 CHECK(tmp, 1, E(25, 0, 50));
925 }
926
927 /* Test AddPaddingAtEnd. */
928 {
929 Ptr<Packet> tmp = Create<Packet>(0);
930 tmp->AddTrailer(ATestTrailer<100>());
931 tmp->AddByteTag(ATestTag<25>());
932 CHECK(tmp, 1, E(25, 0, 100));
933 tmp->RemoveAtEnd(50);
934 CHECK(tmp, 1, E(25, 0, 50));
935 tmp->AddPaddingAtEnd(50);
936 CHECK(tmp, 1, E(25, 0, 50));
937 }
938
939 /* Test reducing tagged packet size and increasing it back,
940 * now using padding bytes to avoid triggering dirty state
941 * in virtual buffer
942 */
943 {
944 Ptr<Packet> tmp = Create<Packet>(100);
945 tmp->AddByteTag(ATestTag<25>());
946 CHECK(tmp, 1, E(25, 0, 100));
947 tmp->RemoveAtEnd(50);
948 CHECK(tmp, 1, E(25, 0, 50));
949 tmp->AddPaddingAtEnd(50);
950 CHECK(tmp, 1, E(25, 0, 50));
951 }
952
953 /* Test ALargeTestTag */
954 {
955 Ptr<Packet> tmp = Create<Packet>(0);
957 tmp->AddPacketTag(a);
958 }
959}
960
968{
969 public:
971 ~PacketTagListTest() override;
972
973 private:
974 void DoRun() override;
982 void CheckRef(const PacketTagList& ref, ATestTagBase& t, const char* msg, bool miss = false);
989 void CheckRefList(const PacketTagList& ref, const char* msg, int miss = 0);
990
998 int RemoveTime(const PacketTagList& ref, ATestTagBase& t, const char* msg = nullptr);
999
1005 int AddRemoveTime(const bool verbose = false);
1006};
1007
1009 : TestCase("PacketTagListTest: ")
1010{
1011}
1012
1014{
1015}
1016
1017void
1018PacketTagListTest::CheckRef(const PacketTagList& ref, ATestTagBase& t, const char* msg, bool miss)
1019{
1020 int expect = t.GetData(); // the value we should find
1021 bool found = ref.Peek(t); // rewrites t with actual value
1022 NS_TEST_EXPECT_MSG_EQ(found, !miss, msg << ": ref contains " << t.GetTypeId().GetName());
1023 if (found)
1024 {
1026 expect,
1027 msg << ": ref " << t.GetTypeId().GetName() << " = " << expect);
1028 }
1029}
1030
1031// A set of tags with data value 1, to check COW
1032#define MAKE_TEST_TAGS \
1033 ATestTag<1> t1(1); \
1034 ATestTag<2> t2(1); \
1035 ATestTag<3> t3(1); \
1036 ATestTag<4> t4(1); \
1037 ATestTag<5> t5(1); \
1038 ATestTag<6> t6(1); \
1039 ATestTag<7> t7(1); \
1040 constexpr int TAG_LAST [[maybe_unused]] = 7; /* length of ref PacketTagList */
1041
1042void
1043PacketTagListTest::CheckRefList(const PacketTagList& ptl, const char* msg, int miss /* = 0 */)
1044{
1046 CheckRef(ptl, t1, msg, miss == 1);
1047 CheckRef(ptl, t2, msg, miss == 2);
1048 CheckRef(ptl, t3, msg, miss == 3);
1049 CheckRef(ptl, t4, msg, miss == 4);
1050 CheckRef(ptl, t5, msg, miss == 5);
1051 CheckRef(ptl, t6, msg, miss == 6);
1052 CheckRef(ptl, t7, msg, miss == 7);
1053}
1054
1055int
1056PacketTagListTest::RemoveTime(const PacketTagList& ref, ATestTagBase& t, const char* msg /* = 0 */)
1057{
1058 const int reps = 10000;
1059 std::vector<PacketTagList> ptv(reps, ref);
1060 int start = clock();
1061 for (int i = 0; i < reps; ++i)
1062 {
1063 ptv[i].Remove(t);
1064 }
1065 int stop = clock();
1066 int delta = stop - start;
1067 if (msg)
1068 {
1069 std::cout << GetName() << "remove time: " << msg << ": " << std::setw(8) << delta
1070 << " ticks to remove " << reps << " times" << std::endl;
1071 }
1072 return delta;
1073}
1074
1075int
1077{
1078 const int reps = 100000;
1079 PacketTagList ptl;
1080 ATestTag<2> t(2);
1081 int start = clock();
1082 for (int i = 0; i < reps; ++i)
1083 {
1084 ptl.Add(t);
1085 ptl.Remove(t);
1086 }
1087 int stop = clock();
1088 int delta = stop - start;
1089 if (verbose)
1090 {
1091 std::cout << GetName() << "add/remove time: " << std::setw(8) << delta
1092 << " ticks to add+remove " << reps << " times" << std::endl;
1093 }
1094 return delta;
1095}
1096
1097void
1099{
1100 std::cout << GetName() << "begin" << std::endl;
1101
1103
1104 PacketTagList ref; // empty list
1105 ref.Add(t1); // last
1106 ref.Add(t2); // post merge
1107 ref.Add(t3); // merge successor
1108 ref.Add(t4); // merge
1109 ref.Add(t5); // merge precursor
1110 ref.Add(t6); // pre-merge
1111 ref.Add(t7); // first
1112
1113 { // Peek
1114 std::cout << GetName() << "check Peek (missing tag) returns false" << std::endl;
1115 ATestTag<10> t10;
1116 NS_TEST_EXPECT_MSG_EQ(ref.Peek(t10), false, "missing tag");
1117 }
1118
1119 { // Copy ctor, assignment
1120 std::cout << GetName() << "check copy and assignment" << std::endl;
1121 {
1122 // Test copy constructor
1123 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1124 PacketTagList ptl(ref);
1125 CheckRefList(ref, "copy ctor orig");
1126 CheckRefList(ptl, "copy ctor copy");
1127 }
1128 {
1129 // Test copy constructor
1130 // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1131 PacketTagList ptl = ref;
1132 CheckRefList(ref, "assignment orig");
1133 CheckRefList(ptl, "assignment copy");
1134 }
1135 }
1136
1137 {// Removal
1138#define RemoveCheck(n) \
1139 { \
1140 PacketTagList p##n = ref; \
1141 p##n.Remove(t##n); \
1142 CheckRefList(ref, "remove " #n " orig"); \
1143 CheckRefList(p##n, "remove " #n " copy", n); \
1144 }
1145
1146 {// Remove single tags from list
1147 std::cout << GetName() << "check removal of each tag" << std::endl;
1148 RemoveCheck(1);
1149 RemoveCheck(2);
1150 RemoveCheck(3);
1151 RemoveCheck(4);
1152 RemoveCheck(5);
1153 RemoveCheck(6);
1154 RemoveCheck(7);
1155}
1156
1157{ // Remove in the presence of a merge
1158 std::cout << GetName() << "check removal doesn't disturb merge " << std::endl;
1159 PacketTagList ptl = ref;
1160 ptl.Remove(t7);
1161 ptl.Remove(t6);
1162 ptl.Remove(t5);
1163
1164 PacketTagList mrg = ptl; // merged list
1165 ATestTag<8> m5(1);
1166 mrg.Add(m5); // ptl and mrg differ
1167 ptl.Add(t5);
1168 ptl.Add(t6);
1169 ptl.Add(t7);
1170
1171 CheckRefList(ref, "post merge, orig");
1172 CheckRefList(ptl, "post merge, long chain");
1173 const char* msg = "post merge, short chain";
1174 CheckRef(mrg, t1, msg, false);
1175 CheckRef(mrg, t2, msg, false);
1176 CheckRef(mrg, t3, msg, false);
1177 CheckRef(mrg, t4, msg, false);
1178 CheckRef(mrg, m5, msg, false);
1179}
1180#undef RemoveCheck
1181} // Removal
1182
1183{ // Replace
1184
1185 std::cout << GetName() << "check replacing each tag" << std::endl;
1186
1187#define ReplaceCheck(n) \
1188 t##n.m_data = 2; \
1189 { \
1190 PacketTagList p##n = ref; \
1191 p##n.Replace(t##n); \
1192 CheckRefList(ref, "replace " #n " orig"); \
1193 CheckRef(p##n, t##n, "replace " #n " copy"); \
1194 }
1195
1196 ReplaceCheck(1);
1197 ReplaceCheck(2);
1198 ReplaceCheck(3);
1199 ReplaceCheck(4);
1200 ReplaceCheck(5);
1201 ReplaceCheck(6);
1202 ReplaceCheck(7);
1203}
1204
1205{ // Timing
1206 std::cout << GetName() << "add+remove timing" << std::endl;
1207 int flm = std::numeric_limits<int>::max();
1208 const int nIterations = 100;
1209 for (int i = 0; i < nIterations; ++i)
1210 {
1211 int now = AddRemoveTime();
1212 if (now < flm)
1213 {
1214 flm = now;
1215 }
1216 }
1217 std::cout << GetName() << "min add+remove time: " << std::setw(8) << flm << " ticks"
1218 << std::endl;
1219
1220 std::cout << GetName() << "remove timing" << std::endl;
1221 // tags numbered from 1, so add one for (unused) entry at 0
1222 std::vector<int> rmn(TAG_LAST + 1, std::numeric_limits<int>::max());
1223 for (int i = 0; i < nIterations; ++i)
1224 {
1225 for (int j = 1; j <= TAG_LAST; ++j)
1226 {
1227 int now = 0;
1228 switch (j)
1229 {
1230 case 7:
1231 now = RemoveTime(ref, t7);
1232 break;
1233 case 6:
1234 now = RemoveTime(ref, t6);
1235 break;
1236 case 5:
1237 now = RemoveTime(ref, t5);
1238 break;
1239 case 4:
1240 now = RemoveTime(ref, t4);
1241 break;
1242 case 3:
1243 now = RemoveTime(ref, t3);
1244 break;
1245 case 2:
1246 now = RemoveTime(ref, t2);
1247 break;
1248 case 1:
1249 now = RemoveTime(ref, t1);
1250 break;
1251 } // switch
1252
1253 if (now < rmn[j])
1254 {
1255 rmn[j] = now;
1256 }
1257 } // for tag j
1258 } // for iteration i
1259 for (int j = TAG_LAST; j > 0; --j)
1260 {
1261 std::cout << GetName() << "min remove time: t" << j << ": " << std::setw(8) << rmn[j]
1262 << " ticks" << std::endl;
1263 }
1264} // Timing
1265}
1266
1274{
1275 public:
1277};
1278
1280 : TestSuite("packet", UNIT)
1281{
1284}
1285
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 DoRun() override
Implementation to actually run this TestCase.
void CheckRef(const PacketTagList &ref, ATestTagBase &t, const char *msg, bool miss=false)
Checks against a reference PacketTagList.
int RemoveTime(const PacketTagList &ref, ATestTagBase &t, const char *msg=nullptr)
Prints the remove time.
Packet unit tests.
void DoCheckData(Ptr< const Packet > p, uint32_t n,...)
Checks the packet and its data.
void DoRun() override
Implementation to actually run this TestCase.
void DoCheck(Ptr< const Packet > p, uint32_t n,...)
Checks the packet.
Packet TestSuite.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t Deserialize(Buffer::Iterator iter) override
void Serialize(Buffer::Iterator iter) const override
void Print(std::ostream &os) const override
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
uint32_t Deserialize(Buffer::Iterator iter) override
void Serialize(Buffer::Iterator iter) const override
iterator in a Buffer instance
Definition: buffer.h:100
uint8_t ReadU8()
Definition: buffer.h:1027
void WriteU8(uint8_t data)
Definition: buffer.h:881
void Prev()
go backward by one byte
Definition: buffer.h:860
Identifies a byte tag and a set of bytes within a packet to which the tag applies.
Definition: packet.h:63
uint32_t GetEnd() const
The index is an offset from the start of the packet.
Definition: packet.cc:48
void GetTag(Tag &tag) const
Read the requested tag and store it in the user-provided tag instance.
Definition: packet.cc:54
uint32_t GetStart() const
The index is an offset from the start of the packet.
Definition: packet.cc:42
TypeId GetTypeId() const
Definition: packet.cc:36
Iterator over the set of byte tags in a packet.
Definition: packet.h:56
bool HasNext() const
Definition: packet.cc:72
Protocol header serialization and deserialization.
Definition: header.h:44
network packets
Definition: packet.h:239
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
void RemoveAllPacketTags()
Remove all packet tags.
Definition: packet.cc:1009
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:934
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:1002
List of the packet tags stored in a packet.
bool Remove(Tag &tag)
Remove (the first instance of) tag from the list.
void Add(const Tag &tag) const
Add a tag to the head of this branch.
bool Peek(Tag &tag) const
Find a tag and return its value.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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()
Definition: tag-buffer.h:196
tag a set of bytes in a packet
Definition: tag.h:39
encapsulates test code
Definition: test.h:1060
@ QUICK
Fast test.
Definition: test.h:1065
void AddTestCase(TestCase *testCase, TestDuration duration=QUICK)
Add an individual child TestCase to this test suite.
Definition: test.cc:301
std::string GetName() const
Definition: test.cc:373
A suite of tests to run.
Definition: test.h:1256
Protocol trailer serialization and deserialization.
Definition: trailer.h:41
a unique identifier for an interface.
Definition: type-id.h:59
Callback< ObjectBase * > GetConstructor() const
Get the constructor callback.
Definition: type-id.cc:1089
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:936
std::string GetName() const
Get the name.
Definition: type-id.cc:996
#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:666
#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:251
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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.