VPP-453: SNAT delete and dump addresses
Delete operation for SNAT addresses Dump API for SNAT addresses Change-Id: I84e888d20286ec2523fbd4ca7e68e3eef5927984 Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:
@ -20,12 +20,13 @@
|
|||||||
* called through a shared memory interface.
|
* called through a shared memory interface.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** \brief Add S-NAT address range
|
/** \brief Add/del S-NAT address range
|
||||||
@param client_index - opaque cookie to identify the sender
|
@param client_index - opaque cookie to identify the sender
|
||||||
@param context - sender context, to match reply w/ request
|
@param context - sender context, to match reply w/ request
|
||||||
@param is_ip4 - 1 if address type is IPv4
|
@param is_ip4 - 1 if address type is IPv4
|
||||||
@first_ip_address - first IP address
|
@first_ip_address - first IP address
|
||||||
@last_ip_address - last IP address
|
@last_ip_address - last IP address
|
||||||
|
@is_add - 1 if add, 0 if delete
|
||||||
*/
|
*/
|
||||||
define snat_add_address_range {
|
define snat_add_address_range {
|
||||||
u32 client_index;
|
u32 client_index;
|
||||||
@ -33,6 +34,7 @@ define snat_add_address_range {
|
|||||||
u8 is_ip4;
|
u8 is_ip4;
|
||||||
u8 first_ip_address[16];
|
u8 first_ip_address[16];
|
||||||
u8 last_ip_address[16];
|
u8 last_ip_address[16];
|
||||||
|
u8 is_add;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Add S-NAT address range reply
|
/** \brief Add S-NAT address range reply
|
||||||
@ -45,6 +47,26 @@ define snat_add_address_range_reply {
|
|||||||
i32 retval;
|
i32 retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** \brief Dump S-NAT addresses
|
||||||
|
@param client_index - opaque cookie to identify the sender
|
||||||
|
@param context - sender context, to match reply w/ request
|
||||||
|
*/
|
||||||
|
define snat_address_dump {
|
||||||
|
u32 client_index;
|
||||||
|
u32 context;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** \brief S-NAT address details response
|
||||||
|
@param context - sender context, to match reply w/ request
|
||||||
|
@param is_ip4 - 1 if address type is IPv4
|
||||||
|
@param ip_address - IP address
|
||||||
|
*/
|
||||||
|
define snat_address_details {
|
||||||
|
u32 context;
|
||||||
|
u8 is_ip4;
|
||||||
|
u8 ip_address[16];
|
||||||
|
};
|
||||||
|
|
||||||
/** \brief Enable/disable S-NAT feature on the interface
|
/** \brief Enable/disable S-NAT feature on the interface
|
||||||
@param client_index - opaque cookie to identify the sender
|
@param client_index - opaque cookie to identify the sender
|
||||||
@param context - sender context, to match reply w/ request
|
@param context - sender context, to match reply w/ request
|
||||||
|
@ -207,6 +207,84 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int is_snat_address_used_in_static_mapping (snat_main_t *sm,
|
||||||
|
ip4_address_t addr)
|
||||||
|
{
|
||||||
|
snat_static_mapping_t *m;
|
||||||
|
pool_foreach (m, sm->static_mappings,
|
||||||
|
({
|
||||||
|
if (m->external_addr.as_u32 == addr.as_u32)
|
||||||
|
return 1;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int snat_del_address (snat_main_t *sm, ip4_address_t addr)
|
||||||
|
{
|
||||||
|
clib_warning("%U", format_ip4_address, &addr);
|
||||||
|
snat_address_t *a = 0;
|
||||||
|
snat_session_t *ses;
|
||||||
|
u32 *ses_to_be_removed = 0, *ses_index;
|
||||||
|
clib_bihash_kv_8_8_t kv, value;
|
||||||
|
snat_user_key_t user_key;
|
||||||
|
snat_user_t *u;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Find SNAT address */
|
||||||
|
for (i=0; i < vec_len (sm->addresses); i++)
|
||||||
|
{
|
||||||
|
if (sm->addresses[i].addr.as_u32 == addr.as_u32)
|
||||||
|
{
|
||||||
|
a = sm->addresses + i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!a)
|
||||||
|
return VNET_API_ERROR_NO_SUCH_ENTRY;
|
||||||
|
|
||||||
|
/* Check if address is used in some static mapping */
|
||||||
|
if (is_snat_address_used_in_static_mapping(sm, addr))
|
||||||
|
{
|
||||||
|
clib_warning ("address used in static mapping");
|
||||||
|
return VNET_API_ERROR_UNSPECIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete sessions using address */
|
||||||
|
if (a->busy_ports)
|
||||||
|
{
|
||||||
|
pool_foreach (ses, sm->sessions, ({
|
||||||
|
if (ses->out2in.addr.as_u32 == addr.as_u32)
|
||||||
|
{
|
||||||
|
vec_add1 (ses_to_be_removed, ses - sm->sessions);
|
||||||
|
kv.key = ses->in2out.as_u64;
|
||||||
|
clib_bihash_add_del_8_8 (&sm->in2out, &kv, 0);
|
||||||
|
kv.key = ses->out2in.as_u64;
|
||||||
|
clib_bihash_add_del_8_8 (&sm->out2in, &kv, 0);
|
||||||
|
clib_dlist_remove (sm->list_pool, ses->per_user_index);
|
||||||
|
user_key.addr = ses->in2out.addr;
|
||||||
|
user_key.fib_index = ses->in2out.fib_index;
|
||||||
|
kv.key = user_key.as_u64;
|
||||||
|
if (!clib_bihash_search_8_8 (&sm->user_hash, &kv, &value))
|
||||||
|
{
|
||||||
|
u = pool_elt_at_index (sm->users, value.value);
|
||||||
|
u->nsessions--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
vec_foreach (ses_index, ses_to_be_removed)
|
||||||
|
pool_put_index (sm->sessions, ses_index[0]);
|
||||||
|
|
||||||
|
vec_free (ses_to_be_removed);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec_del1 (sm->addresses, i);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void increment_v4_address (ip4_address_t * a)
|
static void increment_v4_address (ip4_address_t * a)
|
||||||
{
|
{
|
||||||
u32 v;
|
u32 v;
|
||||||
@ -490,7 +568,14 @@ vl_api_snat_add_address_range_t_handler
|
|||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
snat_add_address (sm, &this_addr);
|
if (mp->is_add)
|
||||||
|
snat_add_address (sm, &this_addr);
|
||||||
|
else
|
||||||
|
rv = snat_del_address (sm, this_addr);
|
||||||
|
|
||||||
|
if (rv)
|
||||||
|
goto send_reply;
|
||||||
|
|
||||||
increment_v4_address (&this_addr);
|
increment_v4_address (&this_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,6 +597,49 @@ static void *vl_api_snat_add_address_range_t_print
|
|||||||
FINISH;
|
FINISH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
send_snat_address_details
|
||||||
|
(snat_address_t * a, unix_shared_memory_queue_t * q, u32 context)
|
||||||
|
{
|
||||||
|
vl_api_snat_address_details_t *rmp;
|
||||||
|
snat_main_t * sm = &snat_main;
|
||||||
|
|
||||||
|
rmp = vl_msg_api_alloc (sizeof (*rmp));
|
||||||
|
memset (rmp, 0, sizeof (*rmp));
|
||||||
|
rmp->_vl_msg_id = ntohs (VL_API_SNAT_ADDRESS_DETAILS+sm->msg_id_base);
|
||||||
|
rmp->is_ip4 = 1;
|
||||||
|
clib_memcpy (rmp->ip_address, &(a->addr), 4);
|
||||||
|
rmp->context = context;
|
||||||
|
|
||||||
|
vl_msg_api_send_shmem (q, (u8 *) & rmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vl_api_snat_address_dump_t_handler
|
||||||
|
(vl_api_snat_address_dump_t * mp)
|
||||||
|
{
|
||||||
|
unix_shared_memory_queue_t *q;
|
||||||
|
snat_main_t * sm = &snat_main;
|
||||||
|
snat_address_t * a;
|
||||||
|
|
||||||
|
q = vl_api_client_index_to_input_queue (mp->client_index);
|
||||||
|
if (q == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
vec_foreach (a, sm->addresses)
|
||||||
|
send_snat_address_details (a, q, mp->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *vl_api_snat_address_dump_t_print
|
||||||
|
(vl_api_snat_address_dump_t *mp, void * handle)
|
||||||
|
{
|
||||||
|
u8 *s;
|
||||||
|
|
||||||
|
s = format (0, "SCRIPT: snat_address_dump ");
|
||||||
|
|
||||||
|
FINISH;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vl_api_snat_interface_add_del_feature_t_handler
|
vl_api_snat_interface_add_del_feature_t_handler
|
||||||
(vl_api_snat_interface_add_del_feature_t * mp)
|
(vl_api_snat_interface_add_del_feature_t * mp)
|
||||||
@ -735,7 +863,8 @@ _(SNAT_INTERFACE_ADD_DEL_FEATURE, snat_interface_add_del_feature) \
|
|||||||
_(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping) \
|
_(SNAT_ADD_STATIC_MAPPING, snat_add_static_mapping) \
|
||||||
_(SNAT_CONTROL_PING, snat_control_ping) \
|
_(SNAT_CONTROL_PING, snat_control_ping) \
|
||||||
_(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump) \
|
_(SNAT_STATIC_MAPPING_DUMP, snat_static_mapping_dump) \
|
||||||
_(SNAT_SHOW_CONFIG, snat_show_config)
|
_(SNAT_SHOW_CONFIG, snat_show_config) \
|
||||||
|
_(SNAT_ADDRESS_DUMP, snat_address_dump)
|
||||||
|
|
||||||
/* Set up the API message handling tables */
|
/* Set up the API message handling tables */
|
||||||
static clib_error_t *
|
static clib_error_t *
|
||||||
@ -921,20 +1050,27 @@ add_address_command_fn (vlib_main_t * vm,
|
|||||||
ip4_address_t start_addr, end_addr, this_addr;
|
ip4_address_t start_addr, end_addr, this_addr;
|
||||||
u32 start_host_order, end_host_order;
|
u32 start_host_order, end_host_order;
|
||||||
int i, count;
|
int i, count;
|
||||||
|
int is_add = 1;
|
||||||
|
int rv = 0;
|
||||||
|
|
||||||
/* Get a line of input. */
|
/* Get a line of input. */
|
||||||
if (!unformat_user (input, unformat_line_input, line_input))
|
if (!unformat_user (input, unformat_line_input, line_input))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (unformat (line_input, "%U - %U",
|
while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
|
||||||
unformat_ip4_address, &start_addr,
|
{
|
||||||
unformat_ip4_address, &end_addr))
|
if (unformat (line_input, "%U - %U",
|
||||||
;
|
unformat_ip4_address, &start_addr,
|
||||||
else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
|
unformat_ip4_address, &end_addr))
|
||||||
end_addr = start_addr;
|
;
|
||||||
else
|
else if (unformat (line_input, "%U", unformat_ip4_address, &start_addr))
|
||||||
return clib_error_return (0, "unknown input '%U'", format_unformat_error,
|
end_addr = start_addr;
|
||||||
input);
|
else if (unformat (line_input, "del"))
|
||||||
|
is_add = 0;
|
||||||
|
else
|
||||||
|
return clib_error_return (0, "unknown input '%U'",
|
||||||
|
format_unformat_error, input);
|
||||||
|
}
|
||||||
unformat_free (line_input);
|
unformat_free (line_input);
|
||||||
|
|
||||||
if (sm->static_mapping_only)
|
if (sm->static_mapping_only)
|
||||||
@ -958,7 +1094,23 @@ add_address_command_fn (vlib_main_t * vm,
|
|||||||
|
|
||||||
for (i = 0; i < count; i++)
|
for (i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
snat_add_address (sm, &this_addr);
|
if (is_add)
|
||||||
|
snat_add_address (sm, &this_addr);
|
||||||
|
else
|
||||||
|
rv = snat_del_address (sm, this_addr);
|
||||||
|
|
||||||
|
switch (rv)
|
||||||
|
{
|
||||||
|
case VNET_API_ERROR_NO_SUCH_ENTRY:
|
||||||
|
return clib_error_return (0, "S-NAT address not exist.");
|
||||||
|
break;
|
||||||
|
case VNET_API_ERROR_UNSPECIFIED:
|
||||||
|
return clib_error_return (0, "S-NAT address used in static mapping.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
increment_v4_address (&this_addr);
|
increment_v4_address (&this_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -967,7 +1119,7 @@ add_address_command_fn (vlib_main_t * vm,
|
|||||||
|
|
||||||
VLIB_CLI_COMMAND (add_address_command, static) = {
|
VLIB_CLI_COMMAND (add_address_command, static) = {
|
||||||
.path = "snat add address",
|
.path = "snat add address",
|
||||||
.short_help = "snat add addresses <ip4-range-start> [- <ip4-range-end>]",
|
.short_help = "snat add addresses <ip4-range-start> [- <ip4-range-end>] [del]",
|
||||||
.function = add_address_command_fn,
|
.function = add_address_command_fn,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -89,7 +89,8 @@ _(SNAT_INTERFACE_ADD_DEL_FEATURE_REPLY, \
|
|||||||
_(SNAT_ADD_STATIC_MAPPING_REPLY, snat_add_static_mapping_reply) \
|
_(SNAT_ADD_STATIC_MAPPING_REPLY, snat_add_static_mapping_reply) \
|
||||||
_(SNAT_CONTROL_PING_REPLY, snat_control_ping_reply) \
|
_(SNAT_CONTROL_PING_REPLY, snat_control_ping_reply) \
|
||||||
_(SNAT_STATIC_MAPPING_DETAILS, snat_static_mapping_details) \
|
_(SNAT_STATIC_MAPPING_DETAILS, snat_static_mapping_details) \
|
||||||
_(SNAT_SHOW_CONFIG_REPLY, snat_show_config_reply)
|
_(SNAT_SHOW_CONFIG_REPLY, snat_show_config_reply) \
|
||||||
|
_(SNAT_ADDRESS_DETAILS, snat_address_details)
|
||||||
|
|
||||||
/* M: construct, but don't yet send a message */
|
/* M: construct, but don't yet send a message */
|
||||||
#define M(T,t) \
|
#define M(T,t) \
|
||||||
@ -134,18 +135,24 @@ static int api_snat_add_address_range (vat_main_t * vam)
|
|||||||
ip4_address_t start_addr, end_addr;
|
ip4_address_t start_addr, end_addr;
|
||||||
u32 start_host_order, end_host_order;
|
u32 start_host_order, end_host_order;
|
||||||
vl_api_snat_add_address_range_t * mp;
|
vl_api_snat_add_address_range_t * mp;
|
||||||
|
u8 is_add = 1;
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
if (unformat (i, "%U - %U",
|
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||||
unformat_ip4_address, &start_addr,
|
|
||||||
unformat_ip4_address, &end_addr))
|
|
||||||
;
|
|
||||||
else if (unformat (i, "%U", unformat_ip4_address, &start_addr))
|
|
||||||
end_addr = start_addr;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
clib_warning("unknown input '%U'", format_unformat_error, i);
|
if (unformat (i, "%U - %U",
|
||||||
return -99;
|
unformat_ip4_address, &start_addr,
|
||||||
|
unformat_ip4_address, &end_addr))
|
||||||
|
;
|
||||||
|
else if (unformat (i, "%U", unformat_ip4_address, &start_addr))
|
||||||
|
end_addr = start_addr;
|
||||||
|
else if (unformat (i, "del"))
|
||||||
|
is_add = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clib_warning("unknown input '%U'", format_unformat_error, i);
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
|
start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
|
||||||
@ -172,6 +179,7 @@ static int api_snat_add_address_range (vat_main_t * vam)
|
|||||||
memcpy (mp->first_ip_address, &start_addr, 4);
|
memcpy (mp->first_ip_address, &start_addr, 4);
|
||||||
memcpy (mp->last_ip_address, &end_addr, 4);
|
memcpy (mp->last_ip_address, &end_addr, 4);
|
||||||
mp->is_ip4 = 1;
|
mp->is_ip4 = 1;
|
||||||
|
mp->is_add = is_add;
|
||||||
|
|
||||||
S; W;
|
S; W;
|
||||||
|
|
||||||
@ -395,18 +403,53 @@ static int api_snat_show_config(vat_main_t * vam)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vl_api_snat_address_details_t_handler
|
||||||
|
(vl_api_snat_address_details_t *mp)
|
||||||
|
{
|
||||||
|
snat_test_main_t * sm = &snat_test_main;
|
||||||
|
vat_main_t *vam = sm->vat_main;
|
||||||
|
|
||||||
|
fformat (vam->ofp, "%U\n", format_ip4_address, &mp->ip_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int api_snat_address_dump(vat_main_t * vam)
|
||||||
|
{
|
||||||
|
snat_test_main_t * sm = &snat_test_main;
|
||||||
|
f64 timeout;
|
||||||
|
vl_api_snat_address_dump_t * mp;
|
||||||
|
|
||||||
|
if (vam->json_output)
|
||||||
|
{
|
||||||
|
clib_warning ("JSON output not supported for snat_address_dump");
|
||||||
|
return -99;
|
||||||
|
}
|
||||||
|
|
||||||
|
M(SNAT_ADDRESS_DUMP, snat_address_dump);
|
||||||
|
S;
|
||||||
|
/* Use a control ping for synchronization */
|
||||||
|
{
|
||||||
|
vl_api_snat_control_ping_t *mp;
|
||||||
|
M (SNAT_CONTROL_PING, snat_control_ping);
|
||||||
|
S;
|
||||||
|
}
|
||||||
|
W;
|
||||||
|
/* NOTREACHED */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of messages that the api test plugin sends,
|
* List of messages that the api test plugin sends,
|
||||||
* and that the data plane plugin processes
|
* and that the data plane plugin processes
|
||||||
*/
|
*/
|
||||||
#define foreach_vpe_api_msg \
|
#define foreach_vpe_api_msg \
|
||||||
_(snat_add_address_range, "<start-addr> [- <end-addr]") \
|
_(snat_add_address_range, "<start-addr> [- <end-addr] [del]") \
|
||||||
_(snat_interface_add_del_feature, \
|
_(snat_interface_add_del_feature, \
|
||||||
"<intfc> | sw_if_index <id> [in] [out] [del]") \
|
"<intfc> | sw_if_index <id> [in] [out] [del]") \
|
||||||
_(snat_add_static_mapping, "local_addr <ip> external_addr <ip> " \
|
_(snat_add_static_mapping, "local_addr <ip> external_addr <ip> " \
|
||||||
"[local_port <n>] [external_port <n>] [vrf <table-id>] [del]") \
|
"[local_port <n>] [external_port <n>] [vrf <table-id>] [del]") \
|
||||||
_(snat_static_mapping_dump, "") \
|
_(snat_static_mapping_dump, "") \
|
||||||
_(snat_show_config, "")
|
_(snat_show_config, "") \
|
||||||
|
_(snat_address_dump, "")
|
||||||
|
|
||||||
void vat_api_hookup (vat_main_t *vam)
|
void vat_api_hookup (vat_main_t *vam)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user