summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew G Smith <mgsmith@netgate.com>2019-07-17 10:01:17 -0500
committerNeale Ranns <nranns@cisco.com>2019-07-19 07:35:55 +0000
commit88d29a9206bbaa70f7772fa157ec6b1ccaf567a8 (patch)
tree3d601d4501d7e134cdb0859c2b8e1b9ec29271b1
parent9fd996275c745faec2843cf3a8b1d15d6f8c9dab (diff)
ip: admin change affects intf IPv4 addr routes
Type: feature When admin status is changed on an interface, add or delete the routes for the IPv4 addresses configured on that interface. This is already being done for IPv6 interface addresses. Change-Id: Ib1e7dc49c499921dd287e075640243520ffa5589 Signed-off-by: Matthew Smith <mgsmith@netgate.com>
-rw-r--r--src/vnet/ip/ip4_forward.c60
-rw-r--r--test/test_ip4.py74
2 files changed, 127 insertions, 7 deletions
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index a05428c047d..03b0f3e740a 100644
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -297,6 +297,7 @@ ip4_interface_first_address (ip4_main_t * im, u32 sw_if_index,
*result_ia = result ? ia : 0;
return result;
}
+#endif
static void
ip4_add_subnet_bcast_route (u32 fib_index,
@@ -485,6 +486,7 @@ ip4_del_interface_routes (ip4_main_t * im,
fib_table_entry_delete (fib_index, &pfx, FIB_SOURCE_INTERFACE);
}
+#ifndef CLIB_MARCH_VARIANT
void
ip4_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
{
@@ -604,13 +606,18 @@ ip4_add_del_interface_address_internal (vlib_main_t * vm,
ip4_sw_interface_enable_disable (sw_if_index, !is_del);
- if (is_del)
- ip4_del_interface_routes (im, ip4_af.fib_index, address, address_length);
- else
- ip4_add_interface_routes (sw_if_index,
- im, ip4_af.fib_index,
- pool_elt_at_index
- (lm->if_address_pool, if_address_index));
+ /* intf addr routes are added/deleted on admin up/down */
+ if (vnet_sw_interface_is_admin_up (vnm, sw_if_index))
+ {
+ if (is_del)
+ ip4_del_interface_routes (im, ip4_af.fib_index, address,
+ address_length);
+ else
+ ip4_add_interface_routes (sw_if_index,
+ im, ip4_af.fib_index,
+ pool_elt_at_index
+ (lm->if_address_pool, if_address_index));
+ }
/* If pool did not grow/shrink: add duplicate address. */
if (elts_before != pool_elts (lm->if_address_pool))
@@ -676,6 +683,45 @@ ip4_directed_broadcast (u32 sw_if_index, u8 enable)
}
#endif
+static clib_error_t *
+ip4_sw_interface_admin_up_down (vnet_main_t * vnm, u32 sw_if_index, u32 flags)
+{
+ ip4_main_t *im = &ip4_main;
+ ip_interface_address_t *ia;
+ ip4_address_t *a;
+ u32 is_admin_up, fib_index;
+
+ /* Fill in lookup tables with default table (0). */
+ vec_validate (im->fib_index_by_sw_if_index, sw_if_index);
+
+ vec_validate_init_empty (im->
+ lookup_main.if_address_pool_index_by_sw_if_index,
+ sw_if_index, ~0);
+
+ is_admin_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
+
+ fib_index = vec_elt (im->fib_index_by_sw_if_index, sw_if_index);
+
+ /* *INDENT-OFF* */
+ foreach_ip_interface_address (&im->lookup_main, ia, sw_if_index,
+ 0 /* honor unnumbered */,
+ ({
+ a = ip_interface_address_get_address (&im->lookup_main, ia);
+ if (is_admin_up)
+ ip4_add_interface_routes (sw_if_index,
+ im, fib_index,
+ ia);
+ else
+ ip4_del_interface_routes (im, fib_index,
+ a, ia->address_length);
+ }));
+ /* *INDENT-ON* */
+
+ return 0;
+}
+
+VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION (ip4_sw_interface_admin_up_down);
+
/* Built-in ip4 unicast rx feature path definition */
/* *INDENT-OFF* */
VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
diff --git a/test/test_ip4.py b/test/test_ip4.py
index 933958911fe..a6920f8dba5 100644
--- a/test/test_ip4.py
+++ b/test/test_ip4.py
@@ -210,6 +210,80 @@ class TestIPv4(VppTestCase):
self.verify_capture(i, pkts)
+class TestIPV4IfAddrRoute(VppTestCase):
+ """ IPv4 Interface Addr Route Test Case """
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestIPV4IfAddrRoute, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestIPV4IfAddrRoute, cls).tearDownClass()
+
+ def setUp(self):
+ super(TestIPV4IfAddrRoute, self).setUp()
+
+ # create 1 pg interface
+ self.create_pg_interfaces(range(1))
+
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.config_ip4()
+ i.resolve_arp()
+
+ def tearDown(self):
+ super(TestIPV4IfAddrRoute, self).tearDown()
+ for i in self.pg_interfaces:
+ i.unconfig_ip4()
+ i.admin_down()
+
+ def test_ipv4_ifaddr_route(self):
+ """ IPv4 Interface Address Route test
+
+ Test scenario:
+
+ - Create loopback
+ - Configure IPv4 address on loopback
+ - Verify that address is not in the FIB
+ - Bring loopback up
+ - Verify that address is in the FIB now
+ - Bring loopback down
+ - Verify that address is not in the FIB anymore
+ - Bring loopback up
+ - Configure IPv4 address on loopback
+ - Verify that address is in the FIB now
+ """
+
+ # create a loopback and configure IPv4
+ loopbacks = self.create_loopback_interfaces(1)
+ lo_if = self.lo_interfaces[0]
+
+ lo_if.local_ip4_prefix_len = 32
+ lo_if.config_ip4()
+
+ # The intf was down when addr was added -> entry not in FIB
+ fib4_dump = self.vapi.ip_route_dump(0)
+ self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
+
+ # When intf is brought up, entry is added
+ lo_if.admin_up()
+ fib4_dump = self.vapi.ip_route_dump(0)
+ self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
+
+ # When intf is brought down, entry is removed
+ lo_if.admin_down()
+ fib4_dump = self.vapi.ip_route_dump(0)
+ self.assertFalse(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
+
+ # Remove addr, bring up interface, re-add -> entry in FIB
+ lo_if.unconfig_ip4()
+ lo_if.admin_up()
+ lo_if.config_ip4()
+ fib4_dump = self.vapi.ip_route_dump(0)
+ self.assertTrue(lo_if.is_ip4_entry_in_fib_dump(fib4_dump))
+
+
class TestICMPEcho(VppTestCase):
""" ICMP Echo Test Case """