summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/snat/snat.api51
-rw-r--r--src/plugins/snat/snat.c122
-rw-r--r--src/plugins/snat/snat_test.c87
-rw-r--r--test/test_snat.py26
-rw-r--r--test/vpp_papi_provider.py18
5 files changed, 287 insertions, 17 deletions
diff --git a/src/plugins/snat/snat.api b/src/plugins/snat/snat.api
index a191eed5944..f046a9657e2 100644
--- a/src/plugins/snat/snat.api
+++ b/src/plugins/snat/snat.api
@@ -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;
+};
diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c
index 94e05078529..a1236cf74f4 100644
--- a/src/plugins/snat/snat.c
+++ b/src/plugins/snat/snat.c
@@ -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,
};
diff --git a/src/plugins/snat/snat_test.c b/src/plugins/snat/snat_test.c
index 2a003ba60c6..6f87d80379b 100644
--- a/src/plugins/snat/snat_test.c
+++ b/src/plugins/snat/snat_test.c
@@ -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)
{
diff --git a/test/test_snat.py b/test/test_snat.py
index d23becf5ce9..653496e2880 100644
--- a/test/test_snat.py
+++ b/test/test_snat.py
@@ -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:
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index b78e861347f..73d3b564001 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -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)