Jonathan Hart
Committed by Gerrit Code Review

ProxyArp: Reply directly when we know an external target host

Change-Id: I38773dcdcae05506c678c2006d1f63306af6b383
......@@ -146,47 +146,25 @@ public class ProxyArpManager implements ProxyArpService {
VlanId vlan = VlanId.vlanId(eth.getVlanID());
// If the request came from outside the network, only reply if it was
// for one of our external addresses.
if (isOutsidePort(inPort)) {
// If the request came from outside the network, only reply if it was
// for one of our external addresses.
Set<PortAddresses> addressSet =
hostService.getAddressBindingsForPort(inPort);
hostService.getAddressBindingsForPort(inPort);
for (PortAddresses addresses : addressSet) {
for (InterfaceIpAddress ia : addresses.ipAddresses()) {
if (ia.ipAddress().equals(targetAddress)) {
Ethernet arpReply =
buildArpReply(targetAddress, addresses.mac(), eth);
buildArpReply(targetAddress, addresses.mac(), eth);
sendTo(arpReply, inPort);
}
}
}
return;
} else {
// If the source address matches one of our external addresses
// it could be a request from an internal host to an external
// address. Forward it over to the correct ports.
Ip4Address source =
Ip4Address.valueOf(arp.getSenderProtocolAddress());
Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
boolean matched = false;
for (PortAddresses pa : sourceAddresses) {
for (InterfaceIpAddress ia : pa.ipAddresses()) {
if (ia.ipAddress().equals(source) &&
pa.vlan().equals(vlan)) {
matched = true;
sendTo(eth, pa.connectPoint());
break;
}
}
}
if (matched) {
return;
}
}
// Continue with normal proxy ARP case
// See if we have the target host in the host store
Set<Host> hosts = hostService.getHostsByIp(targetAddress);
......@@ -201,20 +179,41 @@ public class ProxyArpManager implements ProxyArpService {
}
}
if (src == null || dst == null) {
//
// The request couldn't be resolved.
// Flood the request on all ports except the incoming ports.
//
flood(eth, inPort);
if (src != null && dst != null) {
// We know the target host so we can respond
Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth);
sendTo(arpReply, inPort);
return;
}
// If the source address matches one of our external addresses
// it could be a request from an internal host to an external
// address. Forward it over to the correct port.
Ip4Address source =
Ip4Address.valueOf(arp.getSenderProtocolAddress());
Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
boolean matched = false;
for (PortAddresses pa : sourceAddresses) {
for (InterfaceIpAddress ia : pa.ipAddresses()) {
if (ia.ipAddress().equals(source) &&
pa.vlan().equals(vlan)) {
matched = true;
sendTo(eth, pa.connectPoint());
break;
}
}
}
if (matched) {
return;
}
//
// Reply on the port the request was received on
// The request couldn't be resolved.
// Flood the request on all ports except the incoming port.
//
Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth);
sendTo(arpReply, inPort);
flood(eth, inPort);
return;
}
private void replyNdp(Ethernet eth, ConnectPoint inPort) {
......
......@@ -242,8 +242,8 @@ public class ProxyArpManagerTest {
}
/**
* Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the
* IP address is not known.
* Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
* case where the IP address is not known.
* Verifies the method returns false.
*/
@Test
......@@ -255,8 +255,8 @@ public class ProxyArpManagerTest {
}
/**
* Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the
* IP address is known.
* Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
* case where the IP address is known.
* Verifies the method returns true.
*/
@Test
......@@ -403,12 +403,14 @@ public class ProxyArpManagerTest {
@Test
public void testReplyToRequestFromUs() {
replay(hostService); // no further host service expectations
Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
MacAddress ourMac = MacAddress.valueOf(1L);
Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
replay(hostService);
// This is a request from something inside our network (like a BGP
// daemon) to an external host.
Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp);
......