SNAT: add API and test for NAT pool address from interface
Change-Id: I2a868f736fae8d37b438c604a9284653ea415541 Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:

committed by
Damjan Marion

parent
97f6edc1f5
commit
8bf68e858a
@ -24,9 +24,9 @@
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_ip4 - 1 if address type is IPv4
|
||||
@first_ip_address - first IP address
|
||||
@last_ip_address - last IP address
|
||||
@is_add - 1 if add, 0 if delete
|
||||
@param first_ip_address - first IP address
|
||||
@param last_ip_address - last IP address
|
||||
@param is_add - 1 if add, 0 if delete
|
||||
*/
|
||||
define snat_add_address_range {
|
||||
u32 client_index;
|
||||
@ -38,7 +38,6 @@ define snat_add_address_range {
|
||||
};
|
||||
|
||||
/** \brief Add S-NAT address range reply
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
*/
|
||||
@ -83,7 +82,6 @@ define snat_interface_add_del_feature {
|
||||
};
|
||||
|
||||
/** \brief Enable/disable S-NAT feature on the interface reply
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
*/
|
||||
@ -138,7 +136,6 @@ define snat_add_static_mapping {
|
||||
};
|
||||
|
||||
/** \brief Add/delete S-NAT static mapping reply
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
*/
|
||||
@ -251,7 +248,6 @@ define snat_set_workers {
|
||||
};
|
||||
|
||||
/** \brief Set S-NAT workers reply
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
*/
|
||||
@ -281,3 +277,44 @@ define snat_worker_details {
|
||||
u32 lcore_id;
|
||||
u8 name[64];
|
||||
};
|
||||
|
||||
/** \brief Add/delete S-NAT pool address from specific interfce
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param is_add - 1 if add, 0 if delete
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
define snat_add_del_interface_addr {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
u8 is_add;
|
||||
u8 is_inside;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
||||
/** \brief Add/delete S-NAT pool address from specific interfce reply
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param retval - return code
|
||||
*/
|
||||
define snat_add_del_interface_addr_reply {
|
||||
u32 context;
|
||||
i32 retval;
|
||||
};
|
||||
|
||||
/** \brief Dump S-NAT pool addresses interfaces
|
||||
@param client_index - opaque cookie to identify the sender
|
||||
@param context - sender context, to match reply w/ request
|
||||
*/
|
||||
define snat_interface_addr_dump {
|
||||
u32 client_index;
|
||||
u32 context;
|
||||
};
|
||||
|
||||
/** \brief S-NAT pool addresses interfaces details response
|
||||
@param context - sender context, to match reply w/ request
|
||||
@param sw_if_index - software index of the interface
|
||||
*/
|
||||
define snat_interface_addr_details {
|
||||
u32 context;
|
||||
u32 sw_if_index;
|
||||
};
|
||||
|
@ -1094,6 +1094,84 @@ static void *vl_api_snat_worker_dump_t_print
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static int snat_add_interface_address(snat_main_t *sm,
|
||||
u32 sw_if_index,
|
||||
int is_del);
|
||||
|
||||
static void
|
||||
vl_api_snat_add_del_interface_addr_t_handler
|
||||
(vl_api_snat_add_del_interface_addr_t * mp)
|
||||
{
|
||||
snat_main_t * sm = &snat_main;
|
||||
vl_api_snat_add_del_interface_addr_reply_t * rmp;
|
||||
u8 is_del = mp->is_add == 0;
|
||||
u32 sw_if_index = ntohl(mp->sw_if_index);
|
||||
int rv = 0;
|
||||
|
||||
VALIDATE_SW_IF_INDEX(mp);
|
||||
|
||||
rv = snat_add_interface_address (sm, sw_if_index, is_del);
|
||||
|
||||
BAD_SW_IF_INDEX_LABEL;
|
||||
|
||||
REPLY_MACRO(VL_API_SNAT_ADD_DEL_INTERFACE_ADDR_REPLY);
|
||||
}
|
||||
|
||||
static void *vl_api_snat_add_del_interface_addr_t_print
|
||||
(vl_api_snat_add_del_interface_addr_t * mp, void *handle)
|
||||
{
|
||||
u8 * s;
|
||||
|
||||
s = format (0, "SCRIPT: snat_add_del_interface_addr ");
|
||||
s = format (s, "sw_if_index %d %s",
|
||||
clib_host_to_net_u32(mp->sw_if_index),
|
||||
mp->is_add ? "" : "del");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
static void
|
||||
send_snat_interface_addr_details
|
||||
(u32 sw_if_index, unix_shared_memory_queue_t * q, u32 context)
|
||||
{
|
||||
vl_api_snat_interface_addr_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_INTERFACE_ADDR_DETAILS+sm->msg_id_base);
|
||||
rmp->sw_if_index = ntohl (sw_if_index);
|
||||
rmp->context = context;
|
||||
|
||||
vl_msg_api_send_shmem (q, (u8 *) & rmp);
|
||||
}
|
||||
|
||||
static void
|
||||
vl_api_snat_interface_addr_dump_t_handler
|
||||
(vl_api_snat_interface_addr_dump_t * mp)
|
||||
{
|
||||
unix_shared_memory_queue_t *q;
|
||||
snat_main_t * sm = &snat_main;
|
||||
u32 * i;
|
||||
|
||||
q = vl_api_client_index_to_input_queue (mp->client_index);
|
||||
if (q == 0)
|
||||
return;
|
||||
|
||||
vec_foreach (i, sm->auto_add_sw_if_indices)
|
||||
send_snat_interface_addr_details(*i, q, mp->context);
|
||||
}
|
||||
|
||||
static void *vl_api_snat_interface_addr_dump_t_print
|
||||
(vl_api_snat_interface_addr_dump_t *mp, void * handle)
|
||||
{
|
||||
u8 *s;
|
||||
|
||||
s = format (0, "SCRIPT: snat_interface_addr_dump ");
|
||||
|
||||
FINISH;
|
||||
}
|
||||
|
||||
/* List of message types that this plugin understands */
|
||||
#define foreach_snat_plugin_api_msg \
|
||||
_(SNAT_ADD_ADDRESS_RANGE, snat_add_address_range) \
|
||||
@ -1105,7 +1183,9 @@ _(SNAT_SHOW_CONFIG, snat_show_config) \
|
||||
_(SNAT_ADDRESS_DUMP, snat_address_dump) \
|
||||
_(SNAT_INTERFACE_DUMP, snat_interface_dump) \
|
||||
_(SNAT_SET_WORKERS, snat_set_workers) \
|
||||
_(SNAT_WORKER_DUMP, snat_worker_dump)
|
||||
_(SNAT_WORKER_DUMP, snat_worker_dump) \
|
||||
_(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr) \
|
||||
_(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_dump)
|
||||
|
||||
/* Set up the API message handling tables */
|
||||
static clib_error_t *
|
||||
@ -1840,7 +1920,7 @@ show_snat_command_fn (vlib_main_t * vm,
|
||||
snat_address_t * ap;
|
||||
vnet_main_t *vnm = vnet_get_main();
|
||||
snat_main_per_thread_data_t *tsm;
|
||||
u32 users_num = 0, sessions_num = 0, *worker;
|
||||
u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
|
||||
uword j = 0;
|
||||
|
||||
if (unformat (input, "detail"))
|
||||
@ -1870,6 +1950,16 @@ show_snat_command_fn (vlib_main_t * vm,
|
||||
i->is_inside ? "in" : "out");
|
||||
}));
|
||||
|
||||
if (vec_len (sm->auto_add_sw_if_indices))
|
||||
{
|
||||
vlib_cli_output (vm, "SNAT pool addresses interfaces:");
|
||||
vec_foreach (sw_if_index, sm->auto_add_sw_if_indices)
|
||||
{
|
||||
vlib_cli_output (vm, "%U", format_vnet_sw_interface_name, vnm,
|
||||
vnet_get_sw_interface (vnm, *sw_if_index));
|
||||
}
|
||||
}
|
||||
|
||||
vec_foreach (ap, sm->addresses)
|
||||
{
|
||||
u8 * s = format (0, "");
|
||||
@ -2011,7 +2101,9 @@ snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
|
||||
}
|
||||
|
||||
|
||||
static int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index)
|
||||
static int snat_add_interface_address (snat_main_t *sm,
|
||||
u32 sw_if_index,
|
||||
int is_del)
|
||||
{
|
||||
ip4_main_t * ip4_main = sm->ip4_main;
|
||||
ip4_address_t * first_int_addr;
|
||||
@ -2023,9 +2115,24 @@ static int snat_add_interface_address (snat_main_t *sm, u32 sw_if_index)
|
||||
for (i = 0; i < vec_len(sm->auto_add_sw_if_indices); i++)
|
||||
{
|
||||
if (sm->auto_add_sw_if_indices[i] == sw_if_index)
|
||||
return 0;
|
||||
{
|
||||
if (is_del)
|
||||
{
|
||||
/* if have address remove it */
|
||||
if (first_int_addr)
|
||||
(void) snat_del_address (sm, first_int_addr[0]);
|
||||
vec_del1(sm->auto_add_sw_if_indices, i);
|
||||
}
|
||||
else
|
||||
return VNET_API_ERROR_VALUE_EXIST;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_del)
|
||||
return VNET_API_ERROR_NO_SUCH_ENTRY;
|
||||
|
||||
/* add to the auto-address list */
|
||||
vec_add1(sm->auto_add_sw_if_indices, sw_if_index);
|
||||
|
||||
@ -2045,6 +2152,7 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
|
||||
unformat_input_t _line_input, *line_input = &_line_input;
|
||||
u32 sw_if_index;
|
||||
int rv;
|
||||
int is_del = 0;
|
||||
|
||||
/* Get a line of input. */
|
||||
if (!unformat_user (input, unformat_line_input, line_input))
|
||||
@ -2055,12 +2163,14 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
|
||||
if (unformat (line_input, "%U", unformat_vnet_sw_interface,
|
||||
sm->vnet_main, &sw_if_index))
|
||||
;
|
||||
else if (unformat (line_input, "del"))
|
||||
is_del = 1;
|
||||
else
|
||||
return clib_error_return (0, "unknown input '%U'",
|
||||
format_unformat_error, line_input);
|
||||
}
|
||||
|
||||
rv = snat_add_interface_address (sm, sw_if_index);
|
||||
rv = snat_add_interface_address (sm, sw_if_index, is_del);
|
||||
|
||||
switch (rv)
|
||||
{
|
||||
@ -2076,6 +2186,6 @@ snat_add_interface_address_command_fn (vlib_main_t * vm,
|
||||
|
||||
VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {
|
||||
.path = "snat add interface address",
|
||||
.short_help = "snat add interface address <interface>",
|
||||
.short_help = "snat add interface address <interface> [del]",
|
||||
.function = snat_add_interface_address_command_fn,
|
||||
};
|
||||
|
@ -61,7 +61,8 @@ snat_test_main_t snat_test_main;
|
||||
_(snat_add_address_range_reply) \
|
||||
_(snat_interface_add_del_feature_reply) \
|
||||
_(snat_add_static_mapping_reply) \
|
||||
_(snat_set_workers_reply)
|
||||
_(snat_set_workers_reply) \
|
||||
_(snat_add_del_interface_addr_reply)
|
||||
|
||||
#define _(n) \
|
||||
static void vl_api_##n##_t_handler \
|
||||
@ -94,7 +95,10 @@ _(SNAT_SHOW_CONFIG_REPLY, snat_show_config_reply) \
|
||||
_(SNAT_ADDRESS_DETAILS, snat_address_details) \
|
||||
_(SNAT_INTERFACE_DETAILS, snat_interface_details) \
|
||||
_(SNAT_SET_WORKERS_REPLY, snat_set_workers_reply) \
|
||||
_(SNAT_WORKER_DETAILS, snat_worker_details)
|
||||
_(SNAT_WORKER_DETAILS, snat_worker_details) \
|
||||
_(SNAT_ADD_DEL_INTERFACE_ADDR_REPLY, \
|
||||
snat_add_del_interface_addr_reply) \
|
||||
_(SNAT_INTERFACE_ADDR_DETAILS, snat_interface_addr_details)
|
||||
|
||||
/* M: construct, but don't yet send a message */
|
||||
#define M(T,t) \
|
||||
@ -539,6 +543,80 @@ static int api_snat_worker_dump(vat_main_t * vam)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int api_snat_add_del_interface_addr (vat_main_t * vam)
|
||||
{
|
||||
snat_test_main_t * sm = &snat_test_main;
|
||||
unformat_input_t * i = vam->input;
|
||||
f64 timeout;
|
||||
vl_api_snat_add_del_interface_addr_t * mp;
|
||||
u32 sw_if_index;
|
||||
u8 sw_if_index_set = 0;
|
||||
u8 is_add = 1;
|
||||
|
||||
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
|
||||
sw_if_index_set = 1;
|
||||
else if (unformat (i, "sw_if_index %d", &sw_if_index))
|
||||
sw_if_index_set = 1;
|
||||
else if (unformat (i, "del"))
|
||||
is_add = 0;
|
||||
else
|
||||
{
|
||||
clib_warning("unknown input '%U'", format_unformat_error, i);
|
||||
return -99;
|
||||
}
|
||||
}
|
||||
|
||||
if (sw_if_index_set == 0)
|
||||
{
|
||||
errmsg ("interface / sw_if_index required\n");
|
||||
return -99;
|
||||
}
|
||||
|
||||
M(SNAT_ADD_DEL_INTERFACE_ADDR, snat_add_del_interface_addr);
|
||||
mp->sw_if_index = ntohl(sw_if_index);
|
||||
mp->is_add = is_add;
|
||||
|
||||
S; W;
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vl_api_snat_interface_addr_details_t_handler
|
||||
(vl_api_snat_interface_addr_details_t *mp)
|
||||
{
|
||||
snat_test_main_t * sm = &snat_test_main;
|
||||
vat_main_t *vam = sm->vat_main;
|
||||
|
||||
fformat (vam->ofp, "sw_if_index %d\n", ntohl (mp->sw_if_index));
|
||||
}
|
||||
|
||||
static int api_snat_interface_addr_dump(vat_main_t * vam)
|
||||
{
|
||||
snat_test_main_t * sm = &snat_test_main;
|
||||
f64 timeout;
|
||||
vl_api_snat_interface_addr_dump_t * mp;
|
||||
|
||||
if (vam->json_output)
|
||||
{
|
||||
clib_warning ("JSON output not supported for snat_address_dump");
|
||||
return -99;
|
||||
}
|
||||
|
||||
M(SNAT_INTERFACE_ADDR_DUMP, snat_interface_addr_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,
|
||||
* and that the data plane plugin processes
|
||||
@ -554,7 +632,10 @@ _(snat_static_mapping_dump, "") \
|
||||
_(snat_show_config, "") \
|
||||
_(snat_address_dump, "") \
|
||||
_(snat_interface_dump, "") \
|
||||
_(snat_worker_dump, "")
|
||||
_(snat_worker_dump, "") \
|
||||
_(snat_add_del_interface_addr, \
|
||||
"<intfc> | sw_if_index <id> [del]") \
|
||||
_(snat_interface_addr_dump, "")
|
||||
|
||||
void vat_api_hookup (vat_main_t *vam)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@ class TestSNAT(VppTestCase):
|
||||
cls.icmp_id_out = 6305
|
||||
cls.snat_addr = '10.0.0.3'
|
||||
|
||||
cls.create_pg_interfaces(range(7))
|
||||
cls.create_pg_interfaces(range(8))
|
||||
cls.interfaces = list(cls.pg_interfaces[0:4])
|
||||
|
||||
for i in cls.interfaces:
|
||||
@ -48,6 +48,8 @@ class TestSNAT(VppTestCase):
|
||||
i.admin_up()
|
||||
i.resolve_arp()
|
||||
|
||||
cls.pg7.admin_up()
|
||||
|
||||
except Exception:
|
||||
super(TestSNAT, cls).tearDownClass()
|
||||
raise
|
||||
@ -178,6 +180,10 @@ class TestSNAT(VppTestCase):
|
||||
"""
|
||||
Clear SNAT configuration.
|
||||
"""
|
||||
interfaces = self.vapi.snat_interface_addr_dump()
|
||||
for intf in interfaces:
|
||||
self.vapi.snat_add_interface_addr(intf.sw_if_index, is_add=0)
|
||||
|
||||
interfaces = self.vapi.snat_interface_dump()
|
||||
for intf in interfaces:
|
||||
self.vapi.snat_interface_add_del_feature(intf.sw_if_index,
|
||||
@ -623,6 +629,24 @@ class TestSNAT(VppTestCase):
|
||||
# verify number of translated packet
|
||||
self.pg1.get_capture(pkts_num)
|
||||
|
||||
def test_interface_addr(self):
|
||||
""" Acquire SNAT addresses from interface """
|
||||
self.vapi.snat_add_interface_addr(self.pg7.sw_if_index)
|
||||
|
||||
# no address in NAT pool
|
||||
adresses = self.vapi.snat_address_dump()
|
||||
self.assertEqual(0, len(adresses))
|
||||
|
||||
# configure interface address and check NAT address pool
|
||||
self.pg7.config_ip4()
|
||||
adresses = self.vapi.snat_address_dump()
|
||||
self.assertEqual(1, len(adresses))
|
||||
|
||||
# remove interface address and check NAT address pool
|
||||
self.pg7.unconfig_ip4()
|
||||
adresses = self.vapi.snat_address_dump()
|
||||
self.assertEqual(0, len(adresses))
|
||||
|
||||
def tearDown(self):
|
||||
super(TestSNAT, self).tearDown()
|
||||
if not self.vpp_dead:
|
||||
|
@ -916,6 +916,24 @@ class VppPapiProvider(object):
|
||||
"""
|
||||
return self.api(self.papi.snat_show_config, {})
|
||||
|
||||
def snat_add_interface_addr(
|
||||
self,
|
||||
sw_if_index,
|
||||
is_add=1):
|
||||
"""Add/del S-NAT address from interface
|
||||
|
||||
:param sw_if_index: Software index of the interface
|
||||
:param is_add: 1 if add, 0 if delete (Default value = 1)
|
||||
"""
|
||||
return self.api(self.papi.snat_add_del_interface_addr,
|
||||
{'is_add': is_add, 'sw_if_index': sw_if_index})
|
||||
|
||||
def snat_interface_addr_dump(self):
|
||||
"""Dump S-NAT addresses interfaces
|
||||
:return: Dictionary of S-NAT addresses interfaces
|
||||
"""
|
||||
return self.api(self.papi.snat_interface_addr_dump, {})
|
||||
|
||||
def control_ping(self):
|
||||
self.api(self.papi.control_ping)
|
||||
|
||||
|
Reference in New Issue
Block a user