HwmpProtocol: path error procedure reviewed, RequestRoute reviewed
authorKirill Andreev <andreev@iitp.ru>
Fri, 27 Mar 2009 16:33:08 +0300
changeset 4894 a6cf8696922a
parent 4893 d390c2dd2f14
child 4895 b68a1309a89e
HwmpProtocol: path error procedure reviewed, RequestRoute reviewed
src/devices/mesh/dot11s/hwmp-mac-plugin.cc
src/devices/mesh/dot11s/hwmp-protocol.cc
src/devices/mesh/dot11s/hwmp-protocol.h
src/devices/mesh/dot11s/hwmp-rtable.cc
src/devices/mesh/dot11s/hwmp-rtable.h
src/devices/mesh/dot11s/wscript
--- a/src/devices/mesh/dot11s/hwmp-mac-plugin.cc	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-mac-plugin.cc	Fri Mar 27 16:33:08 2009 +0300
@@ -71,14 +71,14 @@
         NS_ASSERT(false);
     };
     tag.SetSeqno (2);//meshHdr.GetMeshSeqno ());
+    if(meshHdr.GetMeshTtl () == 0)
+      return false;
     tag.SetTtl (meshHdr.GetMeshTtl () - 1);
     tag.SetAddress (header.GetAddr2 ());
     packet->AddTag(tag);
     if (destination == Mac48Address::GetBroadcast ())
       if(m_protocol->DropDataFrame (meshHdr.GetMeshSeqno (), header.GetAddr4 ()) )
         return false;
-    if(tag.GetTtl () == 0)
-      return false;
   }
   return true;
 }
--- a/src/devices/mesh/dot11s/hwmp-protocol.cc	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-protocol.cc	Fri Mar 27 16:33:08 2009 +0300
@@ -102,13 +102,26 @@
         UintegerValue (32),
         MakeUintegerAccessor (&HwmpProtocol::m_maxTtl),
         MakeUintegerChecker<uint8_t> (1)
+        )
+  .AddAttribute ("unicastPerrThreshold",
+        "Maximum number of PERR receivers, when we send a PERR as a chain of unicasts",
+        UintegerValue (32),
+        MakeUintegerAccessor (&HwmpProtocol::m_unicastPerrThreshold),
+        MakeUintegerChecker<uint8_t> (1)
+        )
+  .AddAttribute ("unicastPreqThreshold",
+        "Maximum number of PREQ receivers, when we send a PREQ as a chain of unicasts",
+        UintegerValue (0),
+        MakeUintegerAccessor (&HwmpProtocol::m_unicastPreqThreshold),
+        MakeUintegerChecker<uint8_t> (0)
         );
   return tid;
 }
 HwmpProtocol::HwmpProtocol ():
-    m_dataSeqno(0),
-    m_hwmpSeqno(0),
-    m_rtable (CreateObject<HwmpRtable> ())
+    m_dataSeqno(1),
+    m_hwmpSeqno(1),
+    m_rtable (CreateObject<HwmpRtable> ()),
+    m_isRoot (false)
 {
 }
 
@@ -119,37 +132,14 @@
 void
 HwmpProtocol::DoDispose ()
 {
-#if 0
   for (std::map<Mac48Address, EventId>::iterator i = m_preqTimeouts.begin (); i != m_preqTimeouts.end(); i ++)
     i->second.Cancel ();
   m_preqTimeouts.clear ();
-  m_seqnoDatabase.clear ();
+  m_lastDataSeqno.clear ();
+  m_lastHwmpSeqno.clear ();
+  m_rqueue.clear ();
   m_rtable = 0;
-
-  /**
-   * clear routing queue:
-   */
-  for (
-    std::map<Mac48Address, std::queue<QueuedPacket> >::iterator i =  m_rqueue.begin ();
-    i != m_rqueue.end ();
-    i++
-  )
-    {
-      while (1)
-        {
-          if (i->second.empty ())
-            break;
-          i->second.pop ();
-        }
-    }
-  m_rqueue.clear ();
-  /**
-   * clear HWMP states
-   */
-  for (unsigned int i = 0; i < m_hwmpStates.size (); i ++)
-    m_hwmpStates[i] = 0;
-  m_hwmpStates.clear ();
-#endif
+  //TODO: clear plugins
 }
 
 bool
@@ -163,7 +153,6 @@
 )
 {
   NS_LOG_UNCOND("Packet has come!");
-  //HwmpRtable::LookupResult result;
   HwmpTag tag;
   if (sourceIface == GetMeshPoint ()->GetIfIndex())
     // packet from level 3
@@ -177,140 +166,61 @@
     if (m_dataSeqno == 0xffffffff)
       m_dataSeqno = 0;
     packet->AddTag(tag);
-    if (destination == Mac48Address::GetBroadcast ())
-    {
-      //Reply immediately
-      routeReply (true, packet, source, destination, protocolType, HwmpRtable::INTERFACE_ANY);
-    }
-    else
-    {
-      
-    }
   }
-  else
-    // packet from own interface
-  {
-    NS_ASSERT (packet->FindFirstMatchingTag(tag));
-    if (destination == Mac48Address::GetBroadcast ())
-      //reply immediately
-      routeReply (true, packet, source, destination, protocolType, HwmpRtable::INTERFACE_ANY);
-    else
-    {
-      NS_ASSERT(false);
-    }
-  }
-#if 0
-      if (destination == Mac48Address::GetBroadcast ())
-        {
-          std::map<Mac48Address, uint32_t>::iterator i = m_seqnoDatabase.find (source);
-          if (i == m_seqnoDatabase.end ())
-            m_seqnoDatabase[source] = tag.GetSeqno ();
-          else
-            {
-              if (i->second >= tag.GetSeqno ())
-                return false;
-              m_seqnoDatabase[source] = tag.GetSeqno ();
-            }
-        }
-    }
-  if (tag.GetTtl () == 0)
-    return false;
-  tag.DecrementTtl ();
+  NS_ASSERT (packet->FindFirstMatchingTag(tag));
   if (destination == Mac48Address::GetBroadcast ())
-    {
-      //add RA tag RA = broadcast
-      packet->RemoveAllTags ();
-      packet->AddTag (tag);
-      routeReply (
-        true,
-        packet,
-        source,
-        destination,
-        protocolType,
-        HwmpRtable::INTERFACE_ANY
-      );
-      return true;
-    }
-  result = m_rtable->LookupReactive (destination);
-  if (result.retransmitter == Mac48Address::GetBroadcast ())
-    {
-      //no actual route exists, queue packet and start route
-      //discover procedure
-      if (sourceIface != GetMeshPoint ()->GetIfIndex())
-        {
-          //Start path error procedure:
-          NS_LOG_DEBUG ("Must Send PERR");
-          std::vector<HwmpRtable::FailedDestination> destinations;
-          HwmpRtable::FailedDestination dst;
-          dst.seqnum = m_rtable->RequestSeqnum (destination);
-          dst.destination = destination;
-          destinations.push_back (dst);
-          StartPathErrorProcedure (destinations, result.ifIndex);
-        }
-      MeshL2RoutingProtocol::QueuedPacket pkt;
-      packet->RemoveAllTags ();
-      packet->AddTag (tag);
-      pkt.pkt = packet;
-      pkt.dst = destination;
-      pkt.src = source;
-      pkt.protocol = protocolType;
-      pkt.reply = routeReply;
-      pkt.inPort = sourceIface;
-      QueuePacket (pkt);
-      for (unsigned int i = 0; i< m_requestCallback.size (); i++)
-        {
-          if ((m_modes[i] == REACTIVE) || (m_modes[i] == ROOT))
-            {
-              if (ShouldSendPreq (destination))
-                m_requestCallback[i] (destination);
-            }
-          else
-            {
-              NS_ASSERT (false);
-              //PROACTIVE mode
-              //lookup a default route
-              result = m_rtable->LookupProactive (m_hwmpStates[i]->GetAssociatedIfaceId());
-              if (result.retransmitter == Mac48Address::GetBroadcast ())
-                {
-                  m_rtable->DeleteProactivePath (m_hwmpStates[i]->GetAssociatedIfaceId());
-                  m_modes[i] = REACTIVE;
-                  if (ShouldSendPreq (destination))
-                    m_requestCallback[i] (destination);
-                  continue;
-                }
-              tag.SetAddress (result.retransmitter);
-              packet->RemoveAllTags ();
-              packet->AddTag (tag);
-              routeReply (
-                true,
-                packet,
-                source,
-                destination,
-                protocolType,
-                result.ifIndex
-              );
-            }
-        }
-      for (unsigned int i = 0; i< m_requestCallback.size (); i++)
-        {
-          m_requestCallback[i] (Mac48Address("00:00:00:00:00:19"));
-        }
-    }
+    routeReply (true, packet, source, destination, protocolType, HwmpRtable::INTERFACE_ANY);
   else
-    {
-      tag.SetAddress (result.retransmitter);
-      packet->RemoveAllTags ();
-      packet->AddTag (tag);
-      routeReply (
-        true,
-        packet,
-        source,
-        destination,
-        protocolType,
-        result.ifIndex
-      );
-    }
-#endif
+    return ForwardUnicast(sourceIface, source, destination, packet, protocolType, routeReply);
+  return true;
+}
+bool
+HwmpProtocol::ForwardUnicast(uint32_t  sourceIface, const Mac48Address source, const Mac48Address destination,
+    Ptr<Packet>  packet, uint16_t  protocolType, RouteReplyCallback  routeReply)
+{
+  NS_ASSERT(destination != Mac48Address::GetBroadcast ());
+  HwmpRtable::LookupResult result = m_rtable->LookupReactive(destination);
+  if(result.retransmitter == Mac48Address::GetBroadcast ())
+    result = m_rtable->LookupProactive ();
+  if(result.retransmitter != Mac48Address::GetBroadcast ())
+  {
+    //reply immediately:
+    routeReply (true, packet, source, destination, protocolType, result.ifIndex);
+    return true;
+  }
+  if (sourceIface != GetMeshPoint ()->GetIfIndex())
+  {
+    //Start path error procedure:
+    NS_LOG_DEBUG ("Must Send PERR");
+    result = m_rtable->LookupReactiveExpired (destination);
+    //1.  Lookup expired reactive path. If exists - start path error
+    //    procedure towards a next hop of this path
+    //2.  If there was no reactive path, we lookup expired proactive
+    //    path. If exist - start path error procedure towards path to
+    //    root
+    //3.  If and only if we are a root station - we queue packet
+    if((result.retransmitter == Mac48Address::GetBroadcast ()) && (!m_isRoot))
+      result = m_rtable->LookupProactiveExpired ();
+    if((result.retransmitter == Mac48Address::GetBroadcast ()) && (!m_isRoot))
+      return false;
+    MakePathError (result.retransmitter, result.ifIndex);
+    if(!m_isRoot)
+      return false;
+  }
+  //Request a destination:
+  NS_ASSERT(false);
+  QueuedPacket pkt;
+  HwmpTag tag;
+  tag.SetAddress(Mac48Address::GetBroadcast ());
+  packet->RemoveAllTags ();
+  packet->AddTag (tag);
+  pkt.pkt = packet;
+  pkt.dst = destination;
+  pkt.src = source;
+  pkt.protocol = protocolType;
+  pkt.reply = routeReply;
+  pkt.inInterface = sourceIface;
+  QueuePacket (pkt);
   return true;
 }
 bool
@@ -352,65 +262,6 @@
 
 #if 0
 void
-HwmpProtocol::SetRoot (uint32_t port)
-{
-  int position = 0;
-  for (std::vector<Ptr<HwmpProtocolState> >::iterator i = m_hwmpStates.begin (); i != m_hwmpStates.end(); i++)
-    {
-      if (((*i)->GetAssociatedIfaceId () == port)||(port == HwmpRtable::INTERFACE_ANY))
-        {
-          if (m_hwmpStates[position]->SetRoot ())
-            {
-              m_modes[position] = ROOT;
-              NS_LOG_DEBUG ("I am proactive");
-            }
-        }
-      position ++;
-    }
-}
-void
-HwmpProtocol::SetProactive (uint32_t port)
-{
-  int position = 0;
-  for (std::vector<Ptr<HwmpProtocolState> >::iterator i = m_hwmpStates.begin (); i != m_hwmpStates.end(); i++)
-    {
-      if ((*i)->GetAssociatedIfaceId () == port)
-        {
-          m_modes[position] = PROACTIVE;
-          return;
-        }
-      position ++;
-    }
-}
-bool
-HwmpProtocol::IsRoot (uint32_t port)
-{
-  int position = 0;
-  for (std::vector<Ptr<HwmpProtocolState> >::iterator i = m_hwmpStates.begin (); i != m_hwmpStates.end(); i++)
-    {
-      if ((*i)->GetAssociatedIfaceId () == port)
-        if (m_modes[position] == ROOT)
-          return true;
-      position ++;
-    }
-  return false;
-}
-void
-HwmpProtocol::UnSetRoot (uint32_t port)
-{
-  int position = 0;
-  for (std::vector<Ptr<HwmpProtocolState> >::iterator i = m_hwmpStates.begin (); i != m_hwmpStates.end(); i++)
-    {
-      if (((*i)->GetAssociatedIfaceId () == port)||(port == HwmpRtable::INTERFACE_ANY))
-        {
-          m_modes[position] = REACTIVE;
-          m_hwmpStates[position]->UnSetRoot ();
-        }
-      position ++;
-    }
-}
-
-void
 HwmpProtocol::ObtainRoutingInformation (
   HwmpProtocolState::INFO info
 )
@@ -475,63 +326,51 @@
       peer.destination = info.destination;
       peer.seqnum = 0;
       failedDestinations.push_back (peer);
-      StartPathErrorProcedure (failedDestinations, info.outPort);
+      MakePathError (failedDestinations, info.outPort);
     }
     break;
     default:
       return;
     }
 }
-
-HwmpRtable::LookupResult
-HwmpProtocol::RequestRouteForAddress (const Mac48Address& dst)
-{
-  return m_rtable->LookupReactive (dst);
-}
-
-HwmpRtable::LookupResult
-HwmpProtocol::RequestRootPathForPort (uint32_t port)
-{
-  return m_rtable->LookupProactive (port);
-}
-
+#endif
 void
-HwmpProtocol::StartPathErrorProcedure (std::vector<HwmpRtable::FailedDestination> destinations, uint32_t port)
+HwmpProtocol::MakePathError (Mac48Address retransmitter, uint32_t interface)
 {
   NS_LOG_DEBUG ("START PERR");
-  for (unsigned int i  = 0; i < m_hwmpStates.size (); i++)
-    if (m_hwmpStates[i]->GetAssociatedIfaceId () == port)
-      m_pathErrorCallback[i] (destinations);
+  //TODO:
+  //make a perr IE and send
+  std::vector<IePerr::FailedDestination> destinations = m_rtable->GetUnreachableDestinations (retransmitter, interface);
+  //HwmpRtable increments a sequence number as written in 11B.9.7.2
+  std::vector<Mac48Address> receivers = GetPerrReceivers (destinations, interface);
+  NS_ASSERT(false);
 }
 std::vector<Mac48Address>
-HwmpProtocol::GetRetransmittersForFailedDestinations (std::vector<HwmpRtable::FailedDestination> failedDest, uint32_t port)
+HwmpProtocol::GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest, uint32_t interface)
 {
   std::vector<Mac48Address> retransmitters;
-  if (m_broadcastPerr)
-    retransmitters.push_back (Mac48Address::GetBroadcast());
-  else
-    for (unsigned int i = 0; i < failedDest.size (); i ++)
-      {
-        std::vector<Mac48Address> precursors =
-          m_rtable->GetPrecursors (failedDest[i].destination, port);
-        for (unsigned int j = 0; j < precursors.size (); j++)
-          {
-            for (unsigned int k = 0; k < retransmitters.size (); k ++)
-              if (retransmitters[k] == precursors[j])
-                break;
-            retransmitters.push_back (precursors[j]);
-          }
-      }
+    
   for (unsigned int i = 0; i < failedDest.size (); i ++)
+  {
+    std::vector<Mac48Address> precursors =
+      m_rtable->GetPrecursors (failedDest[i].destination, interface);
+    for (unsigned int j = 0; j < precursors.size (); j++)
     {
-      m_rtable->DeleteReactivePath (failedDest[i].destination, port);
-      m_rtable->DeleteProactivePath (failedDest[i].destination, port);
+      for (unsigned int k = 0; k < retransmitters.size (); k ++)
+        if (retransmitters[k] == precursors[j])
+          break;
+      retransmitters.push_back (precursors[j]);
     }
+  }
+  for (unsigned int i = 0; i < failedDest.size (); i ++)
+  {
+      m_rtable->DeleteReactivePath (failedDest[i].destination, interface);
+      m_rtable->DeleteProactivePath(failedDest[i].destination);
+  }
   return retransmitters;
 }
-#endif
 bool
-HwmpProtocol::QueuePacket (MeshL2RoutingProtocol::QueuedPacket packet)
+HwmpProtocol::QueuePacket (QueuedPacket packet)
 {
   if (m_rqueue.size () > m_maxQueueSize)
     return false;
@@ -542,7 +381,7 @@
 MeshL2RoutingProtocol::QueuedPacket
 HwmpProtocol::DequeueFirstPacketByDst (Mac48Address dst)
 {
-  MeshL2RoutingProtocol::QueuedPacket retval;
+  QueuedPacket retval;
   retval.pkt = NULL;
   for(std::vector<QueuedPacket>::iterator i = m_rqueue.begin (); i != m_rqueue.end (); i++)
     if((*i).dst == dst)
@@ -556,7 +395,7 @@
 MeshL2RoutingProtocol::QueuedPacket
 HwmpProtocol::DequeueFirstPacket ()
 {
-  MeshL2RoutingProtocol::QueuedPacket retval;
+  QueuedPacket retval;
   retval.pkt = NULL;
   if(m_rqueue.size () != 0)
     retval = m_rqueue[0];
@@ -569,7 +408,7 @@
   HwmpRtable::LookupResult result = m_rtable->LookupReactive (dst);
   NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
   //Send all packets stored for this destination    
-  MeshL2RoutingProtocol::QueuedPacket packet;
+  QueuedPacket packet;
   while (1)
   {
     packet = DequeueFirstPacketByDst (dst);
@@ -590,7 +429,21 @@
   //send all packets to root
   HwmpRtable::LookupResult result = m_rtable->LookupProactive ();
   NS_ASSERT(result.retransmitter != Mac48Address::GetBroadcast ());
-  NS_ASSERT(false);
+  QueuedPacket packet;
+  while (1)
+  {
+    packet = DequeueFirstPacket ();
+    if (packet.pkt == NULL)
+      return;
+    //set RA tag for retransmitter:
+    HwmpTag tag;
+    NS_ASSERT (packet.pkt->FindFirstMatchingTag(tag));
+    tag.SetAddress (result.retransmitter);
+    packet.pkt->RemoveAllTags ();
+    packet.pkt->AddTag (tag);
+    packet.reply (true, packet.pkt, packet.src, packet.dst, packet.protocol, result.ifIndex);
+  }
+
 }
 
 bool
@@ -622,7 +475,7 @@
   numOfRetry++;
   if (numOfRetry > m_dot11MeshHWMPmaxPREQretries)
     {
-      MeshL2RoutingProtocol::QueuedPacket packet;
+      QueuedPacket packet;
       //purge queue and delete entry from retryDatabase
       while (1)
         {
--- a/src/devices/mesh/dot11s/hwmp-protocol.h	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-protocol.h	Fri Mar 27 16:33:08 2009 +0300
@@ -24,6 +24,7 @@
 
 #include "ns3/mesh-l2-routing-protocol.h"
 #include "ns3/nstime.h"
+#include "ns3/ie-dot11s-perr.h"
 #include <vector>
 #include <map>
 
@@ -37,7 +38,6 @@
 class HwmpRtable;
 class IePreq;
 class IePrep;
-class IePerr;
 /**
  * \ingroup mesh
  */
@@ -48,82 +48,33 @@
   HwmpProtocol ();
   ~HwmpProtocol ();
   void DoDispose ();
-  bool RequestRoute (
-    uint32_t  sourceIface,
-    const Mac48Address source,
-    const Mac48Address destination,
-    Ptr<Packet>  packet,
-    uint16_t  protocolType,
-    MeshL2RoutingProtocol::RouteReplyCallback  routeReply
-  );
+  bool RequestRoute (uint32_t  sourceIface, const Mac48Address source, const Mac48Address destination,
+      Ptr<Packet>  packet, uint16_t  protocolType, RouteReplyCallback  routeReply);
   bool Install (Ptr<MeshPointDevice>);
-#if 0
-  /**
-   * \brief Disables port by index.
-   * \details Needed for external modules like
-   * clusterization.
-   */
-  void DisablePort (uint32_t port);
-  /**
-   * \brief enables port
-   */
-  void EnablePort (uint32_t port);
-  /**
-   * \brief Setting proative mode.
-   * \details To enable proactive mode you must
-   * set a root node. Choosing the route is made
-   * in accordance with the following:
-   *  1. Find 'reactive' route. If route is
-   *  found - send a packet using this
-   *  information
-   *  2. If there is no reactive route -
-   *  find proactive or 'default' route.
-   * \attention Comparsion between proactive and
-   * reactive routes is incorrect, because we
-   * have metric to root MP in te first case and
-   * metric to the destination in the second
-   * case.
-   * \param port is the port where proactive
-   * mode should be activated
-   */
-  void SetRoot (uint32_t port);
-  /**
-   * \brief Disable root functionality at a
-   * given port
-   */
-  void UnSetRoot (uint32_t port);
-  /**
-   * \brief HwmpProtocolState retrns to HwmpProtocol class all
-   * routing information obtained from all HWMP
-   * action frames
-   */
-  void ObtainRoutingInformation (
-    HwmpProtocolState::INFO info
-  );
-  /**
-   * \brief HwmpProtocol state noyifyes that neighbour
-   * is dissapeared. HwmpProtocol state knows about peer
-   * failure from MAC
-   */
-  void PeerFailure (Mac48Address peerAddress);
-  void SetMaxTtl (uint8_t ttl);
-  uint8_t  GetMaxTtl ();
-  static const uint32_t MAX_SEQNO = 0xffffffff;
-#endif
-  //candidate queue is implemented inside the
-  //protocol:
 private:
   friend class HwmpMacPlugin;
-  ///\brief interaction with HWMP MAC plugin
+  ///\brief Like RequestRoute, but for unicast packets
+  bool ForwardUnicast (uint32_t  sourceIface, const Mac48Address source, const Mac48Address destination,
+      Ptr<Packet>  packet, uint16_t  protocolType, RouteReplyCallback  routeReply);
+  ///\name interaction with HWMP MAC plugin
+  //\{
   void ReceivePreq(Ptr<IePreq> preq, Mac48Address from);
   void ReceivePrep(Ptr<IePreq> prep, Mac48Address from);
   void ReceivePerr(Ptr<IePreq> perr, Mac48Address from);
+  ///\brief forms a path error information element when list of
+  //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
+  std::vector<Mac48Address> GetPerrReceivers (std::vector<IePerr::FailedDestination> failedDest, uint32_t port);
+
   ///\brief MAC-plugin asks wether the frame can be dropeed. Protocol
   //automatically updates seqno.
   //\returns true if frame can be dropped
   //\param uint32_t is the seqno
   //\param Mac48Address is the mesh source addrress of the frame
   bool DropDataFrame(uint32_t, Mac48Address);
+  ///\}
 private:
   ///\name Methods related to Queue/Dequeue procedures
   ///\{
@@ -150,7 +101,6 @@
   std::map<uint32_t, Ptr<HwmpMacPlugin> > m_interfaces;
   uint32_t m_dataSeqno;
   uint32_t m_hwmpSeqno;
-  uint32_t m_maxTtl;
   ///\brief Sequence number filters:
   std::map<Mac48Address, uint32_t,std::less<Mac48Address> >  m_lastDataSeqno;
   std::map<Mac48Address, uint32_t,std::less<Mac48Address> >  m_lastHwmpSeqno;
@@ -173,47 +123,11 @@
   Time m_dot11MeshHWMPactivePathTimeout;
   Time m_dot11MeshHWMPpathToRootInterval;
   Time m_dot11MeshHWMPrannInterval;
+  bool m_isRoot;
+  uint8_t m_maxTtl;
+  uint8_t m_unicastPerrThreshold;
+  uint8_t m_unicastPreqThreshold;
   ///\}
-#if 0
-  //devices and HWMP states:
-  enum DeviceMode {
-    REACTIVE,
-    PROACTIVE,
-    ROOT
-  };
-  std::vector<enum DeviceMode>   m_modes;
-  //Proactive routines:
-  /**
-   * \brief Set port state as proactive.
-   * \details mode is supposed to be proactive
-   * when proatcive PREQ with a valid
-   * information was received.
-   */
-  void  SetProactive (uint32_t port);
-  /**
-   * \brief Checks if the port is root, if true
-   * - no default routes must be used at this
-   * port
-   */
-  bool  IsRoot (uint32_t port);
-    /**
-   * \brief HwmpProtocolState need to know where to
-   * retransmit PERR, only HWMP knows how to
-   * retransmit it (broadcast/unicast) and only
-   * HWMP has accessto routing table
-   */
-  std::vector<Mac48Address>  GetRetransmittersForFailedDestinations (
-    std::vector<HwmpRtable::FailedDestination> failedDest,
-    uint32_t port);
-  /**
-   * \brief Needed by HwmpProtocolState to find routes in case
-   * of intermediate reply and choosing the
-   * better route
-   *
-   */
-  HwmpRtable::LookupResult  RequestRouteForAddress (const Mac48Address& destination);
-  HwmpRtable::LookupResult  RequestRootPathForPort (uint32_t port);
-#endif
 };
 } //namespace dot11s
 } //namespace ns3
--- a/src/devices/mesh/dot11s/hwmp-rtable.cc	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-rtable.cc	Fri Mar 27 16:33:08 2009 +0300
@@ -148,6 +148,12 @@
   m_root.whenExpire = Simulator::Now ();
 }
 void
+HwmpRtable::DeleteProactivePath (Mac48Address root)
+{
+  if(m_root.root == root)
+    DeleteProactivePath ();
+}
+void
 HwmpRtable::DeleteReactivePath (Mac48Address destination, uint32_t interface)
 {
   std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
@@ -177,6 +183,24 @@
   return result;
 }
 HwmpRtable::LookupResult
+HwmpRtable::LookupReactiveExpired (Mac48Address destination)
+{
+  LookupResult result;
+  result.retransmitter = Mac48Address::GetBroadcast ();
+  result.metric = MAX_METRIC;
+  result.ifIndex = INTERFACE_ANY;
+
+  std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
+  if (i == m_routes.end ())
+    return result;
+  result.ifIndex = i->second.interface;
+  result.retransmitter = i->second.retransmitter;
+  result.metric = i->second.metric;
+  result.seqnum = i->second.seqnum;
+  return result;
+}
+
+HwmpRtable::LookupResult
 HwmpRtable::LookupProactive ()
 {
   if (m_root.whenExpire < Simulator::Now ())
@@ -188,6 +212,16 @@
   retval.seqnum = m_root.seqnum;
   return retval;
 }
+HwmpRtable::LookupResult
+HwmpRtable::LookupProactiveExpired ()
+{
+  LookupResult retval;
+  retval.retransmitter = m_root.retransmitter;
+  retval.ifIndex = m_root.interface;
+  retval.metric = m_root.metric;
+  retval.seqnum = m_root.seqnum;
+  return retval;
+}
 std::vector<IePerr::FailedDestination>
 HwmpRtable::GetUnreachableDestinations (Mac48Address peerAddress, uint32_t interface)
 {
@@ -204,7 +238,7 @@
   /**
    * Lookup a path to root
    */
-  if (m_root.retransmitter == peerAddress)
+  if ((m_root.retransmitter == peerAddress) &&(m_root.interface == interface))
     {
       IePerr::FailedDestination dst;
       dst.destination = m_root.root;
@@ -213,14 +247,6 @@
     }
   return retval;
 }
-uint32_t
-HwmpRtable::RequestSeqnum (Mac48Address destination)
-{
-  std::map<Mac48Address, ReactiveRoute>::iterator i = m_routes.find (destination);
-  if (i == m_routes.end ())
-    return 0;
-  return i->second.seqnum;
-}
 std::vector<Mac48Address>
 HwmpRtable::GetPrecursors (Mac48Address destination, uint32_t interface)
 {
--- a/src/devices/mesh/dot11s/hwmp-rtable.h	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/hwmp-rtable.h	Fri Mar 27 16:33:08 2009 +0300
@@ -56,6 +56,7 @@
   );
   void AddPrecursor (Mac48Address destination, uint32_t interface, Mac48Address precursor);
   void DeleteProactivePath ();
+  void DeleteProactivePath (Mac48Address root);
   void DeleteReactivePath (Mac48Address destination, uint32_t interface);
   struct LookupResult
   {
@@ -64,11 +65,12 @@
     uint32_t metric;
     uint32_t seqnum;
   };
-  LookupResult  LookupReactive (Mac48Address destination);
-  LookupResult  LookupProactive ();
+  LookupResult LookupReactive (Mac48Address destination);
+  LookupResult LookupReactiveExpired (Mac48Address destination);
+  LookupResult LookupProactive ();
+  LookupResult LookupProactiveExpired ();
   //path error routines:
   std::vector<IePerr::FailedDestination>  GetUnreachableDestinations (Mac48Address peerAddress, uint32_t interface);
-  uint32_t  RequestSeqnum (Mac48Address dst);
   std::vector<Mac48Address>  GetPrecursors (Mac48Address destination, uint32_t interface);
   const static uint32_t INTERFACE_ANY = 0xffffffff;
   const static uint32_t MAX_METRIC = 0xffffffff;
--- a/src/devices/mesh/dot11s/wscript	Fri Mar 27 13:46:02 2009 +0300
+++ b/src/devices/mesh/dot11s/wscript	Fri Mar 27 16:33:08 2009 +0300
@@ -28,7 +28,7 @@
         'ie-dot11s-peer-management.h',
         #'ie-dot11s-preq.h',
         #'ie-dot11s-prep.h',
-        #'ie-dot11s-perr.h',
+        'ie-dot11s-perr.h',
         #'ie-dot11s-rann.h',
         #'peer-link-frame.h',
         #'peer-link.h',