ip-neighbor: Grat ARPs from different subnet are dropped 35/29035/3
authorNeale Ranns <nranns@cisco.com>
Wed, 23 Sep 2020 11:25:21 +0000 (11:25 +0000)
committerOle Tr�an <otroan@employees.org>
Thu, 8 Oct 2020 09:04:05 +0000 (09:04 +0000)
Type: test

Signed-off-by: Neale Ranns <nranns@cisco.com>
Change-Id: Id07e8981a903f11f50fb494a93d01815382025e4

src/vnet/arp/arp.c
test/test_neighbor.py
test/vpp_neighbor.py

index 14a1ae9..6a32229 100644 (file)
@@ -543,6 +543,8 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
          dst_fei = ip4_fib_table_lookup (ip4_fib_get (fib_index0),
                                          &arp0->ip4_over_ethernet[1].ip4,
                                          32);
+         conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
+
          switch (arp_dst_fib_check (dst_fei, &dst_flags))
            {
            case ARP_DST_FIB_ADJ:
@@ -554,10 +556,12 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
               * from spamming us with gratuitous ARPS that might otherwise
               * blow our ARP cache
               */
-             if (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
-                 arp0->ip4_over_ethernet[1].ip4.as_u32)
-               error0 =
-                 arp_learn (sw_if_index0, &arp0->ip4_over_ethernet[0]);
+             if (conn_sw_if_index0 != sw_if_index0)
+               error0 = ETHERNET_ARP_ERROR_l3_dst_address_not_local;
+             else if (arp0->ip4_over_ethernet[0].ip4.as_u32 ==
+                      arp0->ip4_over_ethernet[1].ip4.as_u32)
+               error0 = arp_learn (sw_if_index0,
+                                   &arp0->ip4_over_ethernet[0]);
              goto drop;
            case ARP_DST_FIB_CONN:
              /* destination is connected, continue to process */
@@ -615,7 +619,6 @@ arp_reply (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
            }
 
          /* Honor unnumbered interface, if any */
-         conn_sw_if_index0 = fib_entry_get_resolving_interface (dst_fei);
          if (sw_if_index0 != conn_sw_if_index0 ||
              sw_if_index0 != fib_entry_get_resolving_interface (src_fei))
            {
index 1045f4b..dfefb15 100644 (file)
@@ -1435,6 +1435,7 @@ class ARPTestCase(VppTestCase):
         # Generate some hosts on the LAN
         #
         self.pg1.generate_remote_hosts(4)
+        self.pg2.generate_remote_hosts(4)
 
         #
         # And an ARP entry
@@ -1526,6 +1527,36 @@ class ARPTestCase(VppTestCase):
                                   self.pg1.sw_if_index,
                                   self.pg1.remote_hosts[2].ip4))
 
+        #
+        # IP address in different subnets are not learnt
+        #
+        self.pg2.configure_ipv4_neighbors()
+
+        for op in ["is-at", "who-has"]:
+            p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
+                         src=self.pg2.remote_hosts[1].mac) /
+                   ARP(op=op,
+                       hwdst=self.pg2.local_mac,
+                       hwsrc=self.pg2.remote_hosts[1].mac,
+                       pdst=self.pg2.remote_hosts[1].ip4,
+                       psrc=self.pg2.remote_hosts[1].ip4)),
+                  (Ether(dst="ff:ff:ff:ff:ff:ff",
+                         src=self.pg2.remote_hosts[1].mac) /
+                   ARP(op=op,
+                       hwdst="ff:ff:ff:ff:ff:ff",
+                       hwsrc=self.pg2.remote_hosts[1].mac,
+                       pdst=self.pg2.remote_hosts[1].ip4,
+                       psrc=self.pg2.remote_hosts[1].ip4))]
+
+            self.send_and_assert_no_replies(self.pg1, p1)
+            self.assertFalse(find_nbr(self,
+                                      self.pg1.sw_if_index,
+                                      self.pg2.remote_hosts[1].ip4))
+
+        # they are all dropped because the subnet's don't match
+        self.assertEqual(4, self.statistics.get_err_counter(
+            "/err/arp-reply/IP4 destination address not local to subnet"))
+
     def test_arp_incomplete(self):
         """ Incomplete Entries """
 
index ffe87d9..6f54261 100644 (file)
@@ -20,7 +20,8 @@ def find_nbr(test, sw_if_index, nbr_addr, is_static=0, mac=None):
                                       af=ip_addr.vapi_af)
 
     for n in nbrs:
-        if ip_addr == n.neighbor.ip_address and \
+        if sw_if_index == n.neighbor.sw_if_index and \
+           ip_addr == n.neighbor.ip_address and \
            is_static == (n.neighbor.flags & e.IP_API_NEIGHBOR_FLAG_STATIC):
             if mac:
                 if mac == str(n.neighbor.mac_address):