fix bug 185
authorMathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sun, 25 May 2008 14:44:36 -0700
changeset 3151 428f8ec6da29
parent 3150 7350a68e5856
child 3152 4260de124c74
fix bug 185
src/internet-node/arp-cache.cc
src/internet-node/arp-cache.h
src/internet-node/arp-l3-protocol.cc
--- a/src/internet-node/arp-cache.cc	Sun May 25 14:44:14 2008 -0700
+++ b/src/internet-node/arp-cache.cc	Sun May 25 14:44:36 2008 -0700
@@ -20,11 +20,15 @@
 #include "ns3/assert.h"
 #include "ns3/packet.h"
 #include "ns3/simulator.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
 
 #include "arp-cache.h"
 #include "arp-header.h"
 #include "ipv4-interface.h"
 
+NS_LOG_COMPONENT_DEFINE ("ArpCache");
+
 namespace ns3 {
 
 TypeId 
@@ -47,6 +51,11 @@
                    TimeValue (Seconds (1)),
                    MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
                    MakeTimeChecker ())
+    .AddAttribute ("PendingQueueSize",
+                   "The size of the queue for packets pending an arp reply.",
+                   UintegerValue (3),
+                   MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
+                   MakeUintegerChecker<uint32_t> ())
     ;
   return tid;
 }
@@ -54,11 +63,23 @@
 ArpCache::ArpCache ()
   : m_device (0), 
     m_interface (0)
-{}
+{
+  NS_LOG_FUNCTION (this);
+}
 
 ArpCache::~ArpCache ()
 {
+  NS_LOG_FUNCTION (this);
+}
+
+void 
+ArpCache::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
   Flush ();
+  m_device = 0;
+  m_interface = 0;
+  Object::DoDispose ();
 }
 
 void
@@ -145,8 +166,7 @@
 
 ArpCache::Entry::Entry (ArpCache *arp)
   : m_arp (arp),
-    m_state (ALIVE),
-    m_waiting ()
+    m_state (ALIVE)
 {}
 
 
@@ -171,23 +191,18 @@
 ArpCache::Entry::MarkDead (void) 
 {
   m_state = DEAD;
-  //NS_ASSERT (m_waiting != 0);
   UpdateSeen ();
 }
-Ptr<Packet>
+void
 ArpCache::Entry::MarkAlive (Address macAddress) 
 {
   NS_ASSERT (m_state == WAIT_REPLY);
-  //NS_ASSERT (m_waiting != 0);
   m_macAddress = macAddress;
   m_state = ALIVE;
   UpdateSeen ();
-  Ptr<Packet> waiting = m_waiting;
-  //m_waiting = 0;
-  return waiting;
 }
 
-Ptr<Packet>
+bool
 ArpCache::Entry::UpdateWaitReply (Ptr<Packet> waiting)
 {
   NS_ASSERT (m_state == WAIT_REPLY);
@@ -195,17 +210,20 @@
    * we dump the previously waiting packet and
    * replace it with this one.
    */
-  Ptr<Packet> old = m_waiting;
-  m_waiting = waiting;
-  return old;
+  if (m_pending.size () >= m_arp->m_pendingQueueSize)
+    {
+      return false;
+    }
+  m_pending.push_back (waiting);
+  return true;
 }
 void 
 ArpCache::Entry::MarkWaitReply (Ptr<Packet> waiting)
 {
   NS_ASSERT (m_state == ALIVE || m_state == DEAD);
-  //NS_ASSERT (m_waiting == 0);
+  NS_ASSERT (m_pending.empty ());
   m_state = WAIT_REPLY;
-  m_waiting = waiting;
+  m_pending.push_back (waiting);
   UpdateSeen ();
 }
 
@@ -245,6 +263,20 @@
       return false;
     }
 }
+Ptr<Packet> 
+ArpCache::Entry::DequeuePending (void)
+{
+  if (m_pending.empty ())
+    {
+      return 0;
+    }
+  else
+    {
+      Ptr<Packet> p = m_pending.front ();
+      m_pending.pop_front ();
+      return p;
+    }
+}
 void 
 ArpCache::Entry::UpdateSeen (void)
 {
--- a/src/internet-node/arp-cache.h	Sun May 25 14:44:14 2008 -0700
+++ b/src/internet-node/arp-cache.h	Sun May 25 14:44:36 2008 -0700
@@ -21,6 +21,7 @@
 #define ARP_CACHE_H
 
 #include <stdint.h>
+#include <list>
 #include "ns3/packet.h"
 #include "ns3/nstime.h"
 #include "ns3/net-device.h"
@@ -103,9 +104,8 @@
     void MarkDead (void);
     /**
      * \param macAddress
-     * \return 
      */
-    Ptr<Packet> MarkAlive (Address macAddress);
+    void MarkAlive (Address macAddress);
     /**
      * \param waiting
      */
@@ -114,7 +114,7 @@
      * \param waiting
      * \return 
      */
-    Ptr<Packet> UpdateWaitReply (Ptr<Packet> waiting);
+    bool UpdateWaitReply (Ptr<Packet> waiting);
     /**
      * \return True if the state of this entry is dead; false otherwise.
      */
@@ -136,6 +136,12 @@
      * \return True if this entry has timedout; false otherwise.
      */
     bool IsExpired (void);
+
+    /**
+     * \returns 0 is no packet is pending, the next packet to send if 
+     *            packets are pending.
+     */
+    Ptr<Packet> DequeuePending (void);
   private:
     enum ArpCacheEntryState_e {
       ALIVE,
@@ -148,18 +154,21 @@
     ArpCacheEntryState_e m_state;
     Time m_lastSeen;
     Address m_macAddress;
-    Ptr<Packet> m_waiting;
+    std::list<Ptr<Packet> > m_pending;
   };
 
 private:
   typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash> Cache;
   typedef sgi::hash_map<Ipv4Address, ArpCache::Entry *, Ipv4AddressHash>::iterator CacheI;
 
+  virtual void DoDispose (void);
+
   Ptr<NetDevice> m_device;
   Ptr<Ipv4Interface> m_interface;
   Time m_aliveTimeout;
   Time m_deadTimeout;
   Time m_waitReplyTimeout;
+  uint32_t m_pendingQueueSize;
   Cache m_arpCache;
 };
 
--- a/src/internet-node/arp-l3-protocol.cc	Sun May 25 14:44:14 2008 -0700
+++ b/src/internet-node/arp-l3-protocol.cc	Sun May 25 14:44:36 2008 -0700
@@ -53,12 +53,12 @@
 
 ArpL3Protocol::ArpL3Protocol ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 ArpL3Protocol::~ArpL3Protocol ()
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
 }
 
 void 
@@ -70,7 +70,12 @@
 void 
 ArpL3Protocol::DoDispose (void)
 {
-  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_FUNCTION (this);
+  for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
+    {
+      Ptr<ArpCache> cache = *i;
+      cache->Dispose ();
+    }
   m_cacheList.clear ();
   m_node = 0;
   Object::DoDispose ();
@@ -145,8 +150,17 @@
                         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);
+              while (true)
+                {
+                  Ptr<Packet> pending = entry->DequeuePending();
+                  if (pending != 0)
+                    {
+                      break;
+                    }
+                  cache->GetInterface ()->Send (pending,
+                                                arp.GetSourceIpv4Address ());
+                }
             } 
           else 
             {
@@ -210,25 +224,24 @@
           if (entry->IsDead ()) 
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
-                        ", dead entry for " << destination << " valid -- drop");
+                            ", dead entry for " << destination << " valid -- drop");
 	      // XXX report packet as 'dropped'
             } 
           else if (entry->IsAlive ()) 
             {
               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
-                        ", alive entry for " << destination << " valid -- send");
+                            ", alive entry for " << destination << " valid -- send");
 	      *hardwareDestination = entry->GetMacAddress ();
               return true;
             } 
           else if (entry->IsWaitReply ()) 
             {
               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'
+                            ", wait reply for " << destination << " valid -- drop previous");
+              // XXX potentially report current packet as 'dropped'
+              entry->UpdateWaitReply (packet);
             }
         }
-
     }
   else
     {