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>
This commit is contained in:
Matthew G Smith
2019-07-17 10:01:17 -05:00
committed by Neale Ranns
parent 9fd996275c
commit 88d29a9206
2 changed files with 127 additions and 7 deletions

View File

@ -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) =

View File

@ -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 """