From 4008ac998f43265451281cb6e759cd6184e50bed Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 13 Feb 2017 23:20:04 -0800 Subject: Changing the IP table for an interface is an error if the interface already has an address configured (VPP-601) Change-Id: I311fc264f73dd3b2b3ce9d7d1c33cd0515b36c4a Signed-off-by: Neale Ranns --- src/vnet/ip/ip4_forward.c | 71 ++++++++++++++++++++++++++++------------------ src/vnet/ip/ip6_forward.c | 39 ++++++++++++++++++------- src/vnet/ip/ip6_neighbor.c | 4 +++ src/vnet/ip/lookup.h | 5 ---- 4 files changed, 76 insertions(+), 43 deletions(-) (limited to 'src/vnet/ip') diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c index 66d91ab697d..fe4d6767d0c 100644 --- a/src/vnet/ip/ip4_forward.c +++ b/src/vnet/ip/ip4_forward.c @@ -2781,6 +2781,7 @@ add_del_interface_table (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { vnet_main_t *vnm = vnet_get_main (); + ip_interface_address_t *ia; clib_error_t *error = 0; u32 sw_if_index, table_id; @@ -2802,29 +2803,44 @@ add_del_interface_table (vlib_main_t * vm, goto done; } - { - ip4_main_t *im = &ip4_main; - u32 fib_index; - - fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - table_id); - - // - // FIXME-LATER - // changing an interface's table has consequences for any connecteds - // and adj-fibs already installed. - // - vec_validate (im->fib_index_by_sw_if_index, sw_if_index); - im->fib_index_by_sw_if_index[sw_if_index] = fib_index; - - fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, - table_id); - vec_validate (im->mfib_index_by_sw_if_index, sw_if_index); - im->mfib_index_by_sw_if_index[sw_if_index] = fib_index; - } + /* + * If the interface already has in IP address, then a change int + * VRF is not allowed. The IP address applied must first be removed. + * We do not do that automatically here, since VPP has no knowledge + * of whether thoses subnets are valid in the destination VRF. + */ + /* *INDENT-OFF* */ + foreach_ip_interface_address (&ip4_main.lookup_main, + ia, sw_if_index, + 1 /* honor unnumbered */, + ({ + ip4_address_t * a; + + a = ip_interface_address_get_address (&ip4_main.lookup_main, ia); + error = clib_error_return (0, "interface %U has address %U", + format_vnet_sw_if_index_name, vnm, + sw_if_index, + format_ip4_address, a); + goto done; + })); + /* *INDENT-ON* */ + +{ + ip4_main_t *im = &ip4_main; + u32 fib_index; + + fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id); + + vec_validate (im->fib_index_by_sw_if_index, sw_if_index); + im->fib_index_by_sw_if_index[sw_if_index] = fib_index; + + fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, table_id); + vec_validate (im->mfib_index_by_sw_if_index, sw_if_index); + im->mfib_index_by_sw_if_index[sw_if_index] = fib_index; +} done: - return error; +return error; } /*? @@ -2835,13 +2851,12 @@ done: * an IP Address is assigned to an interface in the table (which adds a route * automatically). * - * @note IP addresses added after setting the interface IP table end up in - * the indicated FIB table. If the IP address is added prior to adding the - * interface to the FIB table, it will NOT be part of the FIB table. Predictable - * but potentially counter-intuitive results occur if you provision interface - * addresses in multiple FIBs. Upon RX, packets will be processed in the last - * IP table ID provisioned. It might be marginally useful to evade source RPF - * drops to put an interface address into multiple FIBs. + * @note IP addresses added after setting the interface IP table are added to + * the indicated FIB table. If an IP address is added prior to changing the + * table then this is an error. The control plane must remove these addresses + * first and then change the table. VPP will not automatically move the + * addresses from the old to the new table as it does not know the validity + * of such a change. * * @cliexpar * Example of how to add an interface to an IPv4 FIB table (where 2 is the table-id): diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c index 5dd22b99ca2..6f77c6dd69d 100644 --- a/src/vnet/ip/ip6_forward.c +++ b/src/vnet/ip/ip6_forward.c @@ -415,9 +415,6 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable) return; } - if (sw_if_index != 0) - ip6_mfib_interface_enable_disable (sw_if_index, is_enable); - vnet_feature_enable_disable ("ip6-unicast", "ip6-lookup", sw_if_index, is_enable, 0, 0); @@ -2972,6 +2969,7 @@ add_del_ip6_interface_table (vlib_main_t * vm, vlib_cli_command_t * cmd) { vnet_main_t *vnm = vnet_get_main (); + ip_interface_address_t *ia; clib_error_t *error = 0; u32 sw_if_index, table_id; @@ -2993,6 +2991,28 @@ add_del_ip6_interface_table (vlib_main_t * vm, goto done; } + /* + * If the interface already has in IP address, then a change int + * VRF is not allowed. The IP address applied must first be removed. + * We do not do that automatically here, since VPP has no knowledge + * of whether thoses subnets are valid in the destination VRF. + */ + /* *INDENT-OFF* */ + foreach_ip_interface_address (&ip6_main.lookup_main, + ia, sw_if_index, + 1 /* honor unnumbered */, + ({ + ip4_address_t * a; + + a = ip_interface_address_get_address (&ip6_main.lookup_main, ia); + error = clib_error_return (0, "interface %U has address %U", + format_vnet_sw_if_index_name, vnm, + sw_if_index, + format_ip6_address, a); + goto done; + })); + /* *INDENT-ON* */ + { u32 fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, table_id); @@ -3020,13 +3040,12 @@ done: * an IP Address is assigned to an interface in the table (which adds a route * automatically). * - * @note IP addresses added after setting the interface IP table end up in - * the indicated FIB table. If the IP address is added prior to adding the - * interface to the FIB table, it will NOT be part of the FIB table. Predictable - * but potentially counter-intuitive results occur if you provision interface - * addresses in multiple FIBs. Upon RX, packets will be processed in the last - * IP table ID provisioned. It might be marginally useful to evade source RPF - * drops to put an interface address into multiple FIBs. + * @note IP addresses added after setting the interface IP table are added to + * the indicated FIB table. If an IP address is added prior to changing the + * table then this is an error. The control plane must remove these addresses + * first and then change the table. VPP will not automatically move the + * addresses from the old to the new table as it does not know the validity + * of such a change. * * @cliexpar * Example of how to add an interface to an IPv6 FIB table (where 2 is the table-id): diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 6b53137ffb2..91ff224c68e 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -24,6 +24,7 @@ #include #include #include +#include /** * @file @@ -3283,6 +3284,7 @@ disable_ip6_interface (vlib_main_t * vm, u32 sw_if_index) ip6_neighbor_sw_interface_add_del (vnm, sw_if_index, 0 /* is_add */ ); + ip6_mfib_interface_enable_disable (sw_if_index, 0); } } return error; @@ -3369,6 +3371,8 @@ enable_ip6_interface (vlib_main_t * vm, u32 sw_if_index) link_local_address.as_u8[8] &= 0xfd; } + ip6_mfib_interface_enable_disable (sw_if_index, 1); + /* essentially "enables" ipv6 on this interface */ error = ip6_add_del_interface_address (vm, sw_if_index, &link_local_address, diff --git a/src/vnet/ip/lookup.h b/src/vnet/ip/lookup.h index 27c70943991..48360b5b41f 100644 --- a/src/vnet/ip/lookup.h +++ b/src/vnet/ip/lookup.h @@ -389,11 +389,6 @@ do { \ CLIB_PREFETCH (_adj, sizeof (_adj[0]), type); \ } while (0) -/* Create new block of given number of contiguous adjacencies. */ -ip_adjacency_t *ip_add_adjacency (ip_lookup_main_t * lm, - ip_adjacency_t * adj, - u32 n_adj, u32 * adj_index_result); - clib_error_t *ip_interface_address_add_del (ip_lookup_main_t * lm, u32 sw_if_index, void *address, -- cgit 1.2.3-korg