First PREQ delivered
authorKirill Andreev <andreev@iitp.ru>
Fri, 27 Mar 2009 20:03:13 +0300
changeset 4895 b68a1309a89e
parent 4894 a6cf8696922a
child 4896 e579c19f0dee
First PREQ delivered
examples/mesh.cc
src/devices/mesh/dot11s/hwmp-mac-plugin.cc
src/devices/mesh/dot11s/hwmp-mac-plugin.h
src/devices/mesh/dot11s/hwmp-protocol.cc
src/devices/mesh/dot11s/hwmp-protocol.h
src/devices/mesh/dot11s/peer-management-plugin.cc
src/devices/mesh/dot11s/peer-management-protocol.cc
--- a/examples/mesh.cc	Fri Mar 27 16:33:08 2009 +0300
+++ b/examples/mesh.cc	Fri Mar 27 20:03:13 2009 +0300
@@ -39,8 +39,8 @@
 main (int argc, char *argv[])
 {
   // Creating square topology with nNodes x nNodes grid:
-  int      xSize       = 3;
-  int      ySize       = 3;
+  int      xSize       = 4;
+  int      ySize       = 4;
   double   step        = 100.0; //Grid with one-hop edge
   double   randomStart = 0.1; //One beacon interval
   NodeContainer      nodes;
--- a/src/devices/mesh/dot11s/hwmp-mac-plugin.cc	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.cc	Fri Mar 27 20:03:13 2009 +0300
@@ -23,7 +23,6 @@
 #include "ns3/simulator.h"
 #include "ns3/nstime.h"
 #include "ns3/log.h"
-#include "ns3/dot11s-parameters.h"
 #include "ns3/mesh-wifi-mac-header.h"
 
 #include "hwmp-mac-plugin.h"
@@ -80,12 +79,55 @@
       if(m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (), header.GetAddr4 ()) )
         return false;
   }
+  if(header.IsMultihopAction())
+  {
+    WifiMeshHeader meshHdr;
+    packet->RemoveHeader (meshHdr);
+    //parse multihop action header:
+    WifiMeshMultihopActionHeader multihopHdr;
+    packet->RemoveHeader (multihopHdr);
+    WifiMeshMultihopActionHeader::ACTION_VALUE actionValue = multihopHdr.GetAction ();
+    if(multihopHdr.GetCategory () != WifiMeshMultihopActionHeader::MESH_PATH_SELECTION)
+      return true;
+    if(meshHdr.GetMeshTtl () == 0)
+        return false;
+    switch (actionValue.pathSelection)
+    {
+      case WifiMeshMultihopActionHeader::PATH_REQUEST:
+        {
+          IePreq preq;
+          NS_ASSERT(false);
+          packet->RemoveHeader (preq);
+          //TODO:recalculate
+          //metric
+          //m_preqReceived (preq, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+          return false;
+        }
+      case WifiMeshMultihopActionHeader::PATH_REPLY:
+        {
+          IePrep prep;
+          packet->RemoveHeader (prep);
+          //m_prepReceived (prep, hdr->GetAddr2(), CalculateMetric(hdr->GetAddr2()));
+          return false;
+        }
+      case WifiMeshMultihopActionHeader::PATH_ERROR:
+        {
+          IePerr perr;
+          packet->RemoveHeader (perr);
+          //m_perrReceived (perr, hdr->GetAddr2());
+          return false;
+        }
+      case WifiMeshMultihopActionHeader::ROOT_ANNOUNCEMENT:
+        return false;
+    }
+  }
   return true;
 }
 bool
 HwmpMacPlugin::UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const
 {
   //TODO: add a mesh header and remove a TAG
+  NS_ASSERT(header.IsData ());
   HwmpTag tag;
   NS_ASSERT(packet->FindFirstMatchingTag(tag));
   WifiMeshHeader meshHdr;
@@ -97,111 +139,49 @@
   return true;
 }
 #if 0
-TypeId
-HwmpMacPlugin::GetTypeId ()
-{
-  static TypeId tid = TypeId ("ns3::HwmpMacPlugin")
-                      .SetParent<Object> ()
-                      .AddConstructor<HwmpMacPlugin> ()
-                      ;
-  return tid;
-}
-
 HwmpMacPlugin::HwmpMacPlugin ():
     m_myPreq (m_preqQueue.end()),
-    m_preqId (1),
-    m_myDsn (1),
-    m_disabled (false),
-    m_maxTtl (10)
 {
 }
-void
-HwmpMacPlugin::SetRequestRouteCallback (
-  Callback<HwmpRtable::LookupResult, const Mac48Address&> cb)
-{
-  m_requestRouteCallback = cb;
-}
 
-void
-HwmpMacPlugin::SetRequestRootPathCallback (
-  Callback<HwmpRtable::LookupResult, uint32_t> cb)
-{
-  m_requestRootPathCallback = cb;
-}
-
-//Setting MAC
-void
-HwmpMacPlugin::SetMac (Ptr<MeshWifiMac> mac)
-{
-  mac->SetPeerStatusCallback (MakeCallback(&HwmpMacPlugin::PeerStatus, this));
-  mac->SetPreqReceivedCallback (MakeCallback(&HwmpMacPlugin::ReceivePreq, this));
-  mac->SetPrepReceivedCallback (MakeCallback(&HwmpMacPlugin::ReceivePrep, this));
-  mac->SetPerrReceivedCallback (MakeCallback(&HwmpMacPlugin::ReceivePerr, this));
-  m_address = mac->GetAddress ();
-  m_preqCallback = MakeCallback (&MeshWifiMac::SendPreq, mac);
-  m_prepCallback = MakeCallback (&MeshWifiMac::SendPrep, mac);
-  m_perrCallback = MakeCallback (&MeshWifiMac::SendPerr, mac);
-}
 HwmpMacPlugin::~HwmpMacPlugin ()
 {
   m_preqQueue.clear ();
 }
 //Interaction with HWMP:
+#endif
 void
-HwmpMacPlugin::SetRoutingInfoCallback (
-  Callback<void, INFO> cb
-)
+HwmpMacPlugin::SendPreq(IePreq, std::vector<Mac48Address> receivers)
 {
-  m_routingInfoCallback = cb;
+  NS_ASSERT(false);
 }
-
-void
-HwmpMacPlugin::SetRetransmittersOfPerrCallback (
-  Callback<std::vector<Mac48Address>, std::vector<HwmpRtable::FailedDestination>, uint32_t> cb)
-{
-  m_retransmittersOfPerrCallback = cb;
-}
-
 void
 HwmpMacPlugin::RequestDestination (Mac48Address dst)
 {
   if (m_preqQueue.end () == m_myPreq)
-    {
-      IeDot11sPreq preq;
-      //fill PREQ:
-      preq.SetHopcount (0);
-      preq.SetTTL (m_maxTtl);
-      preq.SetPreqID (m_preqId++);
-      if (m_preqId == MAX_PREQ_ID)
-        m_preqId = 0;
-      preq.SetLifetime (TIME_TO_TU(dot11sParameters::dot11MeshHWMPactivePathTimeout));
-      preq.SetOriginatorSeqNumber (m_myDsn++);
-      if (m_myDsn == MAX_DSN)
-        m_myDsn = 0;
-      preq.SetOriginatorAddress (m_address);
-      preq.AddDestinationAddressElement (false, false, dst, 0); //DO = 0, RF = 0
-      if (m_preqTimer.IsRunning ())
-        {
-          NS_LOG_DEBUG ("No my preq");
-          m_preqQueue.push_back (preq);
-          //set iterator position to my preq:
-          m_myPreq = m_preqQueue.end () -1;
-        }
-      else
-        {
-          NS_LOG_DEBUG ("Send PREQ now, "<<preq.GetPreqID()<<" destinations, now is "<<Simulator::Now());
-          m_preqCallback (preq);
-          NS_ASSERT (!m_preqTimer.IsRunning());
-          m_preqTimer = Simulator::Schedule (dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpMacPlugin::SendOnePreq, this);
-        }
-    }
+  {
+    IePreq preq;
+    //fill PREQ:
+    preq.SetHopcount (0);
+    preq.SetTTL (m_protocol->GetMaxTtl ());
+    preq.SetPreqID (m_protocol->GetNextPreqId ());
+    preq.SetOriginatorAddress (m_parent->GetAddress ());
+    preq.SetOriginatorSeqNumber (m_protocol->GetNextHwmpSeqno());
+    preq.AddDestinationAddressElement (false, false, dst, 0); //DO = 0, RF = 0
+    m_preqQueue.push_back (preq);
+    //set iterator position to my preq:
+    m_myPreq = m_preqQueue.end () -1;
+    NS_LOG_UNCOND("no preq");
+    SendOnePreq ();
+  }
   else
-    {
-      NS_ASSERT (m_myPreq->GetOriginatorAddress() == m_address);
-      NS_LOG_DEBUG ("add a destination "<<dst);
-      m_myPreq->AddDestinationAddressElement (false, false, dst, 0); //DO = 0, RF = 0
-    }
+  {
+    NS_ASSERT (m_myPreq->GetOriginatorAddress() == m_parent->GetAddress());
+    NS_LOG_UNCOND ("add a destination "<<dst);
+    m_myPreq->AddDestinationAddressElement (false, false, dst, 0); //DO = 0, RF = 0
+  }
 }
+#if 0
 void
 HwmpMacPlugin::SendPathError (std::vector<HwmpRtable::FailedDestination> destinations)
 {
@@ -229,17 +209,6 @@
     }
 }
 //needed to fill routing information structure
-void
-HwmpMacPlugin::SetAssociatedIfaceId (uint32_t interface)
-{
-  m_ifIndex = interface;
-}
-
-uint32_t
-HwmpMacPlugin::GetAssociatedIfaceId ()
-{
-  return m_ifIndex;
-}
 
 //Interaction with MAC:
 void
@@ -472,53 +441,6 @@
     newInfo.type = INFO_FAILED_PEER;
   m_routingInfoCallback (newInfo);
 }
-
-bool
-HwmpMacPlugin::SetRoot ()
-{
-#if 0
-  //TODO:: delete this lines!!!!!!!
-  if (m_address != Mac48Address ("00:00:00:00:00:10"))
-    return false;
-  //TODO
-#endif
-  Simulator::Schedule (dot11sParameters::dot11MeshHWMPactiveRootTimeout, &HwmpMacPlugin::SendProactivePreq, this);
-  return true;
-}
-
-void
-HwmpMacPlugin::SendProactivePreq ()
-{
-  NS_LOG_DEBUG ("Sending proactive PREQ");
-  IeDot11sPreq preq;
-  //By default: must answer
-  preq.SetHopcount (0);
-  preq.SetTTL (m_maxTtl);
-  preq.SetPreqID (m_preqId++);
-  if (m_preqId == MAX_PREQ_ID)
-    m_preqId = 0;
-  preq.SetLifetime (TIME_TO_TU(dot11sParameters::dot11MeshHWMPpathToRootInterval));
-  preq.SetOriginatorSeqNumber (m_myDsn++);
-  if (m_myDsn == MAX_DSN)
-    m_myDsn = 0;
-  preq.SetOriginatorAddress (m_address);
-  preq.AddDestinationAddressElement (
-    true,
-    true,
-    Mac48Address::GetBroadcast ()
-    ,0);
-  if (m_preqTimer.IsRunning ())
-    m_preqQueue.push_back (preq);
-  else
-    {
-      NS_LOG_DEBUG ("Send now "<<preq.GetPreqID());
-      m_preqCallback (preq);
-      NS_ASSERT (!m_preqTimer.IsRunning());
-      m_preqTimer = Simulator::Schedule (dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpMacPlugin::SendOnePreq, this);
-    }
-  Simulator::Schedule (dot11sParameters::dot11MeshHWMPactiveRootTimeout, &HwmpMacPlugin::SendProactivePreq, this);
-}
-
 void
 HwmpMacPlugin::AddPerrReceiver (Mac48Address receiver)
 {
@@ -531,52 +453,57 @@
       return;
   m_myPerrReceivers.push_back (receiver);
 }
-
-void
-HwmpMacPlugin::UnSetRoot ()
-{
-}
-
-void
-HwmpMacPlugin::Disable ()
-{
-  m_disabled = true;
-}
-
-void
-HwmpMacPlugin::Enable ()
-{
-  m_disabled = false;
-}
-
-Mac48Address
-HwmpMacPlugin::GetAddress ()
-{
-  return m_address;
-}
-
+#endif
 void
 HwmpMacPlugin::SendOnePreq ()
 {
+  if(m_preqTimer.IsRunning ())
+    return;
   if (m_preqQueue.size () == 0)
     return;
   if (m_myPreq == m_preqQueue.begin ())
     m_myPreq == m_preqQueue.end ();
-  IeDot11sPreq preq = m_preqQueue[0];
-  NS_LOG_DEBUG (
+  IePreq preq = m_preqQueue[0];
+  NS_LOG_UNCOND (
     "Sending PREQ from "<<preq.GetOriginatorAddress () <<
     " destinations are  "<< (int)preq.GetDestCount()<<
     ", at "<<Simulator::Now ()<<
     ", store in queue "<<m_preqQueue.size ()<<
-    " preqs"<<", I am "<<m_address);
-  m_preqCallback (preq);
+    " preqs"<<", I am "<<m_parent->GetAddress ());
+  //Create packet
+  Ptr<Packet> packet  = Create<Packet> ();
+  packet->AddHeader(preq);
+  //Multihop action header:
+  WifiMeshMultihopActionHeader multihopHdr;
+  WifiMeshMultihopActionHeader::ACTION_VALUE action;
+  action.pathSelection = WifiMeshMultihopActionHeader::PATH_REQUEST;
+  multihopHdr.SetAction (WifiMeshMultihopActionHeader::MESH_PATH_SELECTION, action);
+  packet->AddHeader (multihopHdr);
+  //Mesh header
+  WifiMeshHeader meshHdr;
+  meshHdr.SetMeshTtl (m_protocol->GetMaxTtl ());
+  //TODO: should seqno be here?
+  meshHdr.SetMeshSeqno (0);
+  meshHdr.SetAddressExt(1);
+  meshHdr.SetAddr4(preq.GetOriginatorAddress ());
+  packet->AddHeader (meshHdr);
+  //create 802.11 header:
+  WifiMacHeader hdr;
+  hdr.SetMultihopAction ();
+  hdr.SetDsNotFrom ();
+  hdr.SetDsNotTo ();
+  hdr.SetAddr1 (Mac48Address::GetBroadcast ());
+  hdr.SetAddr2 (m_parent->GetAddress ());
+  hdr.SetAddr3 (Mac48Address::GetBroadcast ());
+  //Send Management frame
+  m_parent->SendManagementFrame(packet, hdr);
   //erase first!
   m_preqQueue.erase (m_preqQueue.begin());
   //reschedule sending PREQ
   NS_ASSERT (!m_preqTimer.IsRunning());
-  m_preqTimer = Simulator::Schedule (dot11sParameters::dot11MeshHWMPpreqMinInterval, &HwmpMacPlugin::SendOnePreq, this);
+  m_preqTimer = Simulator::Schedule (m_protocol->GetPreqMinInterval (), &HwmpMacPlugin::SendOnePreq, this);
 }
-
+#if 0
 void
 HwmpMacPlugin::SendPrep (Mac48Address dst,
                     Mac48Address src,
--- a/src/devices/mesh/dot11s/hwmp-mac-plugin.h	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.h	Fri Mar 27 20:03:13 2009 +0300
@@ -36,29 +36,43 @@
  */
 class HwmpMacPlugin : public MeshWifiInterfaceMacPlugin
 {
-  public:
-    HwmpMacPlugin (uint32_t, Ptr<HwmpProtocol>);
-    ~HwmpMacPlugin ();
-    ///\name Inherited from MAC plugin
-    //\{
-    void SetParent (Ptr<MeshWifiInterfaceMac> parent);
-    bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
-    bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const;
-    ///\brief Update beacon is empty, because HWMP does not know
-    //anything about beacons
-    void UpdateBeacon (MeshWifiBeacon & beacon) const {};
-    //\}
-  private:
-    friend class HwmpProtocol;
-    ///\brief Interaction with protocol:
-    void SendPreq(Ptr<IePreq> preq, std::vector<Mac48Address> receivers);
-    void SendPrep(Ptr<IePreq> prep, std::vector<Mac48Address> receivers);
-    void SendPerr(Ptr<IePreq> perr, std::vector<Mac48Address> receivers);
-  private:
-    Ptr<MeshWifiInterfaceMac> m_parent;
-    uint32_t m_ifIndex;
-    Ptr<HwmpProtocol> m_protocol;
+public:
+  HwmpMacPlugin (uint32_t, Ptr<HwmpProtocol>);
+  ~HwmpMacPlugin ();
+  ///\name Inherited from MAC plugin
+  //\{
+  void SetParent (Ptr<MeshWifiInterfaceMac> parent);
+  bool Receive (Ptr<Packet> packet, const WifiMacHeader & header);
+  bool UpdateOutcomingFrame (Ptr<Packet> packet, WifiMacHeader & header, Mac48Address from, Mac48Address to) const;
+  ///\brief Update beacon is empty, because HWMP does not know
+  //anything about beacons
+  void UpdateBeacon (MeshWifiBeacon & beacon) const {};
+  //\}
+private:
+  friend class HwmpProtocol;
+  ///\brief Interaction with protocol:
+  ///\name Intercation with HWMP:
+  ///\{
+  void SendPreq(IePreq preq, std::vector<Mac48Address> receivers);
+  void SendPrep(IePreq prep, Mac48Address receiver);
+  void SendPerr(IePreq perr, std::vector<Mac48Address> receivers);
+  void RequestDestination (Mac48Address dest);
+  ///\}
+  ///\brief Sends one PREQ when PreqMinInterval after last PREQ
+  //expires (if any PREQ exists in rhe queue)
+  void  SendOnePreq ();
+private:
+  Ptr<MeshWifiInterfaceMac> m_parent;
+  uint32_t m_ifIndex;
+  Ptr<HwmpProtocol> m_protocol;
+  ///\name PREQ queue and PREQ timer:
+  ///\{
+  EventId  m_preqTimer;
+  std::vector<IePreq>  m_preqQueue;
+  std::vector<IePreq>::iterator  m_myPreq;
+  ///\}
 };
+
 #if 0
 class HwmpMacPlugin : public MeshWifiInterfaceMacPlugin {
 public:
@@ -102,7 +116,6 @@
   );
   void SetRetransmittersOfPerrCallback (
     Callback<std::vector<Mac48Address>, std::vector<HwmpRtable::FailedDestination>, uint32_t> cb);
-  void RequestDestination (Mac48Address dest);
   void SendPathError (std::vector<HwmpRtable::FailedDestination> destinations);
   void SetAssociatedIfaceId (uint32_t interface);
   uint32_t  GetAssociatedIfaceId ();
@@ -117,34 +130,10 @@
   void ReceivePreq (IeDot11sPreq&, const Mac48Address& from, const uint32_t& metric);
   void ReceivePrep (IeDot11sPrep&, const Mac48Address& from, const uint32_t& metric);
   void ReceivePerr (IeDot11sPerr&, const Mac48Address& from);
-  void PeerStatus (
-    const Mac48Address peerAddress,
-    const bool status,
-    const uint32_t metric
-  );
-  //Proactive mode routines:
-  bool SetRoot ();
-  void UnSetRoot ();
-  //external handling:
-  void Disable ();
-  void Enable ();
-  //DEBUG purpose:
-  Mac48Address GetAddress ();
 private:
-  static const uint32_t MAX_PREQ_ID = 0xffffffff;
-  static const uint32_t MAX_DSN = 0xffffffff;
-  //information about associated port:
-  Mac48Address m_address;
-  //index when HWMP state is attached
-  uint32_t m_ifIndex;
-  //timers for PREQ and PREP:
-  EventId  m_preqTimer;
-  void  SendOnePreq ();
-  std::vector<IeDot11sPreq>  m_preqQueue;
   //true means that we can add a destination to
   //existing PREQ element
   //False means that we must send
-  EventId  m_prepTimer;
   void  SendPrep (
     Mac48Address dst, //dst is PREQ's originator address
     Mac48Address src, //src is PREQ's destination address
@@ -154,7 +143,6 @@
     uint32_t originatorDsn, //taken from rtable or as m_myDsn ++;
     uint32_t lifetime //taken from PREQ
   );
-  std::vector<IeDot11sPreq>::iterator  m_myPreq;
   //HWMP interaction callbacks:
   Callback<void, INFO>  m_routingInfoCallback;
   Callback<std::vector<Mac48Address>, std::vector<HwmpRtable::FailedDestination>, uint32_t>  m_retransmittersOfPerrCallback;
--- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Fri Mar 27 20:03:13 2009 +0300
@@ -30,6 +30,9 @@
 #include "ns3/wifi-net-device.h"
 #include "ns3/mesh-point-device.h"
 #include "ns3/mesh-wifi-interface-mac.h"
+#include "ie-dot11s-preq.h"
+#include "ie-dot11s-prep.h"
+#include "ie-dot11s-perr.h"
 
 NS_LOG_COMPONENT_DEFINE ("HwmpProtocol");
 
@@ -55,7 +58,7 @@
         MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPnetDiameterTraversalTime),
         MakeTimeChecker ()
         )
-    .AddAttribute ("dot11MeshHWMPpreqMinInterva",
+    .AddAttribute ("dot11MeshHWMPpreqMinInterval",
         "Minimal interval between to successive PREQs",
         TimeValue (MicroSeconds (1024*100)),
         MakeTimeAccessor (&HwmpProtocol::m_dot11MeshHWMPpreqMinInterval),
@@ -118,10 +121,13 @@
   return tid;
 }
 HwmpProtocol::HwmpProtocol ():
-    m_dataSeqno(1),
-    m_hwmpSeqno(1),
+    m_dataSeqno (1),
+    m_hwmpSeqno (1),
+    m_preqId (0),
     m_rtable (CreateObject<HwmpRtable> ()),
-    m_isRoot (false)
+    m_isRoot (false),
+    m_doFlag (false),
+    m_rfFlag (false)
 {
 }
 
@@ -139,6 +145,7 @@
   m_lastHwmpSeqno.clear ();
   m_rqueue.clear ();
   m_rtable = 0;
+
   //TODO: clear plugins
 }
 
@@ -157,7 +164,6 @@
   if (sourceIface == GetMeshPoint ()->GetIfIndex())
     // packet from level 3
   {
-    NS_LOG_UNCOND("Packet from upper layer. Broadcast frame");
     NS_ASSERT (!packet->FindFirstMatchingTag(tag));
     //Filling TAG:
     tag.SetSeqno (m_dataSeqno++);
@@ -208,7 +214,9 @@
       return false;
   }
   //Request a destination:
-  NS_ASSERT(false);
+  if(ShouldSendPreq(destination))
+    for(PLUGINS::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+      i->second->RequestDestination(destination);
   QueuedPacket pkt;
   HwmpTag tag;
   tag.SetAddress(Mac48Address::GetBroadcast ());
@@ -369,6 +377,13 @@
   }
   return retransmitters;
 }
+std::vector<Mac48Address>
+HwmpProtocol::GetPreqReceivers ()
+{
+  std::vector<Mac48Address> retval;
+  retval.push_back (Mac48Address::GetBroadcast ());
+  return retval;
+}
 bool
 HwmpProtocol::QueuePacket (QueuedPacket packet)
 {
@@ -452,6 +467,7 @@
   std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.find (dst);
   if (i == m_preqTimeouts.end ())
     {
+      NS_LOG_UNCOND("Timeout is:" <<2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds()));
       m_preqTimeouts[dst] = Simulator::Schedule (
           MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
           &HwmpProtocol::RetryPathDiscovery, this, dst, 0);
@@ -489,11 +505,82 @@
       m_preqTimeouts.erase (i);
       return;
     }
-  //TODO: Request a destination again
-  NS_ASSERT(false);
+  for(PLUGINS::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+    i->second->RequestDestination(dst);
   m_preqTimeouts[dst] = Simulator::Schedule (
       MilliSeconds (2*(m_dot11MeshHWMPnetDiameterTraversalTime.GetMilliSeconds())),
       &HwmpProtocol::RetryPathDiscovery, this, dst, numOfRetry);
 }
+//Proactive PREQ routines:
+void
+HwmpProtocol::SetRoot ()
+{
+  SendProactivePreq ();
+  m_isRoot = true;
+}
+void
+HwmpProtocol::UnsetRoot ()
+{
+  m_proactivePreqTimer.Cancel ();
+}
+void
+HwmpProtocol::SendProactivePreq ()
+{
+  NS_LOG_DEBUG ("Sending proactive PREQ");
+  IePreq preq;
+  //By default: must answer
+  preq.SetHopcount (0);
+  preq.SetTTL (m_maxTtl);
+  if (m_preqId == 0xffffffff)
+    m_preqId = 0;
+  preq.SetLifetime (m_dot11MeshHWMPpathToRootInterval.GetMicroSeconds () /1024);
+  //\attention: do not forget to set originator address, sequence
+  //number and preq ID in HWMP-MAC plugin
+  preq.AddDestinationAddressElement (true, true, Mac48Address::GetBroadcast (), 0);
+  for(PLUGINS::iterator i = m_interfaces.begin (); i != m_interfaces.end (); i ++)
+    i->second->SendPreq(preq, GetPreqReceivers ());
+  m_proactivePreqTimer = Simulator::Schedule (m_dot11MeshHWMPactiveRootTimeout, &HwmpProtocol::SendProactivePreq, this);
+}
+bool
+HwmpProtocol::GetDoFlag ()
+{
+  return m_doFlag;
+}
+bool
+HwmpProtocol::GetRfFlag ()
+{
+  return m_rfFlag;
+}
+Time
+HwmpProtocol::GetPreqMinInterval ()
+{
+  return m_dot11MeshHWMPpreqMinInterval;
+}
+Time
+HwmpProtocol::GetPerrMinInterval ()
+{
+  return m_dot11MeshHWMPperrMinInterval;
+}
+uint8_t
+HwmpProtocol::GetMaxTtl ()
+{
+  return m_maxTtl;
+}
+uint32_t
+HwmpProtocol::GetNextPreqId ()
+{
+  m_preqId ++;
+  if(m_preqId == 0xffffffff)
+    m_preqId = 0;
+  return m_preqId;
+}
+uint32_t
+HwmpProtocol::GetNextHwmpSeqno ()
+{
+  m_hwmpSeqno ++;
+  if(m_hwmpSeqno == 0xffffffff)
+    m_hwmpSeqno = 0;
+  return m_hwmpSeqno;
+}
 } //namespace dot11s
 } //namespace ns3
--- a/src/devices/mesh/dot11s/hwmp-protocol.h	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-protocol.h	Fri Mar 27 20:03:13 2009 +0300
@@ -25,6 +25,7 @@
 #include "ns3/mesh-l2-routing-protocol.h"
 #include "ns3/nstime.h"
 #include "ns3/ie-dot11s-perr.h"
+#include "ns3/event-id.h"
 #include <vector>
 #include <map>
 
@@ -32,7 +33,6 @@
 class MeshPointDevice;
 class Packet;
 class Mac48Address;
-class EventId;
 namespace dot11s {
 class HwmpMacPlugin;
 class HwmpRtable;
@@ -65,9 +65,9 @@
   //destination fails on a given interface
   //\param uint32_t is an interface ID, where route has failed
   void MakePathError (Mac48Address, uint32_t);
-  ///\return list of addresses where a perr should be sent to
+  ///\return list of addresses where a PERR/PREQ should be sent to
   std::vector<Mac48Address> GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest, uint32_t port);
-
+  std::vector<Mac48Address> GetPreqReceivers ();
   ///\brief MAC-plugin asks wether the frame can be dropeed. Protocol
   //automatically updates seqno.
   //\returns true if frame can be dropped
@@ -96,24 +96,33 @@
   //maximum level - retry mechanish should be cancelled
   void  RetryPathDiscovery (Mac48Address dst, uint8_t numOfRetry);
   ///\}
+  ///\name Proactive Preq routines:
+  ///\{
+  void SetRoot ();
+  void UnsetRoot ();
+  void SendProactivePreq ();
+  ///\}
 private:
   //fields:
-  std::map<uint32_t, Ptr<HwmpMacPlugin> > m_interfaces;
+  typedef std::map<uint32_t, Ptr<HwmpMacPlugin> > PLUGINS;
+  PLUGINS m_interfaces;
   uint32_t m_dataSeqno;
   uint32_t m_hwmpSeqno;
+  uint32_t m_preqId;
   ///\brief Sequence number filters:
-  std::map<Mac48Address, uint32_t,std::less<Mac48Address> >  m_lastDataSeqno;
-  std::map<Mac48Address, uint32_t,std::less<Mac48Address> >  m_lastHwmpSeqno;
+  std::map<Mac48Address, uint32_t,std::less<Mac48Address> > m_lastDataSeqno;
+  std::map<Mac48Address, uint32_t,std::less<Mac48Address> > m_lastHwmpSeqno;
   ///\brief Routing table
   Ptr<HwmpRtable> m_rtable;
   ///\name Timers:
   //\{
-  std::map<Mac48Address, EventId>  m_preqTimeouts;
+  std::map<Mac48Address, EventId> m_preqTimeouts;
+  EventId m_proactivePreqTimer;
   //\}
   ///\Packet Queue
-  std::vector<QueuedPacket>  m_rqueue;
+  std::vector<QueuedPacket> m_rqueue;
 private:
-  ///\name HWMP-protocol parameters
+  ///\name HWMP-protocol parameters (attributes of GetTypeId)
   ///\{
   uint8_t m_dot11MeshHWMPmaxPREQretries;
   Time m_dot11MeshHWMPnetDiameterTraversalTime;
@@ -127,6 +136,19 @@
   uint8_t m_maxTtl;
   uint8_t m_unicastPerrThreshold;
   uint8_t m_unicastPreqThreshold;
+  bool m_doFlag;
+  bool m_rfFlag;
+  ///\}
+  ///\name Methods needed by HwmpMacLugin to access protocol
+  //parameters:
+  ///\{
+  bool GetDoFlag ();
+  bool GetRfFlag ();
+  Time GetPreqMinInterval ();
+  Time GetPerrMinInterval ();
+  uint8_t GetMaxTtl ();
+  uint32_t GetNextPreqId ();
+  uint32_t GetNextHwmpSeqno ();
   ///\}
 };
 } //namespace dot11s
--- a/src/devices/mesh/dot11s/peer-management-plugin.cc	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/peer-management-plugin.cc	Fri Mar 27 20:03:13 2009 +0300
@@ -89,7 +89,6 @@
     NS_ASSERT(meshHdr.GetMeshTtl () == 1);
     NS_ASSERT(meshHdr.GetAddressExt () == 1);
     NS_ASSERT(meshHdr.GetAddr4 () == header.GetAddr2 ());
-
     Mac48Address peerAddress = header.GetAddr2 ();
     PeerLinkFrameStart::PlinkFrameStartFields fields;
     {
@@ -116,7 +115,7 @@
     // frames except CLOSE
     IeConfiguration meshConfig;
     if(fields.subtype != IePeerManagement::PEER_CLOSE)
-    packet->RemoveHeader(meshConfig);
+      packet->RemoveHeader(meshConfig);
     IePeerManagement peerElement;
     packet->RemoveHeader(peerElement);
     // Check the correspondance betwee action valuse and peer link
@@ -141,11 +140,7 @@
     // if we can handle a frame - drop it
     return false;
   }
-  if(header.IsData())
-  {
-    return m_protocol->IsActiveLink(m_ifIndex,header.GetAddr2());
-  }
-  return true;
+  return m_protocol->IsActiveLink(m_ifIndex,header.GetAddr2());
 }
 
 bool
--- a/src/devices/mesh/dot11s/peer-management-protocol.cc	Fri Mar 27 16:33:08 2009 +0300
+++ b/src/devices/mesh/dot11s/peer-management-protocol.cc	Fri Mar 27 20:03:13 2009 +0300
@@ -26,7 +26,6 @@
 #include "ie-dot11s-configuration.h"
 
 #include "ns3/mesh-point-device.h"
-#include "ns3/dot11s-parameters.h"
 #include "ns3/simulator.h"
 #include "ns3/assert.h"
 #include "ns3/log.h"
@@ -272,9 +271,11 @@
   BeaconInfoMap::iterator beaconsOnInterface = m_neighbourBeacons.find (interface);
   if(beaconsOnInterface == m_neighbourBeacons.end())
     FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+  beaconsOnInterface = m_neighbourBeacons.find (interface);
   BeaconsOnInterface::iterator beacon = beaconsOnInterface->second.find (peerAddress);
   if(beacon == beaconsOnInterface->second.end ())
     FillBeaconInfo(interface, peerAddress, lastBeacon, beaconInterval);
+  beacon = beaconsOnInterface->second.find (peerAddress);
   //find a peer link  - it must not exist
   NS_ASSERT(FindPeerLink(interface, peerAddress) == 0);
   // Plugin must exist