From 6e4cfb506806a0e214a5498952c2587e128b4870 Mon Sep 17 00:00:00 2001 From: Aloys Augustin Date: Thu, 16 Sep 2021 20:53:14 +0200 Subject: ip: add ip_table_allocate to api Set tableID = ~0 for auto selection unused ID https://jira.fd.io/browse/VPP-1993 Type: improvement Change-Id: I4eec2cc1d18fc025196cb6ac4c9a4b374388eb56 Signed-off-by: Artem Glazychev Signed-off-by: Aloys Augustin --- src/vnet/fib/fib_table.c | 3 ++- src/vnet/ip/ip.api | 31 +++++++++++++++++++++++++++++- src/vnet/ip/ip.h | 2 ++ src/vnet/ip/ip_api.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++ src/vnet/ip/ip_test.c | 11 +++++++++++ src/vnet/ip/lookup.c | 33 ++++++++++++++++++-------------- 6 files changed, 113 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/vnet/fib/fib_table.c b/src/vnet/fib/fib_table.c index 7cc989d6324..f222828898b 100644 --- a/src/vnet/fib/fib_table.c +++ b/src/vnet/fib/fib_table.c @@ -1322,6 +1322,7 @@ fib_table_lock_dec (fib_table_t *fib_table, { vec_validate(fib_table->ft_locks, source); + ASSERT(fib_table->ft_locks[source] > 0); fib_table->ft_locks[source]--; fib_table->ft_total_locks--; } @@ -1350,7 +1351,7 @@ fib_table_unlock (u32 fib_index, if (0 == fib_table->ft_total_locks) { /* - * no more locak from any source - kill it + * no more lock from any source - kill it */ fib_table_destroy(fib_table); } diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 28786fa5a90..ca1e2008e4f 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -20,7 +20,7 @@ called through a shared memory interface. */ -option version = "3.1.0"; +option version = "3.2.0"; import "vnet/interface_types.api"; import "vnet/fib/fib_types.api"; @@ -57,6 +57,35 @@ autoreply define ip_table_add_del vl_api_ip_table_t table; }; +/** \brief Allocate an unused table + A table can be added multiple times. + If a large number of tables are in use (millions), this API might + fail to find a free ID with very low probability, and will return + EAGAIN. A subsequent attempt may be successful. + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param table - if table.table_id == ~0, vpp allocates an unused table_id and + proceeds as in ip_table_add_del with is_add = true + if table.table_id != ~0, vpp uses the table.table_id and + proceeds as in ip_table_add_del with is_add = true + table.table_id should never be 0 +*/ +define ip_table_allocate +{ + u32 client_index; + u32 context; + + vl_api_ip_table_t table; +}; + +define ip_table_allocate_reply +{ + u32 context; + i32 retval; + + vl_api_ip_table_t table; +}; + /** \brief Dump IP all fib tables @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request diff --git a/src/vnet/ip/ip.h b/src/vnet/ip/ip.h index 6d822d29dbe..cda0de2a451 100644 --- a/src/vnet/ip/ip.h +++ b/src/vnet/ip/ip.h @@ -270,6 +270,8 @@ void ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api); int ip_table_bind (fib_protocol_t fproto, u32 sw_if_index, u32 table_id, u8 is_api); +u32 ip_table_get_unused_id (fib_protocol_t fproto); + u8 ip_is_zero (ip46_address_t * ip46_address, u8 is_ip4); u8 ip_is_local_host (ip46_address_t * ip46_address, u8 is_ip4); u8 ip4_is_local_host (ip4_address_t * ip4_address); diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index f9f9ac783d9..f5ebd029a46 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -601,6 +601,32 @@ ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api) } } +/* + * Returns an unused table id, and ~0 if it can't find one. + */ +u32 +ip_table_get_unused_id (fib_protocol_t fproto) +{ + int i, j; + u32 seed = random_default_seed (); + /* limit to 1M tries */ + for (j = 0; j < 1 << 10; j++) + { + seed = random_u32 (&seed); + for (i = 0; i < 1 << 10; i++) + { + /* look around randomly generated id */ + seed += (2 * (i % 2) - 1) * i; + if (seed == ~0) + continue; + if (fib_table_find (fproto, seed) == ~0) + return seed; + } + } + + return ~0; +} + void vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) { @@ -622,6 +648,29 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY); } +void +vl_api_ip_table_allocate_t_handler (vl_api_ip_table_allocate_t *mp) +{ + vl_api_ip_table_allocate_reply_t *rmp; + fib_protocol_t fproto = + (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + u32 table_id = ntohl (mp->table.table_id); + int rv = 0; + + if (~0 == table_id) + table_id = ip_table_get_unused_id (fproto); + + if (~0 == table_id) + rv = VNET_API_ERROR_EAGAIN; + else + ip_table_create (fproto, table_id, 1, mp->table.name); + + REPLY_MACRO2 (VL_API_IP_TABLE_ALLOCATE_REPLY, { + clib_memcpy_fast (&rmp->table, &mp->table, sizeof (mp->table)); + rmp->table.table_id = htonl (table_id); + }) +} + static int ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp, u32 * stats_index) { diff --git a/src/vnet/ip/ip_test.c b/src/vnet/ip/ip_test.c index 2de8235288d..6bdeca5ff32 100644 --- a/src/vnet/ip/ip_test.c +++ b/src/vnet/ip/ip_test.c @@ -524,6 +524,17 @@ api_ip_table_flush (vat_main_t *vam) return ret; } +static int +api_ip_table_allocate (vat_main_t *vam) +{ + return -1; +} + +static void +vl_api_ip_table_allocate_reply_t_handler (vl_api_ip_table_allocate_reply_t *mp) +{ +} + static void vl_api_ip_route_add_del_v2_reply_t_handler ( vl_api_ip_route_add_del_v2_reply_t *mp) diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index 1753ffd9232..5db14bac092 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -399,27 +399,32 @@ vnet_ip_table_cmd (vlib_main_t * vm, } } - if (~0 == table_id) - { - error = clib_error_return (0, "No table id"); - goto done; - } - else if (0 == table_id) + 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, name); - } - else - { - ip_table_delete (fproto, table_id, 0); + if (is_add) + { + if (~0 == table_id) + { + table_id = ip_table_get_unused_id (fproto); + vlib_cli_output (vm, "%u\n", table_id); + } + ip_table_create (fproto, table_id, 0, name); + } + else + { + if (~0 == table_id) + { + error = clib_error_return (0, "No table id"); + goto done; + } + ip_table_delete (fproto, table_id, 0); + } } - } done: unformat_free (line_input); -- cgit 1.2.3-korg