Jonathan Hart
Committed by Gerrit Code Review

ProxyArp: Reply directly when we know an external target host

Change-Id: I38773dcdcae05506c678c2006d1f63306af6b383
...@@ -146,9 +146,9 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -146,9 +146,9 @@ public class ProxyArpManager implements ProxyArpService {
146 146
147 VlanId vlan = VlanId.vlanId(eth.getVlanID()); 147 VlanId vlan = VlanId.vlanId(eth.getVlanID());
148 148
149 + if (isOutsidePort(inPort)) {
149 // If the request came from outside the network, only reply if it was 150 // If the request came from outside the network, only reply if it was
150 // for one of our external addresses. 151 // for one of our external addresses.
151 - if (isOutsidePort(inPort)) {
152 Set<PortAddresses> addressSet = 152 Set<PortAddresses> addressSet =
153 hostService.getAddressBindingsForPort(inPort); 153 hostService.getAddressBindingsForPort(inPort);
154 154
...@@ -162,10 +162,33 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -162,10 +162,33 @@ public class ProxyArpManager implements ProxyArpService {
162 } 162 }
163 } 163 }
164 return; 164 return;
165 - } else { 165 + }
166 +
167 + // See if we have the target host in the host store
168 +
169 + Set<Host> hosts = hostService.getHostsByIp(targetAddress);
170 +
171 + Host dst = null;
172 + Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
173 + VlanId.vlanId(eth.getVlanID())));
174 +
175 + for (Host host : hosts) {
176 + if (host.vlan().equals(vlan)) {
177 + dst = host;
178 + break;
179 + }
180 + }
181 +
182 + if (src != null && dst != null) {
183 + // We know the target host so we can respond
184 + Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth);
185 + sendTo(arpReply, inPort);
186 + return;
187 + }
188 +
166 // If the source address matches one of our external addresses 189 // If the source address matches one of our external addresses
167 // it could be a request from an internal host to an external 190 // it could be a request from an internal host to an external
168 - // address. Forward it over to the correct ports. 191 + // address. Forward it over to the correct port.
169 Ip4Address source = 192 Ip4Address source =
170 Ip4Address.valueOf(arp.getSenderProtocolAddress()); 193 Ip4Address.valueOf(arp.getSenderProtocolAddress());
171 Set<PortAddresses> sourceAddresses = findPortsInSubnet(source); 194 Set<PortAddresses> sourceAddresses = findPortsInSubnet(source);
...@@ -184,39 +207,15 @@ public class ProxyArpManager implements ProxyArpService { ...@@ -184,39 +207,15 @@ public class ProxyArpManager implements ProxyArpService {
184 if (matched) { 207 if (matched) {
185 return; 208 return;
186 } 209 }
187 - }
188 -
189 - // Continue with normal proxy ARP case
190 210
191 - Set<Host> hosts = hostService.getHostsByIp(targetAddress);
192 -
193 - Host dst = null;
194 - Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
195 - VlanId.vlanId(eth.getVlanID())));
196 -
197 - for (Host host : hosts) {
198 - if (host.vlan().equals(vlan)) {
199 - dst = host;
200 - break;
201 - }
202 - }
203 -
204 - if (src == null || dst == null) {
205 // 211 //
206 // The request couldn't be resolved. 212 // The request couldn't be resolved.
207 - // Flood the request on all ports except the incoming ports. 213 + // Flood the request on all ports except the incoming port.
208 // 214 //
209 flood(eth, inPort); 215 flood(eth, inPort);
210 return; 216 return;
211 } 217 }
212 218
213 - //
214 - // Reply on the port the request was received on
215 - //
216 - Ethernet arpReply = buildArpReply(targetAddress, dst.mac(), eth);
217 - sendTo(arpReply, inPort);
218 - }
219 -
220 private void replyNdp(Ethernet eth, ConnectPoint inPort) { 219 private void replyNdp(Ethernet eth, ConnectPoint inPort) {
221 220
222 IPv6 ipv6 = (IPv6) eth.getPayload(); 221 IPv6 ipv6 = (IPv6) eth.getPayload();
......
...@@ -242,8 +242,8 @@ public class ProxyArpManagerTest { ...@@ -242,8 +242,8 @@ public class ProxyArpManagerTest {
242 } 242 }
243 243
244 /** 244 /**
245 - * Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the 245 + * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
246 - * IP address is not known. 246 + * case where the IP address is not known.
247 * Verifies the method returns false. 247 * Verifies the method returns false.
248 */ 248 */
249 @Test 249 @Test
...@@ -255,8 +255,8 @@ public class ProxyArpManagerTest { ...@@ -255,8 +255,8 @@ public class ProxyArpManagerTest {
255 } 255 }
256 256
257 /** 257 /**
258 - * Tests {@link ProxyArpManager#isKnown(Ip4Address)} in the case where the 258 + * Tests {@link ProxyArpManager#isKnown(org.onlab.packet.IpAddress)} in the
259 - * IP address is known. 259 + * case where the IP address is known.
260 * Verifies the method returns true. 260 * Verifies the method returns true.
261 */ 261 */
262 @Test 262 @Test
...@@ -403,12 +403,14 @@ public class ProxyArpManagerTest { ...@@ -403,12 +403,14 @@ public class ProxyArpManagerTest {
403 403
404 @Test 404 @Test
405 public void testReplyToRequestFromUs() { 405 public void testReplyToRequestFromUs() {
406 - replay(hostService); // no further host service expectations
407 -
408 Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1"); 406 Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
409 MacAddress ourMac = MacAddress.valueOf(1L); 407 MacAddress ourMac = MacAddress.valueOf(1L);
410 Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100"); 408 Ip4Address theirIp = Ip4Address.valueOf("10.0.1.100");
411 409
410 + expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
411 + expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
412 + replay(hostService);
413 +
412 // This is a request from something inside our network (like a BGP 414 // This is a request from something inside our network (like a BGP
413 // daemon) to an external host. 415 // daemon) to an external host.
414 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp); 416 Ethernet arpRequest = buildArp(ARP.OP_REQUEST, ourMac, null, ourIp, theirIp);
......