#include <vnet/ethernet/ethernet.h> /* for ethernet_header_t */
#include <vnet/srp/srp.h> /* for srp_hw_interface_class */
#include <vppinfra/cache.h>
+#include <vnet/fib/fib_urpf_list.h> /* for FIB uRPF check */
#include <vnet/fib/ip6_fib.h>
#include <vnet/mfib/ip6_mfib.h>
#include <vnet/dpo/load_balance.h>
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);
/* get first interface address */
ip6_address_t *
-ip6_interface_first_address (ip6_main_t * im,
- u32 sw_if_index,
- ip_interface_address_t ** result_ia)
+ip6_interface_first_address (ip6_main_t * im, u32 sw_if_index)
{
ip_lookup_main_t *lm = &im->lookup_main;
ip_interface_address_t *ia = 0;
break;
}));
/* *INDENT-ON* */
- if (result_ia)
- *result_ia = result ? ia : 0;
return result;
}
return (next_proto);
}
+/**
+ * @brief returns number of links on which src is reachable.
+ */
+always_inline int
+ip6_urpf_loose_check (ip6_main_t * im, vlib_buffer_t * b, ip6_header_t * i)
+{
+ const load_balance_t *lb0;
+ index_t lbi;
+
+ lbi = ip6_fib_table_fwding_lookup_with_if_index (im,
+ vnet_buffer
+ (b)->sw_if_index[VLIB_RX],
+ &i->src_address);
+
+ lb0 = load_balance_get (lbi);
+
+ return (fib_urpf_check_size (lb0->lb_urpf));
+}
+
static uword
ip6_local (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
{
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;
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);
* 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):
vec_validate (lm->classify_table_index_by_sw_if_index, sw_if_index);
lm->classify_table_index_by_sw_if_index[sw_if_index] = table_index;
- if_addr = ip6_interface_first_address (ipm, sw_if_index, NULL);
+ if_addr = ip6_interface_first_address (ipm, sw_if_index);
if (NULL != if_addr)
{