A Discrete-Event Network Simulator
QKDNetSim v2.0 (NS-3 v3.41) @ (+)
API
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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 
30 using namespace ns3;
31 
32 //-----------------------------------------------------------------------------
33 // Unit tests
34 //-----------------------------------------------------------------------------
35 namespace
36 {
37 
46 class ATestTagBase : public Tag
47 {
48  public:
50  : m_error(false),
51  m_data(0)
52  {
53  }
54 
57  ATestTagBase(uint8_t data)
58  : m_error(false),
59  m_data(data)
60  {
61  }
62 
67  static TypeId GetTypeId()
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 
96 template <int N>
97 class ATestTag : public ATestTagBase
98 {
99  public:
104  static TypeId GetTypeId()
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 
121  uint32_t GetSerializedSize() const override
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)
161  : ATestTagBase(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 
180 class 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 
196  static TypeId GetTypeId()
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 
211  uint32_t GetSerializedSize() const override
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 
253 class ATestHeaderBase : public Header
254 {
255  public:
257  : Header(),
258  m_error(false)
259  {
260  }
261 
266  static TypeId GetTypeId()
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 
288 template <int N>
290 {
291  public:
296  static TypeId GetTypeId()
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 
313  uint32_t GetSerializedSize() const override
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 
326  uint32_t Deserialize(Buffer::Iterator iter) override
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 
344  : ATestHeaderBase()
345  {
346  }
347 };
348 
357 class ATestTrailerBase : public Trailer
358 {
359  public:
361  : Trailer(),
362  m_error(false)
363  {
364  }
365 
370  static TypeId GetTypeId()
371  {
372  static TypeId tid = TypeId("ATestTrailerBase")
373  .SetParent<Trailer>()
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 
392 template <int N>
394 {
395  public:
400  static TypeId GetTypeId()
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 
417  uint32_t GetSerializedSize() const override
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 
431  uint32_t Deserialize(Buffer::Iterator iter) override
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 
450  : ATestTrailerBase()
451  {
452  }
453 };
454 
463 struct Expected
464 {
471  Expected(uint32_t n_, uint32_t start_, uint32_t end_)
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 
494  uint32_t n;
495  uint32_t start;
496  uint32_t end;
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 
520 class 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 
548 void
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 
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 
585 void
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 
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 
624 void
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  auto 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));
661  c0.AddByteTag(ATestTag<10>());
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));
722  ATestHeader<10> h;
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));
733  ATestTrailer<10> t;
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  auto 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  auto 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);
956  ALargeTestTag a;
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 
1017 void
1018 PacketTagListTest::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  {
1025  NS_TEST_EXPECT_MSG_EQ(t.GetData(),
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 
1042 void
1043 PacketTagListTest::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 
1055 int
1056 PacketTagListTest::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 
1075 int
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 
1097 void
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  {
1115  std::cout << GetName() << "check Peek (missing tag) returns false" << std::endl;
1116  ATestTag<10> t10;
1117  NS_TEST_EXPECT_MSG_EQ(ref.Peek(t10), false, "missing tag");
1118  }
1119 
1120  // Copy ctor, assignment
1121  {
1122  std::cout << GetName() << "check copy and assignment" << std::endl;
1123  {
1124  // Test copy constructor
1125  // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1126  PacketTagList ptl(ref);
1127  CheckRefList(ref, "copy ctor orig");
1128  CheckRefList(ptl, "copy ctor copy");
1129  }
1130  {
1131  // Test copy constructor
1132  // NOLINTNEXTLINE(performance-unnecessary-copy-initialization)
1133  PacketTagList ptl = ref;
1134  CheckRefList(ref, "assignment orig");
1135  CheckRefList(ptl, "assignment copy");
1136  }
1137  }
1138 
1139  // Removal
1140  {
1141 #define RemoveCheck(n) \
1142  PacketTagList p##n = ref; \
1143  p##n.Remove(t##n); \
1144  CheckRefList(ref, "remove " #n " orig"); \
1145  CheckRefList(p##n, "remove " #n " copy", n);
1146 
1147  // Remove single tags from list
1148  {
1149  std::cout << GetName() << "check removal of each tag" << std::endl;
1150  RemoveCheck(1);
1151  RemoveCheck(2);
1152  RemoveCheck(3);
1153  RemoveCheck(4);
1154  RemoveCheck(5);
1155  RemoveCheck(6);
1156  RemoveCheck(7);
1157  }
1158 
1159  // Remove in the presence of a merge
1160  {
1161  std::cout << GetName() << "check removal doesn't disturb merge " << std::endl;
1162  PacketTagList ptl = ref;
1163  ptl.Remove(t7);
1164  ptl.Remove(t6);
1165  ptl.Remove(t5);
1166 
1167  PacketTagList mrg = ptl; // merged list
1168  ATestTag<8> m5(1);
1169  mrg.Add(m5); // ptl and mrg differ
1170  ptl.Add(t5);
1171  ptl.Add(t6);
1172  ptl.Add(t7);
1173 
1174  CheckRefList(ref, "post merge, orig");
1175  CheckRefList(ptl, "post merge, long chain");
1176  const char* msg = "post merge, short chain";
1177  CheckRef(mrg, t1, msg, false);
1178  CheckRef(mrg, t2, msg, false);
1179  CheckRef(mrg, t3, msg, false);
1180  CheckRef(mrg, t4, msg, false);
1181  CheckRef(mrg, m5, msg, false);
1182  }
1183 #undef RemoveCheck
1184  } // Removal
1185 
1186  // Replace
1187  {
1188  std::cout << GetName() << "check replacing each tag" << std::endl;
1189 
1190 #define ReplaceCheck(n) \
1191  t##n.m_data = 2; \
1192  { \
1193  PacketTagList p##n = ref; \
1194  p##n.Replace(t##n); \
1195  CheckRefList(ref, "replace " #n " orig"); \
1196  CheckRef(p##n, t##n, "replace " #n " copy"); \
1197  }
1198 
1199  ReplaceCheck(1);
1200  ReplaceCheck(2);
1201  ReplaceCheck(3);
1202  ReplaceCheck(4);
1203  ReplaceCheck(5);
1204  ReplaceCheck(6);
1205  ReplaceCheck(7);
1206  }
1207 
1208  // Timing
1209  {
1210  std::cout << GetName() << "add+remove timing" << std::endl;
1211  int flm = std::numeric_limits<int>::max();
1212  const int nIterations = 100;
1213  for (int i = 0; i < nIterations; ++i)
1214  {
1215  int now = AddRemoveTime();
1216  if (now < flm)
1217  {
1218  flm = now;
1219  }
1220  }
1221  std::cout << GetName() << "min add+remove time: " << std::setw(8) << flm << " ticks"
1222  << std::endl;
1223 
1224  std::cout << GetName() << "remove timing" << std::endl;
1225  // tags numbered from 1, so add one for (unused) entry at 0
1226  std::vector<int> rmn(TAG_LAST + 1, std::numeric_limits<int>::max());
1227  for (int i = 0; i < nIterations; ++i)
1228  {
1229  for (int j = 1; j <= TAG_LAST; ++j)
1230  {
1231  int now = 0;
1232  switch (j)
1233  {
1234  case 7:
1235  now = RemoveTime(ref, t7);
1236  break;
1237  case 6:
1238  now = RemoveTime(ref, t6);
1239  break;
1240  case 5:
1241  now = RemoveTime(ref, t5);
1242  break;
1243  case 4:
1244  now = RemoveTime(ref, t4);
1245  break;
1246  case 3:
1247  now = RemoveTime(ref, t3);
1248  break;
1249  case 2:
1250  now = RemoveTime(ref, t2);
1251  break;
1252  case 1:
1253  now = RemoveTime(ref, t1);
1254  break;
1255  } // switch
1256 
1257  if (now < rmn[j])
1258  {
1259  rmn[j] = now;
1260  }
1261  } // for tag j
1262  } // for iteration i
1263  for (int j = TAG_LAST; j > 0; --j)
1264  {
1265  std::cout << GetName() << "min remove time: t" << j << ": " << std::setw(8) << rmn[j]
1266  << " ticks" << std::endl;
1267  }
1268  } // Timing
1269 }
1270 
1278 {
1279  public:
1280  PacketTestSuite();
1281 };
1282 
1284  : TestSuite("packet", UNIT)
1285 {
1286  AddTestCase(new PacketTest, TestCase::QUICK);
1287  AddTestCase(new PacketTagListTest, TestCase::QUICK);
1288 }
1289 
#define max(a, b)
Definition: 80211b.c:42
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:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:354
uint32_t RemoveTrailer(Trailer &trailer)
Remove a deserialized trailer from the internal buffer.
Definition: packet.cc:336
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t GetSize() const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:861
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:400
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:376
uint32_t GetSerializedSize() const
Returns number of bytes required for packet serialization.
Definition: packet.cc:610
void RemoveAtStart(uint32_t size)
Remove size bytes from the start of the current packet.
Definition: packet.cc:384
Ptr< Packet > Copy() const
performs a COW copy of the packet.
Definition: packet.cc:131
uint32_t Serialize(uint8_t *buffer, uint32_t maxSize) const
Serialize a packet, tags, and metadata into a byte buffer.
Definition: packet.cc:663
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
void RemoveAllPacketTags()
Remove all packet tags.
Definition: packet.cc:990
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:238
void AddByteTag(const Tag &tag) const
Tag each byte included in this packet with a new byte tag.
Definition: packet.cc:915
void AddTrailer(const Trailer &trailer)
Add trailer to this packet.
Definition: packet.cc:324
void AddPaddingAtEnd(uint32_t size)
Add a zero-filled padding to the packet.
Definition: packet.cc:367
bool PeekPacketTag(Tag &tag) const
Search a matching tag and call Tag::Deserialize if it is found.
Definition: packet.cc:983
ByteTagIterator GetByteTagIterator() const
Returns an iterator over the set of byte tags included in this packet.
Definition: packet.cc:937
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.
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
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:1084
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
std::string GetName() const
Get the name.
Definition: type-id.cc:991
#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.