[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