[Ns-developers] ARP pending queue

Guillaume Vu-Brugier gvubrugier at gmail.com
Thu Apr 3 10:33:10 PDT 2008


Here is the patch (the attachment did not reach the mailing list...)

diff -r 1d829915f092 src/internet-node/arp-cache.cc
--- a/src/internet-node/arp-cache.cc	Thu Apr 03 14:15:17 2008 +0100
+++ b/src/internet-node/arp-cache.cc	Thu Apr 03 18:39:13 2008 +0200
@@ -24,6 +24,7 @@
 #include "arp-cache.h"
 #include "arp-header.h"
 #include "ipv4-interface.h"
+#include "ns3/uinteger.h"

 namespace ns3 {

@@ -32,7 +33,8 @@ ArpCache::ArpCache (Ptr<NetDevice> devic
     m_interface (interface),
     m_aliveTimeout (Seconds (120)),
     m_deadTimeout (Seconds (100)),
-    m_waitReplyTimeout (Seconds (1))
+    m_waitReplyTimeout (Seconds (1)),
+    m_unresQlen (3)
 {}

 ArpCache::~ArpCache ()
@@ -110,16 +112,18 @@ ArpCache::Add (Ipv4Address to)
 {
   NS_ASSERT (m_arpCache.find (to) == m_arpCache.end ());

-  ArpCache::Entry *entry = new ArpCache::Entry (this);
+  ArpCache::Entry *entry = new ArpCache::Entry (this,m_unresQlen);
   m_arpCache[to] = entry;
   return entry;
 }

-ArpCache::Entry::Entry (ArpCache *arp)
+ArpCache::Entry::Entry (ArpCache *arp, uint32_t unresQlen)
   : m_arp (arp),
     m_state (ALIVE),
-    m_waiting ()
-{}
+    m_unresQlen (unresQlen)
+{
+  m_pendingQueue = CreateObject<DropTailQueue>
("MaxPackets",Uinteger(m_unresQlen));
+}


 bool
@@ -146,7 +150,7 @@ ArpCache::Entry::MarkDead (void)
   //NS_ASSERT (m_waiting != 0);
   UpdateSeen ();
 }
-Ptr<Packet>
+void
 ArpCache::Entry::MarkAlive (Address macAddress)
 {
   NS_ASSERT (m_state == WAIT_REPLY);
@@ -154,22 +158,18 @@ ArpCache::Entry::MarkAlive (Address macA
   m_macAddress = macAddress;
   m_state = ALIVE;
   UpdateSeen ();
-  Ptr<Packet> waiting = m_waiting;
-  //m_waiting = 0;
-  return waiting;
 }
-
 Ptr<Packet>
+ArpCache::Entry::DequeueUnres (void)
+{
+  //  NS_ASSERT (m_state == WAIT_REPLY);
+  return m_pendingQueue->Dequeue();
+}
+bool
 ArpCache::Entry::UpdateWaitReply (Ptr<Packet> waiting)
 {
   NS_ASSERT (m_state == WAIT_REPLY);
-  /* We are already waiting for an answer so
-   * we dump the previously waiting packet and
-   * replace it with this one.
-   */
-  Ptr<Packet> old = m_waiting;
-  m_waiting = waiting;
-  return old;
+  return m_pendingQueue->Enqueue(waiting);
 }
 void
 ArpCache::Entry::MarkWaitReply (Ptr<Packet> waiting)
@@ -177,7 +177,7 @@ ArpCache::Entry::MarkWaitReply (Ptr<Pack
   NS_ASSERT (m_state == ALIVE || m_state == DEAD);
   //NS_ASSERT (m_waiting == 0);
   m_state = WAIT_REPLY;
-  m_waiting = waiting;
+  m_pendingQueue->Enqueue(waiting);
   UpdateSeen ();
 }

diff -r 1d829915f092 src/internet-node/arp-cache.h
--- a/src/internet-node/arp-cache.h	Thu Apr 03 14:15:17 2008 +0100
+++ b/src/internet-node/arp-cache.h	Thu Apr 03 18:39:13 2008 +0200
@@ -27,6 +27,7 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/address.h"
 #include "ns3/ptr.h"
+#include "ns3/drop-tail-queue.h"
 #include "sgi-hashmap.h"

 namespace ns3 {
@@ -90,17 +91,17 @@ public:
      * \brief Constructor
      * \param arp The ArpCache this entry belongs to
      */
-    Entry (ArpCache *arp);
+    Entry (ArpCache *arp, uint32_t unresQlen);

     /**
      * \brief Changes the state of this entry to dead
      */
     void MarkDead (void);
-    /**
+   /**
      * \param macAddress
      * \return
      */
-    Ptr<Packet> MarkAlive (Address macAddress);
+    void MarkAlive (Address macAddress);
     /**
      * \param waiting
      */
@@ -109,7 +110,11 @@ public:
      * \param waiting
      * \return
      */
-    Ptr<Packet> UpdateWaitReply (Ptr<Packet> waiting);
+    bool UpdateWaitReply (Ptr<Packet> waiting);
+    /**
+     * \return The packet, if successfully dequeued, 0 otherwise
+     */
+    Ptr<Packet> DequeueUnres (void);
     /**
      * \return True if the state of this entry is dead; false otherwise.
      */
@@ -143,7 +148,9 @@ public:
     ArpCacheEntryState_e m_state;
     Time m_lastSeen;
     Address m_macAddress;
-    Ptr<Packet> m_waiting;
+    //Ptr<Packet> m_waiting;
+    Ptr<DropTailQueue> m_pendingQueue;
+    uint32_t m_unresQlen;
   };

 private:
@@ -156,6 +163,7 @@ private:
   Time m_deadTimeout;
   Time m_waitReplyTimeout;
   Cache m_arpCache;
+  uint32_t m_unresQlen;
 };


diff -r 1d829915f092 src/internet-node/arp-ipv4-interface.cc
--- a/src/internet-node/arp-ipv4-interface.cc	Thu Apr 03 14:15:17 2008 +0100
+++ b/src/internet-node/arp-ipv4-interface.cc	Thu Apr 03 18:39:13 2008 +0200
@@ -24,6 +24,7 @@
 #include "ns3/node.h"
 #include "ns3/net-device.h"
 #include "ns3/address.h"
+#include "ns3/simulator.h"

 #include "arp-ipv4-interface.h"
 #include "ipv4-l3-protocol.h"
@@ -107,10 +108,12 @@ ArpIpv4Interface::SendTo (Ptr<Packet> p,

       if (found)
         {
-          NS_LOG_LOGIC ("Address Resolved.  Send.");
+          NS_LOG_LOGIC ("Address Resolved.  Send." << p->GetUid() <<
" @" << Simulator::Now ().GetSeconds ());
           GetDevice ()->Send (p, hardwareDestination,
             Ipv4L3Protocol::PROT_NUMBER);
         }
+      else
+        NS_LOG_LOGIC ("Unable to resolve " << p->GetUid() << " " << dest);
     }
   else
     {
diff -r 1d829915f092 src/internet-node/arp-l3-protocol.cc
--- a/src/internet-node/arp-l3-protocol.cc	Thu Apr 03 14:15:17 2008 +0100
+++ b/src/internet-node/arp-l3-protocol.cc	Thu Apr 03 18:39:13 2008 +0200
@@ -130,8 +130,16 @@ ArpL3Protocol::Receive(Ptr<NetDevice> de
                         arp.GetSourceIpv4Address ()
                      << " for waiting entry -- flush");
               Address from_mac = arp.GetSourceHardwareAddress ();
-              Ptr<Packet> waiting = entry->MarkAlive (from_mac);
-	      cache->GetInterface ()->Send (waiting, arp.GetSourceIpv4Address ());
+
+              entry->MarkAlive (from_mac);
+              for (;;)
+                {
+                  Ptr<Packet> waiting = entry->DequeueUnres();
+                  if (!waiting)
+                    break;
+                  cache->GetInterface ()->Send (waiting,
arp.GetSourceIpv4Address ());
+                }
+
             }
           else
             {
@@ -209,8 +217,8 @@ ArpL3Protocol::Lookup (Ptr<Packet> packe
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
                         ", wait reply for " << destination << " valid
-- drop previous");
-              Ptr<Packet> old = entry->UpdateWaitReply (packet);
-	      // XXX report 'old' packet as 'dropped'
+              entry->UpdateWaitReply (packet);
+	      // XXX potentially report current packet as 'dropped'
             }
         }




2008/4/3, Guillaume Vu-Brugier <gvubrugier at gmail.com>:
> Hi,
>
> I recently spent a lot of time debugging a ns-3 program involving TCP and UDP flows over a CSMA network.
> The problem was that 2 flows were competing at the beginning of the simulation and a TCP SYN segment was lost during the ARP address resolution step, thus delaying this flow for 3s.
>
> I believe that the ARP implementation should buffer more than one outgoing packets while waiting for the ARP reply :
> The Linux kernel seems to do this (with a default 3-packet buffer configured in /proc/sys/net/ipv4/neigh/DEV/unres_qlen [1]) and the Omnet++ INET framework too [2].
>
> The attached patch modifies arp-cache and arp-l3-protocol to provide such a functionality. It is not complete nor thoroughly tested but solved my initial problem, comments are welcomed.
>
> Refs.
> [1] http://lartc.org/howto/lartc.kernel.obscure.html - 13.2.3 'Neighbor policy'
>  [2] http://www.omnetpp.org/doc/INET/walkthrough/tutorial.html#pendingqueue
>
> --
> Guillaume
>
>


More information about the Ns-developers mailing list