revised patch to fix bug 253
authorTom Henderson <tomh@tomh.org>
Wed Jul 30 06:30:42 2008 -0700 (18 months ago)
changeset 3499a18520551cdf
parent 3493 53ec8893863d
child 3500 8a4b1d0ae55c
revised patch to fix bug 253
src/internet-stack/arp-cache.cc
src/internet-stack/arp-cache.h
src/internet-stack/arp-l3-protocol.cc
src/internet-stack/arp-l3-protocol.h
     1.1 --- a/src/internet-stack/arp-cache.cc	Tue Jul 29 15:36:41 2008 -0400
     1.2 +++ b/src/internet-stack/arp-cache.cc	Wed Jul 30 06:30:42 2008 -0700
     1.3 @@ -22,6 +22,8 @@
     1.4  #include "ns3/simulator.h"
     1.5  #include "ns3/uinteger.h"
     1.6  #include "ns3/log.h"
     1.7 +#include "ns3/node.h"
     1.8 +#include "ns3/trace-source-accessor.h"
     1.9  
    1.10  #include "arp-cache.h"
    1.11  #include "arp-header.h"
    1.12 @@ -47,15 +49,23 @@
    1.13                     MakeTimeAccessor (&ArpCache::m_deadTimeout),
    1.14                     MakeTimeChecker ())
    1.15      .AddAttribute ("WaitReplyTimeout",
    1.16 -                   "When this timeout expires, the matching cache entry is marked dead",
    1.17 +                   "When this timeout expires, the cache entries will be scanned and entries in WaitReply state will resend ArpRequest unless MaxRetries has been exceeded, in which case the entry is marked dead",           
    1.18                     TimeValue (Seconds (1)),
    1.19                     MakeTimeAccessor (&ArpCache::m_waitReplyTimeout),
    1.20                     MakeTimeChecker ())
    1.21 +    .AddAttribute ("MaxRetries",                   
    1.22 +                   "Number of retransmissions of ArpRequest before marking dead",                  
    1.23 +                   UintegerValue (3),
    1.24 +                   MakeUintegerAccessor (&ArpCache::m_maxRetries),
    1.25 +                   MakeUintegerChecker<uint32_t> ())
    1.26      .AddAttribute ("PendingQueueSize",
    1.27                     "The size of the queue for packets pending an arp reply.",
    1.28                     UintegerValue (3),
    1.29                     MakeUintegerAccessor (&ArpCache::m_pendingQueueSize),
    1.30                     MakeUintegerChecker<uint32_t> ())
    1.31 +    .AddTraceSource ("Drop",                     
    1.32 +                     "Packet dropped due to ArpCache entry in WaitReply expiring.",
    1.33 +                     MakeTraceSourceAccessor (&ArpCache::m_dropTrace))
    1.34      ;
    1.35    return tid;
    1.36  }
    1.37 @@ -79,6 +89,10 @@
    1.38    Flush ();
    1.39    m_device = 0;
    1.40    m_interface = 0;
    1.41 +  if (!m_waitReplyTimer.IsRunning ())
    1.42 +    {
    1.43 +      Simulator::Remove (m_waitReplyTimer);
    1.44 +    }
    1.45    Object::DoDispose ();
    1.46  }
    1.47  
    1.48 @@ -143,6 +157,73 @@
    1.49  }
    1.50  
    1.51  void 
    1.52 +ArpCache::SetArpRequestCallback (Callback<void, Ptr<const ArpCache>,
    1.53 +                             Ipv4Address> arpRequestCallback)
    1.54 +{
    1.55 +  NS_LOG_FUNCTION_NOARGS ();
    1.56 +  m_arpRequestCallback = arpRequestCallback;
    1.57 +}
    1.58 +
    1.59 +void 
    1.60 +ArpCache::StartWaitReplyTimer (void)
    1.61 +{
    1.62 +  NS_LOG_FUNCTION_NOARGS ();
    1.63 +  if (!m_waitReplyTimer.IsRunning ())
    1.64 +    {
    1.65 +      NS_LOG_LOGIC ("Starting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
    1.66 +      m_waitReplyTimer = Simulator::Schedule (m_waitReplyTimeout, 
    1.67 +        &ArpCache::HandleWaitReplyTimeout, this);
    1.68 +    }
    1.69 +}
    1.70 +
    1.71 +void
    1.72 +ArpCache::HandleWaitReplyTimeout (void)
    1.73 +{
    1.74 +  NS_LOG_FUNCTION_NOARGS ();
    1.75 +  ArpCache::Entry* entry;
    1.76 +  bool restartWaitReplyTimer = false;
    1.77 +  for (CacheI i = m_arpCache.begin (); i != m_arpCache.end (); i++) 
    1.78 +    {
    1.79 +      entry = (*i).second;
    1.80 +      if (entry != 0 && entry->IsWaitReply () && entry->IsExpired ())
    1.81 +          {
    1.82 +          if (entry->GetRetries () < m_maxRetries)
    1.83 +            {
    1.84 +              NS_LOG_LOGIC ("node="<< m_device->GetNode ()->GetId () <<
    1.85 +                ", ArpWaitTimeout for " << entry->GetIpv4Address () <<
    1.86 +                " expired -- retransmitting arp request since retries = " << 
    1.87 +                entry->GetRetries ());
    1.88 +              m_arpRequestCallback (this, entry->GetIpv4Address ());
    1.89 +              restartWaitReplyTimer = true;
    1.90 +              entry->IncrementRetries ();
    1.91 +            }
    1.92 +          else
    1.93 +            {
    1.94 +              NS_LOG_LOGIC ("node="<<m_device->GetNode ()->GetId () <<
    1.95 +                ", wait reply for " << entry->GetIpv4Address () << 
    1.96 +                " expired -- drop since max retries exceeded: " << 
    1.97 +                 entry->GetRetries ());
    1.98 +              entry->MarkDead ();
    1.99 +              entry->ClearRetries ();
   1.100 +              Ptr<Packet> pending = entry->DequeuePending();
   1.101 +              while (pending != 0)
   1.102 +                {
   1.103 +                  m_dropTrace (pending);
   1.104 +                  pending = entry->DequeuePending();
   1.105 +                }
   1.106 +            }
   1.107 +       }
   1.108 +
   1.109 +    }
   1.110 +  if (restartWaitReplyTimer)
   1.111 +    {
   1.112 +      NS_LOG_LOGIC ("Restarting WaitReplyTimer at " << Simulator::Now ().GetSeconds ());
   1.113 +      m_waitReplyTimer = Simulator::Schedule (m_waitReplyTimeout, 
   1.114 +        &ArpCache::HandleWaitReplyTimeout, this);
   1.115 +    }
   1.116 +}
   1.117 +
   1.118 +void 
   1.119  ArpCache::Flush (void)
   1.120  {
   1.121    NS_LOG_FUNCTION_NOARGS ();
   1.122 @@ -173,12 +254,14 @@
   1.123  
   1.124    ArpCache::Entry *entry = new ArpCache::Entry (this);
   1.125    m_arpCache[to] = entry;  
   1.126 +  entry->SetIpv4Address (to);
   1.127    return entry;
   1.128  }
   1.129  
   1.130  ArpCache::Entry::Entry (ArpCache *arp)
   1.131    : m_arp (arp),
   1.132 -    m_state (ALIVE)
   1.133 +    m_state (ALIVE),
   1.134 +    m_retries (0)
   1.135  {
   1.136    NS_LOG_FUNCTION_NOARGS ();
   1.137  }
   1.138 @@ -209,6 +292,7 @@
   1.139  {
   1.140    NS_LOG_FUNCTION_NOARGS ();
   1.141    m_state = DEAD;
   1.142 +  ClearRetries ();
   1.143    UpdateSeen ();
   1.144  }
   1.145  void
   1.146 @@ -218,6 +302,7 @@
   1.147    NS_ASSERT (m_state == WAIT_REPLY);
   1.148    m_macAddress = macAddress;
   1.149    m_state = ALIVE;
   1.150 +  ClearRetries ();
   1.151    UpdateSeen ();
   1.152  }
   1.153  
   1.154 @@ -246,15 +331,29 @@
   1.155    m_state = WAIT_REPLY;
   1.156    m_pending.push_back (waiting);
   1.157    UpdateSeen ();
   1.158 +  m_arp->StartWaitReplyTimer ();
   1.159  }
   1.160  
   1.161  Address
   1.162 -ArpCache::Entry::GetMacAddress (void)
   1.163 +ArpCache::Entry::GetMacAddress (void) const
   1.164  {
   1.165    NS_LOG_FUNCTION_NOARGS ();
   1.166    NS_ASSERT (m_state == ALIVE);
   1.167    return m_macAddress;
   1.168  }
   1.169 +Ipv4Address 
   1.170 +ArpCache::Entry::GetIpv4Address (void) const
   1.171 +{
   1.172 +  NS_LOG_FUNCTION_NOARGS ();
   1.173 +  return m_ipv4Address;
   1.174 +}
   1.175 +void 
   1.176 +ArpCache::Entry::SetIpv4Address (Ipv4Address destination)
   1.177 +{
   1.178 +  NS_LOG_FUNCTION (this << destination);
   1.179 +  m_ipv4Address = destination;
   1.180 +}
   1.181 +
   1.182  bool 
   1.183  ArpCache::Entry::IsExpired (void)
   1.184  {
   1.185 @@ -307,6 +406,25 @@
   1.186    NS_LOG_FUNCTION_NOARGS ();
   1.187    m_lastSeen = Simulator::Now ();
   1.188  }
   1.189 +uint32_t
   1.190 +ArpCache::Entry::GetRetries (void) const
   1.191 +{
   1.192 +  NS_LOG_FUNCTION_NOARGS ();
   1.193 +  return m_retries;
   1.194 +}
   1.195 +void
   1.196 +ArpCache::Entry::IncrementRetries (void)
   1.197 +{
   1.198 +  NS_LOG_FUNCTION_NOARGS ();
   1.199 +  m_retries++;
   1.200 +  UpdateSeen ();
   1.201 +}
   1.202 +void
   1.203 +ArpCache::Entry::ClearRetries (void)
   1.204 +{
   1.205 +  NS_LOG_FUNCTION_NOARGS ();
   1.206 +  m_retries = 0;
   1.207 +}
   1.208  
   1.209  } // namespace ns3
   1.210  
     2.1 --- a/src/internet-stack/arp-cache.h	Tue Jul 29 15:36:41 2008 -0400
     2.2 +++ b/src/internet-stack/arp-cache.h	Wed Jul 30 06:30:42 2008 -0700
     2.3 @@ -22,6 +22,8 @@
     2.4  
     2.5  #include <stdint.h>
     2.6  #include <list>
     2.7 +#include "ns3/simulator.h"
     2.8 +#include "ns3/callback.h"
     2.9  #include "ns3/packet.h"
    2.10  #include "ns3/nstime.h"
    2.11  #include "ns3/net-device.h"
    2.12 @@ -29,6 +31,7 @@
    2.13  #include "ns3/address.h"
    2.14  #include "ns3/ptr.h"
    2.15  #include "ns3/object.h"
    2.16 +#include "ns3/traced-callback.h"
    2.17  #include "sgi-hashmap.h"
    2.18  
    2.19  namespace ns3 {
    2.20 @@ -72,7 +75,22 @@
    2.21    Time GetWaitReplyTimeout (void) const;
    2.22  
    2.23    /**
    2.24 -   * \brief Do lookup in the ARP chache against an IP address
    2.25 +   * This callback is set when the ArpCache is set up and allows
    2.26 +   * the cache to generate an Arp request when the WaitReply
    2.27 +   * time expires and a retransmission must be sent
    2.28 +   *
    2.29 +   * \param arpRequestCallback Callback for transmitting an Arp request.
    2.30 +   */
    2.31 +  void SetArpRequestCallback (Callback<void, Ptr<const ArpCache>, 
    2.32 +                             Ipv4Address> arpRequestCallback);
    2.33 +  /**
    2.34 +   * This method will schedule a timeout at WaitReplyTimeout interval
    2.35 +   * in the future, unless a timer is already running for the cache,
    2.36 +   * in which case this method does nothing.
    2.37 +   */
    2.38 +  void StartWaitReplyTimer (void);
    2.39 +  /**
    2.40 +   * \brief Do lookup in the ARP cache against an IP address
    2.41     * \param destination The destination IPv4 address to lookup the MAC address
    2.42     * of
    2.43     * \return An ArpCache::Entry with info about layer 2
    2.44 @@ -131,7 +149,15 @@
    2.45      /**
    2.46       * \return The MacAddress of this entry
    2.47       */
    2.48 -    Address GetMacAddress (void);
    2.49 +    Address GetMacAddress (void) const;
    2.50 +    /**
    2.51 +     * \return The Ipv4Address for this entry
    2.52 +     */
    2.53 +    Ipv4Address GetIpv4Address (void) const;
    2.54 +    /**
    2.55 +     * \param The Ipv4Address for this entry
    2.56 +     */
    2.57 +    void SetIpv4Address (Ipv4Address destination);
    2.58      /**
    2.59       * \return True if this entry has timedout; false otherwise.
    2.60       */
    2.61 @@ -142,6 +168,20 @@
    2.62       *            packets are pending.
    2.63       */
    2.64      Ptr<Packet> DequeuePending (void);
    2.65 +    /**
    2.66 +     * \returns number of retries that have been sent for an ArpRequest
    2.67 +     *  in WaitReply state.
    2.68 +     */
    2.69 +    uint32_t GetRetries (void) const;
    2.70 +    /**
    2.71 +     * \brief Increment the counter of number of retries for an entry
    2.72 +     */
    2.73 +    void IncrementRetries (void);
    2.74 +    /**
    2.75 +     * \brief Zero the counter of number of retries for an entry
    2.76 +     */
    2.77 +    void ClearRetries (void);
    2.78 +
    2.79    private:
    2.80      enum ArpCacheEntryState_e {
    2.81        ALIVE,
    2.82 @@ -154,7 +194,9 @@
    2.83      ArpCacheEntryState_e m_state;
    2.84      Time m_lastSeen;
    2.85      Address m_macAddress;
    2.86 +    Ipv4Address m_ipv4Address;
    2.87      std::list<Ptr<Packet> > m_pending;
    2.88 +    uint32_t m_retries;
    2.89    };
    2.90  
    2.91  private:
    2.92 @@ -168,8 +210,18 @@
    2.93    Time m_aliveTimeout;
    2.94    Time m_deadTimeout;
    2.95    Time m_waitReplyTimeout;
    2.96 +  EventId m_waitReplyTimer;
    2.97 +  Callback<void, Ptr<const ArpCache>, Ipv4Address> m_arpRequestCallback;
    2.98 +  uint32_t m_maxRetries;
    2.99 +  /**
   2.100 +   * This function is an event handler for the event that the
   2.101 +   * ArpCache wants to check whether it must retry any Arp requests.
   2.102 +   * If there are no Arp requests pending, this event is not scheduled.
   2.103 +   */
   2.104 +  void HandleWaitReplyTimeout (void);
   2.105    uint32_t m_pendingQueueSize;
   2.106    Cache m_arpCache;
   2.107 +  TracedCallback<Ptr<const Packet> > m_dropTrace;
   2.108  };
   2.109  
   2.110  
     3.1 --- a/src/internet-stack/arp-l3-protocol.cc	Tue Jul 29 15:36:41 2008 -0400
     3.2 +++ b/src/internet-stack/arp-l3-protocol.cc	Wed Jul 30 06:30:42 2008 -0700
     3.3 @@ -95,6 +95,7 @@
     3.4    cache->SetDevice (device, interface);
     3.5    NS_ASSERT (device->IsBroadcast ());
     3.6    device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
     3.7 +  cache->SetArpRequestCallback (MakeCallback (&ArpL3Protocol::SendArpRequest, this));
     3.8    m_cacheList.push_back (cache);
     3.9    return cache;
    3.10  }
    3.11 @@ -218,16 +219,7 @@
    3.12              } 
    3.13            else if (entry->IsWaitReply ()) 
    3.14              {
    3.15 -              NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
    3.16 -                        ", wait reply for " << destination << " expired -- drop");
    3.17 -              entry->MarkDead ();
    3.18 -              Ptr<Packet> pending = entry->DequeuePending();
    3.19 -              while (pending != 0)
    3.20 -                {
    3.21 -                  m_dropTrace (pending);
    3.22 -                  pending = entry->DequeuePending();
    3.23 -                }
    3.24 -              m_dropTrace (packet);
    3.25 +              NS_FATAL_ERROR ("Test for possibly unreachable code-- please file a bug report if this is ever hit");
    3.26              }
    3.27          } 
    3.28        else 
     4.1 --- a/src/internet-stack/arp-l3-protocol.h	Tue Jul 29 15:36:41 2008 -0400
     4.2 +++ b/src/internet-stack/arp-l3-protocol.h	Wed Jul 30 06:30:42 2008 -0700
     4.3 @@ -52,7 +52,7 @@
     4.4    Ptr<ArpCache> CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface);
     4.5  
     4.6    /**
     4.7 -   * \brief Recieve a packet
     4.8 +   * \brief Receive a packet
     4.9     */
    4.10    void Receive(Ptr<NetDevice> device, Ptr<Packet> p, uint16_t protocol, const Address &from, const Address &to,
    4.11                 NetDevice::PacketType packetType);