aboutsummaryrefslogtreecommitdiffstats
path: root/src/vnet/ip
diff options
context:
space:
mode:
authorNeale Ranns <nranns@cisco.com>2017-09-10 04:39:11 -0700
committerDamjan Marion <dmarion.lists@gmail.com>2017-09-11 10:14:36 +0000
commit1500254bee11355bbd69cc1dd9705be4f002f2bd (patch)
treec403642105f399baccb3a727020232b5732fe8f7 /src/vnet/ip
parenta7191840beeb2c3a0f2598707ed1051a9f23c45f (diff)
FIB table add/delete API
part 2; - this adds the code to create an IP and MPLS table via the API. - but the enforcement that the table must be created before it is used is still missing, this is so that CSIT can pass. Change-Id: Id124d884ade6cb7da947225200e3bb193454c555 Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/ip')
-rw-r--r--src/vnet/ip/ip.h7
-rw-r--r--src/vnet/ip/ip4.h13
-rwxr-xr-xsrc/vnet/ip/ip4_forward.c101
-rw-r--r--src/vnet/ip/ip4_source_and_port_range_check.c11
-rw-r--r--src/vnet/ip/ip6.h13
-rw-r--r--src/vnet/ip/ip6_forward.c103
-rw-r--r--src/vnet/ip/ip6_neighbor.c108
-rw-r--r--src/vnet/ip/ip_api.c122
-rwxr-xr-xsrc/vnet/ip/lookup.c225
9 files changed, 453 insertions, 250 deletions
diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h
index 70b4ccd8..7aae73ff 100644
--- a/src/vnet/ip/ip.h
+++ b/src/vnet/ip/ip.h
@@ -184,6 +184,13 @@ void ip_del_all_interface_addresses (vlib_main_t * vm, u32 sw_if_index);
extern vlib_node_registration_t ip4_inacl_node;
extern vlib_node_registration_t ip6_inacl_node;
+void ip_table_create (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+void ip_table_delete (fib_protocol_t fproto, uint32_t table_id, u8 is_api);
+
+int ip_table_bind (fib_protocol_t fproto,
+ uint32_t sw_if_index, uint32_t table_id, u8 is_api);
+
#endif /* included_ip_main_h */
/*
diff --git a/src/vnet/ip/ip4.h b/src/vnet/ip/ip4.h
index 8f9a8e27..decb840b 100644
--- a/src/vnet/ip/ip4.h
+++ b/src/vnet/ip/ip4.h
@@ -72,6 +72,16 @@ typedef struct
uword function_opaque;
} ip4_add_del_interface_address_callback_t;
+typedef void (ip4_table_bind_function_t)
+ (struct ip4_main_t * im,
+ uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+ ip4_table_bind_function_t *function;
+ uword function_opaque;
+} ip4_table_bind_callback_t;
+
/**
* @brief IPv4 main type.
*
@@ -117,6 +127,9 @@ typedef struct ip4_main_t
ip4_add_del_interface_address_callback_t
* add_del_interface_address_callbacks;
+ /** Functions to call when interface to table biding changes. */
+ ip4_table_bind_callback_t *table_bind_callbacks;
+
/** Template used to generate IP4 ARP packets. */
vlib_packet_template_t ip4_arp_request_packet_template;
diff --git a/src/vnet/ip/ip4_forward.c b/src/vnet/ip/ip4_forward.c
index 2d48e8a9..ec4287bb 100755
--- a/src/vnet/ip/ip4_forward.c
+++ b/src/vnet/ip/ip4_forward.c
@@ -1198,8 +1198,10 @@ ip4_lookup_init (vlib_main_t * vm)
ip_lookup_init (&im->lookup_main, /* is_ip6 */ 0);
/* Create FIB with index 0 and table id of 0. */
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
- mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+ FIB_SOURCE_DEFAULT_ROUTE);
+ mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, 0,
+ MFIB_SOURCE_DEFAULT_ROUTE);
{
pg_node_t *pn;
@@ -2794,101 +2796,6 @@ VLIB_REGISTER_NODE (ip4_midchain_node) = {
VLIB_NODE_FUNCTION_MULTIARCH (ip4_midchain_node, ip4_midchain);
/* *INDENT-ON */
-static clib_error_t *
-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;
-
- sw_if_index = ~0;
-
- if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
- {
- error = clib_error_return (0, "unknown interface `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- if (unformat (input, "%d", &table_id))
- ;
- else
- {
- error = clib_error_return (0, "expected table id `%U'",
- format_unformat_error, input);
- 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 (&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;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv4 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * 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 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):
- * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
-{
- .path = "set interface ip table",
- .function = add_del_interface_table,
- .short_help = "set interface ip table <interface> <table-id>",
-};
-/* *INDENT-ON* */
-
int
ip4_lookup_validate (ip4_address_t * a, u32 fib_index0)
{
diff --git a/src/vnet/ip/ip4_source_and_port_range_check.c b/src/vnet/ip/ip4_source_and_port_range_check.c
index ae836a11..9aa880ae 100644
--- a/src/vnet/ip/ip4_source_and_port_range_check.c
+++ b/src/vnet/ip/ip4_source_and_port_range_check.c
@@ -1126,6 +1126,14 @@ ip6_source_and_port_range_check_add_del (ip6_address_t * address,
u16 * low_ports,
u16 * high_ports, int is_add)
{
+ uint32_t fib_index;
+
+ fib_index = fib_table_find (FIB_PROTOCOL_IP4, vrf_id);
+
+ ASSERT (~0 != fib_index);
+
+ fib_table_unlock (fib_index, FIB_PROTOCOL_IP4, FIB_SOURCE_CLASSIFY);
+
return 0;
}
@@ -1138,7 +1146,8 @@ ip4_source_and_port_range_check_add_del (ip4_address_t * address,
{
u32 fib_index;
- fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id);
+ fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4, vrf_id,
+ FIB_SOURCE_CLASSIFY);
if (is_add == 0)
{
diff --git a/src/vnet/ip/ip6.h b/src/vnet/ip/ip6.h
index fa922725..8aef53a9 100644
--- a/src/vnet/ip/ip6.h
+++ b/src/vnet/ip/ip6.h
@@ -103,6 +103,16 @@ typedef struct
uword function_opaque;
} ip6_add_del_interface_address_callback_t;
+typedef void (ip6_table_bind_function_t)
+ (struct ip6_main_t * im,
+ uword opaque, u32 sw_if_index, u32 new_fib_index, u32 old_fib_index);
+
+typedef struct
+{
+ ip6_table_bind_function_t *function;
+ uword function_opaque;
+} ip6_table_bind_callback_t;
+
/**
* Enumeration of the FIB table instance types
*/
@@ -183,6 +193,9 @@ typedef struct ip6_main_t
ip6_add_del_interface_address_callback_t
* add_del_interface_address_callbacks;
+ /** Functions to call when interface to table biding changes. */
+ ip6_table_bind_callback_t *table_bind_callbacks;
+
/* Template used to generate IP6 neighbor solicitation packets. */
vlib_packet_template_t discover_neighbor_packet_template;
diff --git a/src/vnet/ip/ip6_forward.c b/src/vnet/ip/ip6_forward.c
index 5832bd0b..1002f6b6 100644
--- a/src/vnet/ip/ip6_forward.c
+++ b/src/vnet/ip/ip6_forward.c
@@ -2999,8 +2999,10 @@ ip6_lookup_init (vlib_main_t * vm)
im->lookup_table_nbuckets, im->lookup_table_size);
/* Create FIB with index 0 and table id of 0. */
- fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
- mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0);
+ fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+ FIB_SOURCE_DEFAULT_ROUTE);
+ mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, 0,
+ MFIB_SOURCE_DEFAULT_ROUTE);
{
pg_node_t *pn;
@@ -3045,103 +3047,6 @@ ip6_lookup_init (vlib_main_t * vm)
VLIB_INIT_FUNCTION (ip6_lookup_init);
-static clib_error_t *
-add_del_ip6_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;
-
- sw_if_index = ~0;
-
- if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
- {
- error = clib_error_return (0, "unknown interface `%U'",
- format_unformat_error, input);
- goto done;
- }
-
- if (unformat (input, "%d", &table_id))
- ;
- else
- {
- error = clib_error_return (0, "expected table id `%U'",
- format_unformat_error, input);
- 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);
-
- vec_validate (ip6_main.fib_index_by_sw_if_index, sw_if_index);
- ip6_main.fib_index_by_sw_if_index[sw_if_index] = fib_index;
-
- fib_index = mfib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- table_id);
-
- vec_validate (ip6_main.mfib_index_by_sw_if_index, sw_if_index);
- ip6_main.mfib_index_by_sw_if_index[sw_if_index] = fib_index;
- }
-
-
-done:
- return error;
-}
-
-/*?
- * Place the indicated interface into the supplied IPv6 FIB table (also known
- * as a VRF). If the FIB table does not exist, this command creates it. To
- * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
- * FIB table will only be displayed if a route has been added to the table, or
- * 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 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):
- * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
- ?*/
-/* *INDENT-OFF* */
-VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
-{
- .path = "set interface ip6 table",
- .function = add_del_ip6_interface_table,
- .short_help = "set interface ip6 table <interface> <table-id>"
-};
-/* *INDENT-ON* */
-
void
ip6_link_local_address_from_ethernet_mac_address (ip6_address_t * ip,
u8 * mac)
diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c
index 62cf23ac..56f33ac8 100644
--- a/src/vnet/ip/ip6_neighbor.c
+++ b/src/vnet/ip/ip6_neighbor.c
@@ -250,6 +250,26 @@ format_ip6_neighbor_ip6_entry (u8 * s, va_list * va)
return s;
}
+static void
+ip6_neighbor_adj_fib_remove (ip6_neighbor_t * n, uint32_t fib_index)
+{
+ if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
+ {
+ fib_prefix_t pfx = {
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_addr.ip6 = n->key.ip6_address,
+ };
+ fib_table_entry_path_remove (fib_index,
+ &pfx,
+ FIB_SOURCE_ADJ,
+ DPO_PROTO_IP6,
+ &pfx.fp_addr,
+ n->key.sw_if_index, ~0,
+ 1, FIB_ROUTE_PATH_FLAG_NONE);
+ }
+}
+
static clib_error_t *
ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
u32 sw_if_index, u32 flags)
@@ -273,22 +293,10 @@ ip6_neighbor_sw_interface_up_down (vnet_main_t * vnm,
{
n = pool_elt_at_index (nm->neighbor_pool, to_delete[i]);
mhash_unset (&nm->neighbor_index_by_key, &n->key, 0);
- if (FIB_NODE_INDEX_INVALID != n->fib_entry_index)
- {
- fib_prefix_t pfx = {
- .fp_len = 128,
- .fp_proto = FIB_PROTOCOL_IP6,
- .fp_addr.ip6 = n->key.ip6_address,
- };
- fib_table_entry_path_remove
- (ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index),
- &pfx,
- FIB_SOURCE_ADJ,
- DPO_PROTO_IP6,
- &pfx.fp_addr,
- n->key.sw_if_index, ~0, 1, FIB_ROUTE_PATH_FLAG_NONE);
- pool_put (nm->neighbor_pool, n);
- }
+ ip6_neighbor_adj_fib_remove (n,
+ ip6_fib_table_get_index_for_sw_if_index
+ (n->key.sw_if_index));
+ pool_put (nm->neighbor_pool, n);
}
vec_free (to_delete);
}
@@ -579,6 +587,24 @@ ip6_ethernet_update_adjacency (vnet_main_t * vnm, u32 sw_if_index, u32 ai)
}
}
+
+static void
+ip6_neighbor_adj_fib_add (ip6_neighbor_t * n, uint32_t fib_index)
+{
+ fib_prefix_t pfx = {
+ .fp_len = 128,
+ .fp_proto = FIB_PROTOCOL_IP6,
+ .fp_addr.ip6 = n->key.ip6_address,
+ };
+
+ n->fib_entry_index =
+ fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
+ FIB_ENTRY_FLAG_ATTACHED,
+ DPO_PROTO_IP6, &pfx.fp_addr,
+ n->key.sw_if_index, ~0, 1, NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+}
+
int
vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
u32 sw_if_index,
@@ -633,21 +659,9 @@ vnet_set_ip6_ethernet_neighbor (vlib_main_t * vm,
*/
if (!is_no_fib_entry)
{
- fib_prefix_t pfx = {
- .fp_len = 128,
- .fp_proto = FIB_PROTOCOL_IP6,
- .fp_addr.ip6 = k.ip6_address,
- };
- u32 fib_index;
-
- fib_index =
- ip6_fib_table_get_index_for_sw_if_index (n->key.sw_if_index);
- n->fib_entry_index =
- fib_table_entry_path_add (fib_index, &pfx, FIB_SOURCE_ADJ,
- FIB_ENTRY_FLAG_ATTACHED,
- DPO_PROTO_IP6, &pfx.fp_addr,
- n->key.sw_if_index, ~0, 1, NULL,
- FIB_ROUTE_PATH_FLAG_NONE);
+ ip6_neighbor_adj_fib_add (n,
+ ip6_fib_table_get_index_for_sw_if_index
+ (n->key.sw_if_index));
}
else
{
@@ -3843,6 +3857,33 @@ ip6_set_neighbor_limit (u32 neighbor_limit)
return 0;
}
+static void
+ip6_neighbor_table_bind (ip6_main_t * im,
+ uword opaque,
+ u32 sw_if_index,
+ u32 new_fib_index, u32 old_fib_index)
+{
+ ip6_neighbor_main_t *nm = &ip6_neighbor_main;
+ ip6_neighbor_t *n = NULL;
+ u32 i, *to_re_add = 0;
+
+ /* *INDENT-OFF* */
+ pool_foreach (n, nm->neighbor_pool,
+ ({
+ if (n->key.sw_if_index == sw_if_index)
+ vec_add1 (to_re_add, n - nm->neighbor_pool);
+ }));
+ /* *INDENT-ON* */
+
+ for (i = 0; i < vec_len (to_re_add); i++)
+ {
+ n = pool_elt_at_index (nm->neighbor_pool, to_re_add[i]);
+ ip6_neighbor_adj_fib_remove (n, old_fib_index);
+ ip6_neighbor_adj_fib_add (n, new_fib_index);
+ }
+ vec_free (to_re_add);
+}
+
static clib_error_t *
ip6_neighbor_init (vlib_main_t * vm)
{
@@ -3874,6 +3915,11 @@ ip6_neighbor_init (vlib_main_t * vm)
cb.function_opaque = 0;
vec_add1 (im->add_del_interface_address_callbacks, cb);
+ ip6_table_bind_callback_t cbt;
+ cbt.function = ip6_neighbor_table_bind;
+ cbt.function_opaque = 0;
+ vec_add1 (im->table_bind_callbacks, cbt);
+
mhash_init (&nm->pending_resolutions_by_address,
/* value size */ sizeof (uword),
/* key size */ sizeof (ip6_address_t));
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index bba65ab4..384ec3e0 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -700,11 +700,57 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
}
void
+ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 != fib_index)
+ {
+ fib_table_unlock (fib_index, fproto,
+ (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+ }
+ if (~0 != mfib_index)
+ {
+ mfib_table_unlock (mfib_index, fproto,
+ (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
+ }
+ }
+}
+
+void
vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
{
vl_api_ip_table_add_del_reply_t *rmp;
+ fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+ u32 table_id = ntohl (mp->table_id);
int rv = 0;
+ if (mp->is_add)
+ {
+ ip_table_create (fproto, table_id, 1);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 1);
+ }
+
REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
}
@@ -866,18 +912,21 @@ add_del_route_check (fib_protocol_t table_proto,
u32 next_hop_sw_if_index,
dpo_proto_t next_hop_table_proto,
u32 next_hop_table_id,
- u8 create_missing_tables,
u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
+ /* Temporaray whilst I do the CSIT dance */
+ u8 create_missing_tables = 1;
+
*fib_index = fib_table_find (table_proto, ntohl (table_id));
if (~0 == *fib_index)
{
if (create_missing_tables)
{
*fib_index = fib_table_find_or_create_and_lock (table_proto,
- ntohl (table_id));
+ ntohl (table_id),
+ FIB_SOURCE_API);
}
else
{
@@ -918,12 +967,14 @@ add_del_route_check (fib_protocol_t table_proto,
*next_hop_fib_index =
mfib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ MFIB_SOURCE_API);
else
*next_hop_fib_index =
fib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ FIB_SOURCE_API);
}
else
{
@@ -948,8 +999,7 @@ ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
mp->next_hop_sw_if_index,
DPO_PROTO_IP4,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
@@ -1008,8 +1058,7 @@ ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
mp->next_hop_sw_if_index,
DPO_PROTO_IP6,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
@@ -1074,27 +1123,57 @@ vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
}
+void
+ip_table_create (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 == fib_index)
+ {
+ fib_table_find_or_create_and_lock (fproto, table_id,
+ (is_api ?
+ FIB_SOURCE_API :
+ FIB_SOURCE_CLI));
+ }
+ if (~0 == mfib_index)
+ {
+ mfib_table_find_or_create_and_lock (fproto, table_id,
+ (is_api ?
+ MFIB_SOURCE_API :
+ MFIB_SOURCE_CLI));
+ }
+ }
+}
+
static int
add_del_mroute_check (fib_protocol_t table_proto,
u32 table_id,
- u32 next_hop_sw_if_index,
- u8 is_local, u8 create_missing_tables, u32 * fib_index)
+ u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
*fib_index = mfib_table_find (table_proto, ntohl (table_id));
if (~0 == *fib_index)
{
- if (create_missing_tables)
- {
- *fib_index = mfib_table_find_or_create_and_lock (table_proto,
- ntohl (table_id));
- }
- else
- {
- /* No such VRF, and we weren't asked to create one */
- return VNET_API_ERROR_NO_SUCH_FIB;
- }
+ /* No such table */
+ return VNET_API_ERROR_NO_SUCH_FIB;
}
if (~0 != ntohl (next_hop_sw_if_index))
@@ -1163,8 +1242,7 @@ api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp)
rv = add_del_mroute_check (fproto,
mp->table_id,
mp->next_hop_sw_if_index,
- mp->is_local,
- mp->create_vrf_if_needed, &fib_index);
+ mp->is_local, &fib_index);
if (0 != rv)
return (rv);
diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c
index 5537bb04..667c6791 100755
--- a/src/vnet/ip/lookup.c
+++ b/src/vnet/ip/lookup.c
@@ -687,6 +687,78 @@ done:
return error;
}
+clib_error_t *
+vnet_ip_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input,
+ vlib_cli_command_t * cmd, fib_protocol_t fproto)
+{
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = NULL;
+ u32 table_id, is_add;
+
+ is_add = 1;
+ table_id = ~0;
+
+ /* Get a line of input. */
+ if (!unformat_user (main_input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "%d", &table_id))
+ ;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else if (unformat (line_input, "add"))
+ is_add = 1;
+ else
+ {
+ error = unformat_parse_error (line_input);
+ goto done;
+ }
+ }
+
+ if (~0 == table_id)
+ {
+ error = clib_error_return (0, "No table id");
+ goto done;
+ }
+ else if (0 == table_id)
+ {
+ error = clib_error_return (0, "Can't change the default table");
+ goto done;
+ }
+ else
+ {
+ if (is_add)
+ {
+ ip_table_create (fproto, table_id, 0);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 0);
+ }
+ }
+
+done:
+ unformat_free (line_input);
+ return error;
+}
+
+clib_error_t *
+vnet_ip4_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+ return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP4));
+}
+
+clib_error_t *
+vnet_ip6_table_cmd (vlib_main_t * vm,
+ unformat_input_t * main_input, vlib_cli_command_t * cmd)
+{
+ return (vnet_ip_table_cmd (vm, main_input, cmd, FIB_PROTOCOL_IP6));
+}
+
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (vlib_cli_ip_command, static) = {
.path = "ip",
@@ -749,6 +821,159 @@ VLIB_CLI_COMMAND (ip_route_command, static) = {
.function = vnet_ip_route_cmd,
.is_mp_safe = 1,
};
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4 Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip4_table_command, static) = {
+ .path = "ip table",
+ .short_help = "ip table [add|del] <table-id>",
+ .function = vnet_ip4_table_cmd,
+ .is_mp_safe = 1,
+};
+/* *INDENT-ON* */
+
+/* *INDENT-ON* */
+/*?
+ * This command is used to add or delete IPv4 Tables. All
+ * Tables must be explicitly added before that can be used. Creating a
+ * table will add both unicast and multicast FIBs
+ *
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (ip6_table_command, static) = {
+ .path = "ip6 table",
+ .short_help = "ip6 table [add|del] <table-id>",
+ .function = vnet_ip6_table_cmd,
+ .is_mp_safe = 1,
+};
+
+static clib_error_t *
+ip_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd,
+ fib_protocol_t fproto)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ clib_error_t *error = 0;
+ u32 sw_if_index, table_id;
+ int rv;
+
+ sw_if_index = ~0;
+
+ if (!unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
+ {
+ error = clib_error_return (0, "unknown interface `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+
+ if (unformat (input, "%d", &table_id))
+ ;
+ else
+ {
+ error = clib_error_return (0, "expected table id `%U'",
+ format_unformat_error, input);
+ goto done;
+ }
+
+ rv = ip_table_bind (fproto, sw_if_index, table_id, 0);
+
+ if (VNET_API_ERROR_ADDRESS_FOUND_FOR_INTERFACE == rv)
+ {
+ error = clib_error_return (0, "IP addresses are still present on %U",
+ format_vnet_sw_if_index_name,
+ vnet_get_main(),
+ sw_if_index);
+ }
+ else if (VNET_API_ERROR_NO_SUCH_FIB == rv)
+ {
+ error = clib_error_return (0, "no such table %d", table_id);
+ }
+ else if (0 != rv)
+ {
+ error = clib_error_return (0, "unknown error");
+ }
+
+ done:
+ return error;
+}
+
+static clib_error_t *
+ip4_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP4));
+}
+
+static clib_error_t *
+ip6_table_bind_cmd (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ return (ip_table_bind_cmd (vm , input, cmd, FIB_PROTOCOL_IP6));
+}
+
+/*?
+ * Place the indicated interface into the supplied IPv4 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv4 FIB table, use the command '<em>show ip fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * 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 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):
+ * @cliexcmd{set interface ip table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip_table_command, static) =
+{
+ .path = "set interface ip table",
+ .function = ip4_table_bind_cmd,
+ .short_help = "set interface ip table <interface> <table-id>",
+};
+/* *INDENT-ON* */
+
+/*?
+ * Place the indicated interface into the supplied IPv6 FIB table (also known
+ * as a VRF). If the FIB table does not exist, this command creates it. To
+ * display the current IPv6 FIB table, use the command '<em>show ip6 fib</em>'.
+ * FIB table will only be displayed if a route has been added to the table, or
+ * 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 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):
+ * @cliexcmd{set interface ip6 table GigabitEthernet2/0/0 2}
+ ?*/
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (set_interface_ip6_table_command, static) =
+{
+ .path = "set interface ip6 table",
+ .function = ip6_table_bind_cmd,
+ .short_help = "set interface ip6 table <interface> <table-id>"
+};
/* *INDENT-ON* */
clib_error_t *