Added wifi-information-element-vector
authorKirill Andreev <andreev@iitp.ru>
Fri, 31 Jul 2009 14:13:10 +0400
changeset 5139 87eb2f77f661
parent 5138 b193dca2b479
child 5140 64084ae6cff1
Added wifi-information-element-vector
src/devices/mesh/dot11s/peer-management-protocol-mac.cc
src/devices/mesh/ie-vector.cc
src/devices/mesh/ie-vector.h
src/devices/mesh/wifi-information-element.cc
src/devices/mesh/wifi-information-element.h
src/devices/mesh/wscript
--- a/src/devices/mesh/dot11s/peer-management-protocol-mac.cc	Wed Jul 29 11:19:59 2009 +0400
+++ b/src/devices/mesh/dot11s/peer-management-protocol-mac.cc	Fri Jul 31 14:13:10 2009 +0400
@@ -27,6 +27,8 @@
 #include "ns3/mesh-wifi-interface-mac.h"
 #include "ns3/simulator.h"
 #include "ns3/wifi-mac-header.h"
+#include "ns3/ie-vector.h"
+#include "ns3/log.h"
 namespace ns3 {
 namespace dot11s {
 PeerManagementProtocolMac::PeerManagementProtocolMac (uint32_t interface,
@@ -54,18 +56,22 @@
   Ptr<Packet> packet = const_packet->Copy ();
   if (header.IsBeacon ())
     {
-      IeBeaconTiming beaconTiming;
-      IeMeshId meshId;
-      Ptr<Packet> myBeacon = packet->Copy ();
       MgtBeaconHeader beacon_hdr;
-      myBeacon->RemoveHeader (beacon_hdr);
-      meshId.FindFirst (myBeacon);
+      packet->RemoveHeader (beacon_hdr);
+      //meshId.FindFirst (myBeacon);
       bool meshBeacon = false;
-      if ((beaconTiming.FindFirst (myBeacon)) && (m_protocol->GetMeshId ()->IsEqual (meshId)))
+      WifiInformationElementVector elements = WifiInformationElementVector::DeserializePacket (packet);
+      Ptr<IeBeaconTiming> beaconTiming = DynamicCast<IeBeaconTiming> (elements.FindFirst (IE11S_BEACON_TIMING));
+      Ptr<IeMeshId> meshId = DynamicCast<IeMeshId> (elements.FindFirst (IE11S_MESH_ID));
+
+      if ((beaconTiming != 0) && (meshId != 0))
         {
-          meshBeacon = true;
+          if (m_protocol->GetMeshId ()->IsEqual (*meshId))
+            {
+              meshBeacon = true;
+            }
         }
-      m_protocol->UpdatePeerBeaconTiming (m_ifIndex, meshBeacon, beaconTiming, header.GetAddr2 (),
+      m_protocol->UpdatePeerBeaconTiming (m_ifIndex, meshBeacon, *beaconTiming, header.GetAddr2 (),
           Simulator::Now (), MicroSeconds (beacon_hdr.GetBeaconIntervalUs ()));
       // Beacon shall not be dropeed. May be needed to another plugins
       return true;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/ie-vector.cc	Fri Jul 31 14:13:10 2009 +0400
@@ -0,0 +1,212 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ie-vector.h"
+#include "ns3/test.h"
+#include "ns3/packet.h"
+// All information elements:
+#include "dot11s/ie-dot11s-beacon-timing.h"
+#include "dot11s/ie-dot11s-configuration.h"
+#include "dot11s/ie-dot11s-id.h"
+#include "dot11s/ie-dot11s-metric-report.h"
+#include "dot11s/ie-dot11s-peer-management.h"
+#include "dot11s/ie-dot11s-peering-protocol.h"
+#include "dot11s/ie-dot11s-perr.h"
+#include "dot11s/ie-dot11s-prep.h"
+#include "dot11s/ie-dot11s-preq.h"
+#include "dot11s/ie-dot11s-rann.h"
+
+namespace ns3 {
+WifiInformationElementVector::WifiInformationElementVector () :
+  m_maxSize (1500)
+{
+}
+WifiInformationElementVector::~WifiInformationElementVector ()
+{
+}
+void
+WifiInformationElementVector::SetMaxSize (uint16_t size)
+{
+  m_maxSize = size;
+}
+WifiInformationElementVector::Iterator
+WifiInformationElementVector::Begin ()
+{
+  return m_elements.begin ();
+}
+WifiInformationElementVector::Iterator
+WifiInformationElementVector::End ()
+{
+  return m_elements.end ();
+}
+bool
+WifiInformationElementVector::AddInformationElement (Ptr<WifiInformationElement> element)
+{
+  if (element->GetSerializedSize () + GetSize () > m_maxSize)
+    {
+      return false;
+    }
+  m_elements.push_back (element);
+  return true;
+}
+Ptr<WifiInformationElement>
+WifiInformationElementVector::FindFirst (enum WifiElementId id) const
+{
+  for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
+    {
+      if ((*i)->ElementId () == id)
+        {
+          return (*i);
+        }
+    }
+  return 0;
+}
+WifiInformationElementVector
+WifiInformationElementVector::DeserializePacket (Ptr<Packet> packet)
+{
+  WifiInformationElementVector retval;
+  EmptyIe ie;
+  while (packet->PeekHeader (ie))
+    {
+      Ptr<WifiInformationElement> newElement;
+      switch (ie.GetElementId ())
+        {
+      case IE11S_MESH_CONFIGURATION:
+        newElement = Create<dot11s::IeConfiguration> ();
+        break;
+      case IE11S_MESH_ID:
+        newElement = Create<dot11s::IeMeshId> ();
+        break;
+      case IE11S_LINK_METRIC_REPORT:
+        newElement = Create<dot11s::IeLinkMetricReport> ();
+        break;
+      case IE11S_PEERING_MANAGEMENT:
+        newElement = Create<dot11s::IePeerManagement> ();
+        break;
+      case IE11S_BEACON_TIMING:
+        newElement = Create<dot11s::IeBeaconTiming> ();
+        break;
+      case IE11S_RANN:
+        newElement = Create<dot11s::IeRann> ();
+        break;
+      case IE11S_PREQ:
+        newElement = Create<dot11s::IePreq> ();
+        break;
+      case IE11S_PREP:
+        newElement = Create<dot11s::IePrep> ();
+        break;
+      case IE11S_PERR:
+        newElement = Create<dot11s::IePerr> ();
+        break;
+      case IE11S_MESH_PEERING_PROTOCOL_VERSION:
+        newElement = Create<dot11s::IePeeringProtocol> ();
+        break;
+      default:
+        NS_FATAL_ERROR ("Information element " << (uint16_t) ie.GetElementId () << " is not implemented");
+        }
+      packet->RemoveHeader (*newElement);
+      if (!retval.AddInformationElement (newElement))
+        {
+          NS_FATAL_ERROR ("Check max size for information element!");
+        }
+      if (packet->GetSize () == 0)
+        {
+          return retval;
+        }
+    }
+  return retval;
+}
+Ptr<Packet>
+WifiInformationElementVector::MakePacket (bool sortByElementId)
+{
+  if (sortByElementId)
+    {
+      //TODO: sort
+    }
+  Ptr<Packet> packet = Create<Packet> ();
+  for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
+    {
+      packet->AddHeader (**i);
+    }
+  return packet;
+}
+uint32_t
+WifiInformationElementVector::GetSize () const
+{
+  uint32_t size = 0;
+  for (IE_VECTOR::const_iterator i = m_elements.begin (); i != m_elements.end (); i++)
+    {
+      size += (*i)->GetSerializedSize ();
+    }
+  return size;
+}
+WifiInformationElementVector::EmptyIe::~EmptyIe ()
+{
+}
+WifiInformationElementVector::EmptyIe::EmptyIe () :
+  m_elementId (0), m_length (0)
+{
+}
+TypeId
+WifiInformationElementVector::EmptyIe::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::WifiInformationElementVector::EmptyIe")
+    .SetParent<Header> ();
+  return tid;
+}
+TypeId
+WifiInformationElementVector::EmptyIe::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+uint8_t
+WifiInformationElementVector::EmptyIe::GetLength ()
+{
+  return m_length;
+}
+uint8_t
+WifiInformationElementVector::EmptyIe::GetElementId ()
+{
+  return m_elementId;
+}
+uint32_t
+WifiInformationElementVector::EmptyIe::GetSerializedSize () const
+{
+  return 2;
+}
+void
+WifiInformationElementVector::EmptyIe::Serialize (Buffer::Iterator start) const
+{
+  start.WriteU8 (m_elementId);
+  start.WriteU8 (m_length);
+}
+uint32_t
+WifiInformationElementVector::EmptyIe::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  m_elementId = i.ReadU8 ();
+  m_length = i.ReadU8 ();
+  return i.GetDistanceFrom (start);
+}
+void
+WifiInformationElementVector::EmptyIe::Print (std::ostream &os) const
+{
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/devices/mesh/ie-vector.h	Fri Jul 31 14:13:10 2009 +0400
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * Author: Kirill Andreev <andreev@iitp.ru>
+ */
+
+#ifndef IE_VECTOR_H
+#define IE_VECTOR_H
+
+#include "ns3/wifi-information-element.h"
+
+namespace ns3 {
+class Packet;
+/**
+ * \ingroup mesh
+ *
+ * \brief Information element vector
+ *
+ * Implements a vector of WifiInformationElement's
+ */
+class WifiInformationElementVector
+{
+public:
+  WifiInformationElementVector ();
+  ~WifiInformationElementVector ();
+  void SetMaxSize (uint16_t size);
+  typedef std::vector<Ptr<WifiInformationElement> >::iterator Iterator;
+  Iterator Begin ();
+  Iterator End ();
+  bool AddInformationElement (Ptr<WifiInformationElement> element);
+  Ptr<WifiInformationElement> FindFirst (enum WifiElementId id) const;
+  static WifiInformationElementVector DeserializePacket (Ptr<Packet> packet);
+  Ptr<Packet> MakePacket (bool sortByElementId = true);
+private:
+  uint32_t GetSize () const;
+  /**
+   * \brief Implements an empty information element: just elementId and length.
+   * \details Needed to understand, which information element we need to deserialize now
+   */
+  class EmptyIe : public Header
+  {
+  public:
+    EmptyIe ();
+    virtual ~EmptyIe ();
+    static TypeId GetTypeId ();
+    TypeId GetInstanceTypeId () const;
+    uint8_t GetLength ();
+    uint8_t GetElementId ();
+    virtual uint32_t GetSerializedSize () const;
+    virtual void Serialize (Buffer::Iterator start) const;
+    virtual uint32_t Deserialize (Buffer::Iterator start);
+    virtual void Print (std::ostream &os) const;
+  private:
+    uint8_t m_elementId;
+    uint8_t m_length;
+  };
+  typedef std::vector<Ptr<WifiInformationElement> > IE_VECTOR;
+  IE_VECTOR m_elements;
+  /// Size in bytes (actually, max packet length)
+  uint16_t m_maxSize;
+};
+}
+#endif
--- a/src/devices/mesh/wifi-information-element.cc	Wed Jul 29 11:19:59 2009 +0400
+++ b/src/devices/mesh/wifi-information-element.cc	Fri Jul 31 14:13:10 2009 +0400
@@ -70,33 +70,6 @@
   PrintInformation (os);
   os << "</information_element>\n";
 }
-
-bool
-WifiInformationElement::FindFirst (Ptr<Packet> packet)
-{
-  const uint8_t * data = packet->PeekData ();
-  uint32_t position = 0;
-  while (position < packet->GetSize ())
-    {
-      if (data[position] == ElementId ())
-        {
-          Ptr<Packet> myIe = packet->CreateFragment (position, data[position + 1] + 2);
-          NS_ASSERT (myIe->GetSize () == (uint32_t) (data[position + 1] + 2));
-          myIe->RemoveHeader (*this);
-          return true;
-        }
-      else
-        {
-          if (data[position] > ElementId ())
-            {
-              return false;
-            }
-          position += data[position + 1] + 2;
-        }
-    }
-  return false;
-}
-
 bool
 operator< (WifiInformationElement const & a, WifiInformationElement const & b)
 {
--- a/src/devices/mesh/wifi-information-element.h	Wed Jul 29 11:19:59 2009 +0400
+++ b/src/devices/mesh/wifi-information-element.h	Fri Jul 31 14:13:10 2009 +0400
@@ -1,7 +1,7 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/* 
+/*
  * Copyright (c) 2009 IITP RAS
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation;
@@ -14,7 +14,7 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
+ *
  * Author: Pavel Boyko <boyko@iitp.ru>
  */
 
@@ -30,14 +30,14 @@
 class Packet;
 /**
  * \ingroup mesh
- * 
- * \brief Enum of all known information element id (aka tags). 
- * 
- * For now only 802.11s (mesh) related elements are supported here (so 11S prefix), 
+ *
+ * \brief Enum of all known information element id (aka tags).
+ *
+ * For now only 802.11s (mesh) related elements are supported here (so 11S prefix),
  * but this can change in future.
- * 
- * Note that 802.11s element ids are not yet officially assigned, we use ones 
- * compatible with open80211s (http://o11s.org/) implementation.   
+ *
+ * Note that 802.11s element ids are not yet officially assigned, we use ones
+ * compatible with open80211s (http://o11s.org/) implementation.
  */
 enum WifiElementId {
   /* begin of open80211s-compatible IDs */
@@ -63,35 +63,35 @@
   /* begin of open80211s-compatible IDs */
   IE11S_PREQ                            = 68,
   IE11S_PREP                            = 69,
-  IE11S_PERR                            = 70, 
+  IE11S_PERR                            = 70,
   /* end of open80211s-compatible IDs */
   IE11S_PROXY_UPDATE                    = 37,
   IE11S_PROXY_UPDATE_CONFIRMATION,
   IE11S_ABBREVIATED_HANDSHAKE,
   IE11S_MESH_PEERING_PROTOCOL_VERSION   = 74,
-};  
-  
+};
+
 /**
  * \ingroup mesh
- * 
+ *
  * \brief Information element, as defined in 802.11-2007 standard
- * 
+ *
  * Elements are defined to have a common general format consisting of a 1 octet Element ID field, a 1 octet
  * length field, and a variable-length element-specific information field. Each element is assigned a unique
  * Element ID as defined in this standard. The Length field specifies the number of octets in the Information
- * field. 
+ * field.
  */
-class WifiInformationElement : public Header, 
-                               public RefCountBase     // need this to use Ptr<WifiInformationElement> 
+class WifiInformationElement : public Header,
+                               public RefCountBase     // need this to use Ptr<WifiInformationElement>
 {
 public:
   /// Support object system
   static TypeId GetTypeId ();
   TypeId GetInstanceTypeId () const;
-  
+
   /// virtual d-tor for subclasses
   virtual ~WifiInformationElement () {}
-  
+
   ///\name Inherited from Header
   //\{
   /**
@@ -120,37 +120,31 @@
    * \return the number of bytes read.
    *
    * This method is used by Packet::RemoveHeader to
-   * re-create a header from the byte buffer of a packet. 
+   * re-create a header from the byte buffer of a packet.
    * The data read is expected to
    * match bit-for-bit the representation of this header in real
    * networks.
    */
   virtual uint32_t Deserialize (Buffer::Iterator start);
   /**
-   * This method is used by Packet::Print to print the 
+   * This method is used by Packet::Print to print the
    * content of a trailer as ascii data to a c++ output stream.
    * Although the trailer is free to format its output as it
    * wishes, it is recommended to follow a few rules to integrate
-   * with the packet pretty printer: start with flags, small field 
-   * values located between a pair of parens. Values should be separated 
-   * by whitespace. Follow the parens with the important fields, 
+   * with the packet pretty printer: start with flags, small field
+   * values located between a pair of parens. Values should be separated
+   * by whitespace. Follow the parens with the important fields,
    * separated by whitespace.
    * i.e.: (field1 val1 field2 val2 field3 val3) field4 val4 field5 val5
    */
   virtual void Print (std::ostream &os) const;
-  /**
-   * This method takes a packet which must be a list of information
-   * elements and looks for an information element of MINE Element ID
-   */
-  bool FindFirst (Ptr<Packet> packet);
   //\}
-    
-protected:
-  ///\name Each subclass must implement 
+  ///\name Each subclass must implement
   //\{
   /// Own unique Element ID
   virtual WifiElementId ElementId () const = 0;
   /// Length of serialized information
+protected:
   virtual uint8_t GetInformationSize () const = 0;
   /// Serialize information
   virtual void SerializeInformation (Buffer::Iterator start) const = 0;
@@ -159,7 +153,7 @@
   /// Print information
   virtual void PrintInformation (std::ostream &os) const = 0;
   //\}
-  
+
   /// Compare information elements using Element ID
   friend bool operator< (WifiInformationElement const & a, WifiInformationElement const & b);
 };
@@ -173,7 +167,7 @@
 {
 public:
   IeTest (const char * name) : Test (name) {}
-  /// Test roundtrip serialization
+  /// Test round-trip serialization
   template <typename IE> bool TestRoundtripSerialization (IE a);
 };
 
@@ -181,7 +175,7 @@
 IeTest::TestRoundtripSerialization (IE a)
 {
   bool result (true);
-  
+
   Ptr<Packet> packet = Create<Packet> ();
   packet->AddHeader (a);
   IE b;
@@ -189,13 +183,13 @@
   NS_TEST_ASSERT_EQUAL (a, b);
   packet->AddHeader (a);
   IE c;
-  bool ok = c.FindFirst (packet);
+  bool ok = packet->RemoveHeader (c);
   NS_TEST_ASSERT (ok);
   NS_TEST_ASSERT_EQUAL (a, c);
-  
+
   return result;
 }
-#endif 
+#endif
 
 }  // namespace ns3
 #endif /* WIFIINFORMATIONELEMENT_H_ */
--- a/src/devices/mesh/wscript	Wed Jul 29 11:19:59 2009 +0400
+++ b/src/devices/mesh/wscript	Fri Jul 31 14:13:10 2009 +0400
@@ -5,6 +5,7 @@
 
     obj.source = [
         'wifi-information-element.cc',
+        'ie-vector.cc',
         'mesh-point-device.cc',
         'mesh-l2-routing-protocol.cc',
         'mesh-wifi-beacon.cc',
@@ -14,6 +15,7 @@
     headers.module = 'mesh'
     headers.source = [
         'wifi-information-element.h',
+        'ie-vector.h',
         'mesh-point-device.h',
         'mesh-l2-routing-protocol.h',
         'mesh-wifi-beacon.h',