summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-08-15 05:33:11 -0700
committerFlorin Coras <florin.coras@gmail.com>2017-08-15 16:37:21 +0000
commit24b170aac55d16cb3ff934d2f3d7983dc11cbe12 (patch)
treefc5636a0f2f933b6f21c3c07d7ef3826db160fc3
parente9ab1c0b4a8d9ae930fbc5522c8d56a0a7a49608 (diff)
Support proxy ARP on mirrored TAP interfaces
When VPP has an interface whose address is also applied to a TAP interface on the host, then VPP's TAP interface will be unnumbered to the 'real' interface and do proxy ARP from the host. the curious aspect of this setup is that ARP requests from the host will come from the VPP's own address. Change-Id: Ia238790e1034ba3cd3facdab29387b65a31525f2 Signed-off-by: Neale Ranns <nranns@cisco.com>
-rw-r--r--src/vnet/ethernet/arp.c20
-rw-r--r--test/test_neighbor.py64
-rw-r--r--test/vpp_interface.py6
3 files changed, 86 insertions, 4 deletions
diff --git a/src/vnet/ethernet/arp.c b/src/vnet/ethernet/arp.c
index c22be3fc809..c84ff47bc00 100644
--- a/src/vnet/ethernet/arp.c
+++ b/src/vnet/ethernet/arp.c
@@ -1004,7 +1004,17 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
if (FIB_ENTRY_FLAG_LOCAL & src_flags)
{
error0 = ETHERNET_ARP_ERROR_l3_src_address_is_local;
- goto drop2;
+ /*
+ * When VPP has an interface whose address is also
+ * applied to a TAP interface on the host, then VPP's
+ * TAP interface will be unnumbered to the 'real'
+ * interface and do proxy ARP from the host.
+ * The curious aspect of this setup is that ARP requests
+ * from the host will come from the VPP's own address.
+ * So don't drop immediately here, instead go see if this
+ * is a proxy ARP case.
+ */
+ goto drop1;
}
/* A Source must also be local to subnet of matching
* interface address. */
@@ -1151,9 +1161,11 @@ arp_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
}
}
- /* We are going to reply to this request, so learn the sender */
- error0 = arp_learn (vnm, am, sw_if_index0,
- &arp0->ip4_over_ethernet[1]);
+ /* We are going to reply to this request, so, in the absence of
+ errors, learn the sender */
+ if (!error0)
+ error0 = arp_learn (vnm, am, sw_if_index0,
+ &arp0->ip4_over_ethernet[1]);
vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
n_left_to_next, pi0, next0);
diff --git a/test/test_neighbor.py b/test/test_neighbor.py
index b4a6878d759..1c7cc2678ff 100644
--- a/test/test_neighbor.py
+++ b/test/test_neighbor.py
@@ -657,6 +657,70 @@ class ARPTestCase(VppTestCase):
self.pg2.admin_down()
self.pg1.admin_down()
+ def test_proxy_mirror_arp(self):
+ """ Interface Mirror Proxy ARP """
+
+ #
+ # When VPP has an interface whose address is also applied to a TAP
+ # interface on the host, then VPP's TAP interface will be unnumbered
+ # to the 'real' interface and do proxy ARP from the host.
+ # the curious aspect of this setup is that ARP requests from the host
+ # will come from the VPP's own address.
+ #
+ self.pg0.generate_remote_hosts(2)
+
+ arp_req_from_me = (Ether(src=self.pg2.remote_mac,
+ dst="ff:ff:ff:ff:ff:ff") /
+ ARP(op="who-has",
+ hwsrc=self.pg2.remote_mac,
+ pdst=self.pg0.remote_hosts[1].ip4,
+ psrc=self.pg0.local_ip4))
+
+ #
+ # Configure Proxy ARP for the subnet on PG0addresses on pg0
+ #
+ self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
+ self.pg0._local_ip4n_bcast)
+
+ # Make pg2 un-numbered to pg0
+ #
+ self.pg2.set_unnumbered(self.pg0.sw_if_index)
+
+ #
+ # Enable pg2 for proxy ARP
+ #
+ self.pg2.set_proxy_arp()
+
+ #
+ # Send the ARP request with an originating address that
+ # is VPP's own address
+ #
+ self.pg2.add_stream(arp_req_from_me)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+
+ rx = self.pg2.get_capture(1)
+ self.verify_arp_resp(rx[0],
+ self.pg2.local_mac,
+ self.pg2.remote_mac,
+ self.pg0.remote_hosts[1].ip4,
+ self.pg0.local_ip4)
+
+ #
+ # validate we have not learned an ARP entry as a result of this
+ #
+ self.assertFalse(find_nbr(self,
+ self.pg2.sw_if_index,
+ self.pg0.local_ip4))
+
+ #
+ # cleanup
+ #
+ self.pg2.set_proxy_arp(0)
+ self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
+ self.pg0._local_ip4n_bcast,
+ is_add=0)
+
def test_proxy_arp(self):
""" Proxy ARP """
diff --git a/test/vpp_interface.py b/test/vpp_interface.py
index 662015eacf7..b8505ce39d7 100644
--- a/test/vpp_interface.py
+++ b/test/vpp_interface.py
@@ -163,6 +163,12 @@ class VppInterface(object):
self._local_ip4 = "172.16.%u.1" % self.sw_if_index
self._local_ip4n = socket.inet_pton(socket.AF_INET, self.local_ip4)
+ self._local_ip4_subnet = "172.16.%u.0" % self.sw_if_index
+ self._local_ip4n_subnet = socket.inet_pton(socket.AF_INET,
+ self._local_ip4_subnet)
+ self._local_ip4_bcast = "172.16.%u.255" % self.sw_if_index
+ self._local_ip4n_bcast = socket.inet_pton(socket.AF_INET,
+ self._local_ip4_bcast)
self.local_ip4_prefix_len = 24
self.has_ip4_config = False
self.ip4_table_id = 0