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 
30 using namespace ns3;
31 
32 //-----------------------------------------------------------------------------
33 // Unit tests
34 //-----------------------------------------------------------------------------
35 namespace {
36 
45 class ATestTagBase : public Tag
46 {
47 public:
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 
84 template <int N>
85 class ATestTag : public ATestTagBase
86 {
87 public:
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 
152 class ALargeTestTag : public Tag
153 {
154 public:
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  }
200 private:
201  uint8_t m_size;
202  std::vector<uint8_t> m_data;
203 };
204 
213 class ATestHeaderBase : public Header
214 {
215 public:
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 
242 template <int N>
244 {
245 public:
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  }
273  virtual uint32_t Deserialize (Buffer::Iterator iter) {
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 
299 class ATestTrailerBase : public Trailer
300 {
301 public:
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 
328 template <int N>
330 {
331 public:
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  }
360  virtual uint32_t Deserialize (Buffer::Iterator iter) {
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 
387 struct Expected
388 {
395  Expected (uint32_t n_, uint32_t start_, uint32_t end_)
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 
408  uint32_t n;
409  uint32_t start;
410  uint32_t end;
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 
436 class PacketTest : public TestCase
437 {
438 public:
439  PacketTest ();
440  virtual void DoRun (void);
441 private:
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 
463 void
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 
500 void
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 
539 void
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");
702  p.RemoveAllPacketTags ();
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 {
868 public:
870  virtual ~PacketTagListTest ();
871 private:
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 
922 void
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 
951 void
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 
966 int
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 
988 int
989 PacketTagListTest::AddRemoveTime (const bool verbose /* = false */)
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 
1010 void
1012 {
1013  std::cout << GetName () << "begin" << std::endl;
1014 
1015  MAKE_TEST_TAGS ;
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 {
1161 public:
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:1853
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.