src/devices/mesh/wifi-information-element-vector.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Thu Nov 12 13:01:01 2009 +0100 (2009-11-12)
changeset 5505 c0ac392289c3
parent 5499 778d4dcaaac7
permissions -rw-r--r--
replace RefCountBase with SimpleRefCount<> to avoid duplicate refcounting implementations.
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2009 IITP RAS
     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: Pavel Boyko <boyko@iitp.ru>
    19  */
    20 
    21 #include "wifi-information-element-vector.h"
    22 #include "ns3/packet.h"
    23 #include <algorithm>
    24 #include "ns3/test.h"
    25 #include "ns3/hwmp-protocol.h"
    26 // All information elements:
    27 #include "dot11s/ie-dot11s-beacon-timing.h"
    28 #include "dot11s/ie-dot11s-configuration.h"
    29 #include "dot11s/ie-dot11s-id.h"
    30 #include "dot11s/ie-dot11s-metric-report.h"
    31 #include "dot11s/ie-dot11s-peer-management.h"
    32 #include "dot11s/ie-dot11s-peering-protocol.h"
    33 #include "dot11s/ie-dot11s-perr.h"
    34 #include "dot11s/ie-dot11s-prep.h"
    35 #include "dot11s/ie-dot11s-preq.h"
    36 #include "dot11s/ie-dot11s-rann.h"
    37 
    38 namespace ns3 {
    39 
    40 WifiInformationElement::~WifiInformationElement ()
    41 {}
    42 
    43 bool
    44 operator< (WifiInformationElement const & a, WifiInformationElement const & b)
    45 {
    46   return (a.ElementId () < b.ElementId ());
    47 }
    48 
    49 WifiInformationElementVector::WifiInformationElementVector () :
    50   m_maxSize (1500)
    51 {
    52 }
    53 WifiInformationElementVector::~WifiInformationElementVector ()
    54 {
    55   for (IE_VECTOR::iterator i = m_elements.begin (); i != m_elements.end (); i++)
    56     {
    57       *i = 0;
    58     }
    59   m_elements.clear ();
    60 }
    61 TypeId
    62 WifiInformationElementVector::GetTypeId ()
    63 {
    64   static TypeId tid = TypeId ("ns3::WifiInformationElementVector")
    65                       .SetParent<Header> ()
    66                       .AddConstructor<WifiInformationElementVector> ();
    67   return tid;
    68 }
    69 TypeId
    70 WifiInformationElementVector::GetInstanceTypeId () const
    71 {
    72   return GetTypeId ();
    73 }
    74 uint32_t
    75 WifiInformationElementVector::GetSerializedSize () const
    76 {
    77   return GetSize ();
    78 }
    79 void
    80 WifiInformationElementVector::Serialize (Buffer::Iterator start) const
    81 {
    82   for(IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i ++)
    83     {
    84       start.WriteU8((*i)->ElementId ());
    85       start.WriteU8 ((*i)->GetInformationSize ());
    86       (*i)->SerializeInformation (start);
    87       start.Next ((*i)->GetInformationSize ());
    88     }
    89 }
    90 uint32_t
    91 WifiInformationElementVector::Deserialize (Buffer::Iterator start)
    92 {
    93   Buffer::Iterator i = start;
    94   uint32_t size = start.GetSize();
    95   while (size > 0)
    96     {
    97       uint32_t deserialized = DeserializeSingleIe(i);
    98       i.Next (deserialized);
    99       size -= deserialized;
   100     }
   101   return i.GetDistanceFrom(start);
   102 }
   103 uint32_t
   104 WifiInformationElementVector::DeserializeSingleIe(Buffer::Iterator start)
   105 {
   106   Buffer::Iterator i = start;
   107   uint8_t id = i.ReadU8 ();
   108   uint8_t length = i.ReadU8 ();
   109   Ptr<WifiInformationElement> newElement;
   110   switch (id)
   111     {
   112   case IE11S_MESH_CONFIGURATION:
   113     newElement = Create<dot11s::IeConfiguration> ();
   114     break;
   115   case IE11S_MESH_ID:
   116     newElement = Create<dot11s::IeMeshId> ();
   117     break;
   118   case IE11S_LINK_METRIC_REPORT:
   119     newElement = Create<dot11s::IeLinkMetricReport> ();
   120     break;
   121   case IE11S_PEERING_MANAGEMENT:
   122     newElement = Create<dot11s::IePeerManagement> ();
   123     break;
   124   case IE11S_BEACON_TIMING:
   125     newElement = Create<dot11s::IeBeaconTiming> ();
   126     break;
   127   case IE11S_RANN:
   128     newElement = Create<dot11s::IeRann> ();
   129     break;
   130   case IE11S_PREQ:
   131     newElement = Create<dot11s::IePreq> ();
   132     break;
   133   case IE11S_PREP:
   134     newElement = Create<dot11s::IePrep> ();
   135     break;
   136   case IE11S_PERR:
   137     newElement = Create<dot11s::IePerr> ();
   138     break;
   139   case IE11S_MESH_PEERING_PROTOCOL_VERSION:
   140     newElement = Create<dot11s::IePeeringProtocol> ();
   141     break;
   142   default:
   143     NS_FATAL_ERROR ("Information element " << (uint16_t) id << " is not implemented");
   144     return 0;
   145     }
   146   if (GetSize () + length > m_maxSize)
   147     {
   148       NS_FATAL_ERROR ("Check max size for information element!");
   149     }
   150   newElement->DeserializeInformation (i, length);
   151   i.Next (length);
   152   m_elements.push_back (newElement);
   153   return i.GetDistanceFrom(start);
   154 }
   155 void
   156 WifiInformationElementVector::Print(std::ostream & os) const
   157 {
   158   //TODO
   159 }
   160 void
   161 WifiInformationElementVector::SetMaxSize (uint16_t size)
   162 {
   163   m_maxSize = size;
   164 }
   165 WifiInformationElementVector::Iterator
   166 WifiInformationElementVector::Begin ()
   167 {
   168   return m_elements.begin ();
   169 }
   170 WifiInformationElementVector::Iterator
   171 WifiInformationElementVector::End ()
   172 {
   173   return m_elements.end ();
   174 }
   175 bool
   176 WifiInformationElementVector::AddInformationElement (Ptr<WifiInformationElement> element)
   177 {
   178   if (element->GetInformationSize () + 2 + GetSize () > m_maxSize)
   179     {
   180       return false;
   181     }
   182   m_elements.push_back (element);
   183   return true;
   184 }
   185 Ptr<WifiInformationElement>
   186 WifiInformationElementVector::FindFirst (enum WifiElementId id) const
   187 {
   188   for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
   189     {
   190       if ((*i)->ElementId () == id)
   191         {
   192           return (*i);
   193         }
   194     }
   195   return 0;
   196 }
   197 namespace {
   198 struct PIEComparator
   199 {
   200   bool
   201   operator () (Ptr<WifiInformationElement> a, Ptr<WifiInformationElement> b) const
   202   {
   203     return ((*PeekPointer (a)) < (*PeekPointer (b)));
   204   }
   205 };
   206 }
   207 uint32_t
   208 WifiInformationElementVector::GetSize () const
   209 {
   210   uint32_t size = 0;
   211   for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
   212     {
   213       size += ((*i)->GetInformationSize () + 2);
   214     }
   215   return size;
   216 }
   217 
   218 bool
   219 operator== (const WifiInformationElementVector & a, const WifiInformationElementVector & b)
   220 {
   221   if (a.m_elements.size () != b.m_elements.size ())
   222     {
   223       NS_ASSERT(false);
   224       return false;
   225     }
   226   WifiInformationElementVector::IE_VECTOR::const_iterator j = b.m_elements.begin ();
   227   for (WifiInformationElementVector::IE_VECTOR::const_iterator i = a.m_elements.begin (); i
   228       != a.m_elements.end (); i++, j++)
   229     {
   230       if ((*i)->ElementId () != (*j)->ElementId ())
   231         {
   232           return false;
   233         }
   234       if ((*i)->GetInformationSize () != (*j)->GetInformationSize ())
   235         {
   236           return false;
   237         }
   238       uint8_t id = (*i)->ElementId ();
   239       switch (id)
   240         {
   241       case IE11S_MESH_CONFIGURATION:
   242         if (DynamicCast<dot11s::IeConfiguration> ((*i)) == 0)
   243           {
   244             return false;
   245           }
   246         if (DynamicCast<dot11s::IeConfiguration> ((*j)) == 0)
   247           {
   248             return false;
   249           }
   250         if (!(*DynamicCast<dot11s::IeConfiguration> ((*i)) == *DynamicCast<dot11s::IeConfiguration> ((*j))))
   251           {
   252             return false;
   253           }
   254         break;
   255       case IE11S_MESH_ID:
   256         if (DynamicCast<dot11s::IeMeshId> ((*i)) == 0)
   257           {
   258             return false;
   259           }
   260         if (DynamicCast<dot11s::IeMeshId> ((*j)) == 0)
   261           {
   262             return false;
   263           }
   264         if (!(*DynamicCast<dot11s::IeMeshId> ((*i)) == *DynamicCast<dot11s::IeMeshId> ((*j))))
   265           {
   266             return false;
   267           }
   268         break;
   269       case IE11S_LINK_METRIC_REPORT:
   270         if (DynamicCast<dot11s::IeLinkMetricReport> ((*i)) == 0)
   271           {
   272             return false;
   273           }
   274         if (DynamicCast<dot11s::IeLinkMetricReport> ((*j)) == 0)
   275           {
   276             return false;
   277           }
   278         if (!(*DynamicCast<dot11s::IeLinkMetricReport> ((*i)) == *DynamicCast<dot11s::IeLinkMetricReport> (
   279             (*j))))
   280           {
   281             return false;
   282           }
   283         break;
   284       case IE11S_PEERING_MANAGEMENT:
   285         if (DynamicCast<dot11s::IePeerManagement> ((*i)) == 0)
   286           {
   287             return false;
   288           }
   289         if (DynamicCast<dot11s::IePeerManagement> ((*j)) == 0)
   290           {
   291             return false;
   292           }
   293         if (!(*DynamicCast<dot11s::IePeerManagement> ((*i)) == *DynamicCast<dot11s::IePeerManagement> ((*j))))
   294           {
   295             return false;
   296           }
   297         break;
   298       case IE11S_BEACON_TIMING:
   299         if (DynamicCast<dot11s::IeBeaconTiming> ((*i)) == 0)
   300           {
   301             return false;
   302           }
   303         if (DynamicCast<dot11s::IeBeaconTiming> ((*j)) == 0)
   304           {
   305             return false;
   306           }
   307         if (!(*DynamicCast<dot11s::IeBeaconTiming> ((*i)) == *DynamicCast<dot11s::IeBeaconTiming> ((*j))))
   308           {
   309             return false;
   310           }
   311         break;
   312       case IE11S_RANN:
   313         if (DynamicCast<dot11s::IeRann> ((*i)) == 0)
   314           {
   315             return false;
   316           }
   317         if (DynamicCast<dot11s::IeRann> ((*j)) == 0)
   318           {
   319             return false;
   320           }
   321         if (!(*DynamicCast<dot11s::IeRann> ((*i)) == *DynamicCast<dot11s::IeRann> ((*j))))
   322           {
   323             return false;
   324           }
   325         break;
   326       case IE11S_PREQ:
   327         if (DynamicCast<dot11s::IePreq> ((*i)) == 0)
   328           {
   329             return false;
   330           }
   331         if (DynamicCast<dot11s::IePreq> ((*j)) == 0)
   332           {
   333             return false;
   334           }
   335         if (!(*DynamicCast<dot11s::IePreq> ((*i)) == *DynamicCast<dot11s::IePreq> ((*j))))
   336           {
   337             return false;
   338           }
   339         break;
   340       case IE11S_PREP:
   341         if (DynamicCast<dot11s::IePrep> ((*i)) == 0)
   342           {
   343             return false;
   344           }
   345         if (DynamicCast<dot11s::IePrep> ((*j)) == 0)
   346           {
   347             return false;
   348           }
   349         if (!(*DynamicCast<dot11s::IePrep> ((*i)) == *DynamicCast<dot11s::IePrep> ((*j))))
   350           {
   351             return false;
   352           }
   353 
   354         break;
   355       case IE11S_PERR:
   356         if (DynamicCast<dot11s::IePerr> ((*i)) == 0)
   357           {
   358             return false;
   359           }
   360         if (DynamicCast<dot11s::IePerr> ((*j)) == 0)
   361           {
   362             return false;
   363           }
   364         if (!(*DynamicCast<dot11s::IePerr> ((*i)) == *DynamicCast<dot11s::IePerr> ((*j))))
   365           {
   366             return false;
   367           }
   368         break;
   369       case IE11S_MESH_PEERING_PROTOCOL_VERSION:
   370         break;
   371       default:
   372         NS_FATAL_ERROR ("Information element " << (uint16_t) id << " is not implemented");
   373         return false;
   374         }
   375     }
   376   return true;
   377 }
   378 
   379 //-----------------------------------------------------------------------------
   380 // Unit tests
   381 //-----------------------------------------------------------------------------
   382 /// Built-in self test for WifiInformationElementVector and all IE
   383 struct WifiInformationElementVectorBist : public TestCase
   384 {
   385   WifiInformationElementVectorBist () :
   386     TestCase ("Serializarion test for all mesh information elements")
   387   {
   388   };
   389   bool DoRun ();
   390 };
   391 
   392 bool
   393 WifiInformationElementVectorBist::DoRun ()
   394 {
   395   WifiInformationElementVector vector;
   396   {
   397     //Mesh ID test
   398     Ptr<dot11s::IeMeshId> meshId = Create<dot11s::IeMeshId> ("qwerty");
   399     vector.AddInformationElement (meshId);
   400   }
   401   {
   402     Ptr<dot11s::IeConfiguration> config = Create<dot11s::IeConfiguration> ();
   403     vector.AddInformationElement (config);
   404   }
   405   {
   406     Ptr<dot11s::IeLinkMetricReport> report = Create<dot11s::IeLinkMetricReport> (123456);
   407     vector.AddInformationElement (report);
   408   }
   409   {
   410     Ptr<dot11s::IePeerManagement> peerMan1 = Create<dot11s::IePeerManagement> ();
   411     peerMan1->SetPeerOpen (1);
   412     Ptr<dot11s::IePeerManagement> peerMan2 = Create<dot11s::IePeerManagement> ();
   413     peerMan2->SetPeerConfirm (1, 2);
   414     Ptr<dot11s::IePeerManagement> peerMan3 = Create<dot11s::IePeerManagement> ();
   415     peerMan3->SetPeerClose (1, 2, dot11s::REASON11S_MESH_CAPABILITY_POLICY_VIOLATION);
   416     vector.AddInformationElement (peerMan1);
   417     vector.AddInformationElement (peerMan2);
   418     vector.AddInformationElement (peerMan3);
   419   }
   420   {
   421     Ptr<dot11s::IeBeaconTiming>  beaconTiming = Create<dot11s::IeBeaconTiming> ();
   422     beaconTiming->AddNeighboursTimingElementUnit (1, Seconds (1.0), Seconds (4.0));
   423     beaconTiming->AddNeighboursTimingElementUnit (2, Seconds (2.0), Seconds (3.0));
   424     beaconTiming->AddNeighboursTimingElementUnit (3, Seconds (3.0), Seconds (2.0));
   425     beaconTiming->AddNeighboursTimingElementUnit (4, Seconds (4.0), Seconds (1.0));
   426     vector.AddInformationElement (beaconTiming);
   427   }
   428   {
   429     Ptr<dot11s::IeRann> rann = Create<dot11s::IeRann> ();
   430     rann->SetFlags (1);
   431     rann->SetHopcount (2);
   432     rann->SetTTL (4);
   433     rann->DecrementTtl ();
   434     NS_TEST_ASSERT_MSG_EQ (rann->GetTtl (), 3, "SetTtl works");
   435     rann->SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
   436     rann->SetDestSeqNumber (5);
   437     rann->SetMetric (6);
   438     rann->IncrementMetric (2);
   439     NS_TEST_ASSERT_MSG_EQ (rann->GetMetric (), 8, "SetMetric works");
   440     vector.AddInformationElement (rann);
   441   }
   442   {
   443     Ptr<dot11s::IePreq> preq = Create<dot11s::IePreq> ();
   444     preq->SetHopcount (0);
   445     preq->SetTTL (1);
   446     preq->SetPreqID (2);
   447     preq->SetOriginatorAddress (Mac48Address ("11:22:33:44:55:66"));
   448     preq->SetOriginatorSeqNumber (3);
   449     preq->SetLifetime (4);
   450     preq->AddDestinationAddressElement (false, false, Mac48Address ("11:11:11:11:11:11"), 5);
   451     preq->AddDestinationAddressElement (false, false, Mac48Address ("22:22:22:22:22:22"), 6);
   452     vector.AddInformationElement (preq);
   453   }
   454   {
   455     Ptr<dot11s::IePrep> prep = Create<dot11s::IePrep> ();
   456     prep->SetFlags (12);
   457     prep->SetHopcount (11);
   458     prep->SetTtl (10);
   459     prep->SetDestinationAddress (Mac48Address ("11:22:33:44:55:66"));
   460     prep->SetDestinationSeqNumber (123);
   461     prep->SetLifetime (5000);
   462     prep->SetMetric (4321);
   463     prep->SetOriginatorAddress (Mac48Address ("33:00:22:00:11:00"));
   464     prep->SetOriginatorSeqNumber (666);
   465     vector.AddInformationElement (prep);
   466   }
   467   {
   468     Ptr<dot11s::IePerr> perr = Create<dot11s::IePerr> ();
   469     dot11s::HwmpProtocol::FailedDestination dest;
   470     dest.destination = Mac48Address ("11:22:33:44:55:66");
   471     dest.seqnum = 1;
   472     perr->AddAddressUnit (dest);
   473     dest.destination = Mac48Address ("10:20:30:40:50:60");
   474     dest.seqnum = 2;
   475     perr->AddAddressUnit (dest);
   476     dest.destination = Mac48Address ("01:02:03:04:05:06");
   477     dest.seqnum = 3;
   478     perr->AddAddressUnit (dest);
   479     vector.AddInformationElement (perr);
   480   }
   481   Ptr<Packet> packet = Create<Packet> ();
   482   packet->AddHeader (vector);
   483   WifiInformationElementVector resultVector;
   484   packet->RemoveHeader (resultVector);
   485   NS_TEST_ASSERT_MSG_EQ (vector, resultVector, "Roundtrip serialization of all known information elements works");
   486   
   487   return false;
   488 }
   489 
   490 class MeshTestSuite : public TestSuite
   491 {
   492 public:
   493   MeshTestSuite ();
   494 };
   495 
   496 MeshTestSuite::MeshTestSuite ()
   497   : TestSuite ("devices-mesh", UNIT)
   498 {
   499   AddTestCase (new WifiInformationElementVectorBist);
   500 }
   501 
   502 MeshTestSuite g_meshTestSuite;
   503 
   504 } //namespace ns3