Device Emulation (contd.): 'Resolve Neighbors' will now resend ARP/NDP requests for unresolved entries

This commit is contained in:
Srivats P 2016-03-17 20:12:13 +05:30
parent 6a7a17cd36
commit 72bab2737f
5 changed files with 55 additions and 10 deletions

View File

@ -625,6 +625,19 @@ void AbstractPort::clearDeviceNeighbors()
void AbstractPort::resolveDeviceNeighbors() void AbstractPort::resolveDeviceNeighbors()
{ {
// For a user triggered 'Resolve Neighbors', the behaviour we want is
// IP not in cache - send ARP/NDP request
// IP present in cache, but unresolved - re-send ARP/NDP request
// IP present in cache and resolved - don't sent ARP/NDP
//
// Device does not resend ARP/NDP requests if the IP address is
// already present in the cache, irrespective of whether it is
// resolved or not (this is done to avoid sending duplicate requests).
//
// So, to get the behaviour we want, let's clear all unresolved neighbors
// before calling resolve
deviceManager_->clearDeviceNeighbors(Device::kUnresolvedNeighbors);
// Resolve gateway for each device first ... // Resolve gateway for each device first ...
deviceManager_->resolveDeviceGateways(); deviceManager_->resolveDeviceGateways();

View File

@ -265,10 +265,33 @@ void Device::resolveGateway()
sendNeighborSolicit(ip6Gateway_); sendNeighborSolicit(ip6Gateway_);
} }
void Device::clearNeighbors() void Device::clearNeighbors(Device::NeighborSet set)
{ {
arpTable_.clear(); QMutableHashIterator<quint32, quint64> arpIter(arpTable_);
ndpTable_.clear(); QMutableHashIterator<UInt128, quint64> ndpIter(ndpTable_);
switch (set) {
case kAllNeighbors:
arpTable_.clear();
ndpTable_.clear();
break;
case kUnresolvedNeighbors:
while (arpIter.hasNext()) {
arpIter.next();
if (arpIter.value() == 0)
arpIter.remove();
}
while (ndpIter.hasNext()) {
ndpIter.next();
if (ndpIter.value() == 0)
ndpIter.remove();
}
break;
default:
Q_ASSERT(false); // Unreachable!
}
} }
// Resolve the Neighbor IP address for this to-be-transmitted pktBuf // Resolve the Neighbor IP address for this to-be-transmitted pktBuf
@ -564,8 +587,12 @@ void Device::sendArpRequest(quint32 tgtIp)
if (!tgtIp) if (!tgtIp)
return; return;
// Do we already have a ARP entry (resolved or unresolved)? // This function will be called once per unique stream - which
// XXX: No NDP state machine for now // may all have the same dst IP; even if dst IP are different the
// gateway for the different dst IP may all be same. However,
// we don't want to send duplicate ARP requests, so we check
// if the tgtIP is already in the cache (resolved or unresolved)
// and if so, we don't resend it
if (arpTable_.contains(tgtIp)) if (arpTable_.contains(tgtIp))
return; return;
@ -945,7 +972,7 @@ void Device::sendNeighborSolicit(UInt128 tgtIp)
return; return;
// Do we already have a NDP entry (resolved or unresolved)? // Do we already have a NDP entry (resolved or unresolved)?
// XXX: No ARP state machine for now // If so, don't resend (see note in sendArpRequest())
if (ndpTable_.contains(tgtIp)) if (ndpTable_.contains(tgtIp))
return; return;

View File

@ -39,6 +39,11 @@ class Device
public: public:
static const quint16 kVlanTpid = 0x8100; static const quint16 kVlanTpid = 0x8100;
enum NeighborSet {
kAllNeighbors,
kUnresolvedNeighbors
};
public: public:
Device(DeviceManager *deviceManager); Device(DeviceManager *deviceManager);
@ -61,7 +66,7 @@ public:
void resolveGateway(); void resolveGateway();
void clearNeighbors(); void clearNeighbors(Device::NeighborSet set);
void resolveNeighbor(PacketBuffer *pktBuf); void resolveNeighbor(PacketBuffer *pktBuf);
void getNeighbors(OstEmul::DeviceNeighborList *neighbors); void getNeighbors(OstEmul::DeviceNeighborList *neighbors);

View File

@ -258,10 +258,10 @@ void DeviceManager::resolveDeviceGateways()
} }
} }
void DeviceManager::clearDeviceNeighbors() void DeviceManager::clearDeviceNeighbors(Device::NeighborSet set)
{ {
foreach(Device *device, deviceList_) foreach(Device *device, deviceList_)
device->clearNeighbors(); device->clearNeighbors(set);
} }
void DeviceManager::getDeviceNeighbors( void DeviceManager::getDeviceNeighbors(

View File

@ -55,7 +55,7 @@ public:
void resolveDeviceGateways(); void resolveDeviceGateways();
void clearDeviceNeighbors(); void clearDeviceNeighbors(Device::NeighborSet set = Device::kAllNeighbors);
void resolveDeviceNeighbor(PacketBuffer *pktBuf); void resolveDeviceNeighbor(PacketBuffer *pktBuf);
void getDeviceNeighbors(OstProto::PortNeighborList *neighborList); void getDeviceNeighbors(OstProto::PortNeighborList *neighborList);