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);