aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/nat
diff options
context:
space:
mode:
authorFilip Varga <fivarga@cisco.com>2021-03-23 12:57:58 +0100
committerOle Tr�an <otroan@employees.org>2021-03-31 11:46:05 +0000
commited2ee5e57b0f65ac4a94aac84cb6c27468878ea4 (patch)
tree60ce5bb4f17bf57c12146c20db66cd19fdb233a4 /src/plugins/nat
parent7554aef84a8a406c9dae73a7445e8b97920a83b3 (diff)
nat: NAT66 plugin enable&disable calls update
Type: improvement Adding support for enable&disable calls (dynamic plugin configuration). API (nat66_plugin_enable_disable) and CLI (nat66 plugin enable/nat66 plugin disable) with support for outside_vrf id configuration. Change-Id: I5637ff1621d6662adc3b7c6f7f8176d84a4b492b Signed-off-by: Filip Varga <fivarga@cisco.com>
Diffstat (limited to 'src/plugins/nat')
-rw-r--r--src/plugins/nat/nat66/nat66.api14
-rw-r--r--src/plugins/nat/nat66/nat66.c140
-rw-r--r--src/plugins/nat/nat66/nat66.h10
-rw-r--r--src/plugins/nat/nat66/nat66_api.c30
-rw-r--r--src/plugins/nat/nat66/nat66_cli.c102
-rw-r--r--src/plugins/nat/test/test_nat66.py55
6 files changed, 258 insertions, 93 deletions
diff --git a/src/plugins/nat/nat66/nat66.api b/src/plugins/nat/nat66/nat66.api
index bbadf07184a..29425c09ce5 100644
--- a/src/plugins/nat/nat66/nat66.api
+++ b/src/plugins/nat/nat66/nat66.api
@@ -18,6 +18,20 @@ import "vnet/ip/ip_types.api";
import "vnet/interface_types.api";
import "plugins/nat/lib/nat_types.api";
+
+/** \brief Enable/disable NAT66 plugin
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+ @param outside_vrf - outside vrf id
+ @param enable - true if enable, false if disable
+*/
+autoreply define nat66_plugin_enable_disable {
+ u32 client_index;
+ u32 context;
+ u32 outside_vrf;
+ bool enable;
+};
+
/** \brief Enable/disable NAT66 feature on the interface
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/plugins/nat/nat66/nat66.c b/src/plugins/nat/nat66/nat66.c
index a8de3f6e0fa..ff8cace615d 100644
--- a/src/plugins/nat/nat66/nat66.c
+++ b/src/plugins/nat/nat66/nat66.c
@@ -17,16 +17,12 @@
* @brief NAT66 implementation
*/
+#include <nat/nat66/nat66.h>
#include <vpp/app/version.h>
#include <vnet/plugin/plugin.h>
-#include <nat/nat66/nat66.h>
-#include <vnet/fib/fib_table.h>
#include <vnet/ip/reass/ip6_sv_reass.h>
nat66_main_t nat66_main;
-fib_source_t nat_fib_src_hi;
-
-/* *INDENT-OFF* */
/* Hook up input features */
VNET_FEATURE_INIT (nat66_in2out, static) = {
@@ -42,39 +38,109 @@ VNET_FEATURE_INIT (nat66_out2in, static) = {
.runs_after = VNET_FEATURES ("ip6-sv-reassembly-feature"),
};
-/* *INDENT-ON* */
-
clib_error_t *nat66_plugin_api_hookup (vlib_main_t * vm);
+
+#define fail_if_enabled() \
+ do \
+ { \
+ nat66_main_t *nm = &nat66_main; \
+ if (PREDICT_FALSE (nm->enabled)) \
+ { \
+ nat66_elog_warn ("plugin enabled"); \
+ return 1; \
+ } \
+ } \
+ while (0)
+
+#define fail_if_disabled() \
+ do \
+ { \
+ nat66_main_t *nm = &nat66_main; \
+ if (PREDICT_FALSE (!nm->enabled)) \
+ { \
+ nat66_elog_warn ("plugin disabled"); \
+ return 1; \
+ } \
+ } \
+ while (0)
+
static clib_error_t *
nat66_init (vlib_main_t * vm)
{
nat66_main_t *nm = &nat66_main;
- vlib_node_t *node;
+
+ clib_memset (nm, 0, sizeof (*nm));
+
+ nm->session_counters.name = "session counters";
+ nm->in2out_packets.name = "in2out";
+ nm->in2out_packets.stat_segment_name = "/nat64/in2out";
+ nm->out2in_packets.name = "out2in";
+ nm->out2in_packets.stat_segment_name = "/nat64/out2in";
+
+ nm->nat_fib_src_hi = fib_source_allocate ("nat66-hi", FIB_SOURCE_PRIORITY_HI,
+ FIB_SOURCE_BH_SIMPLE);
+ return nat66_plugin_api_hookup (vm);
+}
+
+int
+nat66_plugin_enable (u32 outside_vrf)
+{
+ nat66_main_t *nm = &nat66_main;
+
u32 static_mapping_buckets = 1024;
uword static_mapping_memory_size = 64 << 20;
- node = vlib_get_node_by_name (vm, (u8 *) "nat66-in2out");
- nm->in2out_node_index = node->index;
-
- node = vlib_get_node_by_name (vm, (u8 *) "nat66-out2in");
- nm->out2in_node_index = node->index;
+ fail_if_enabled ();
clib_bihash_init_24_8 (&nm->sm_l, "nat66-static-map-by-local",
static_mapping_buckets, static_mapping_memory_size);
clib_bihash_init_24_8 (&nm->sm_e, "nat66-static-map-by-external",
static_mapping_buckets, static_mapping_memory_size);
- nm->session_counters.name = "session counters";
+ nm->outside_vrf_id = outside_vrf;
+ nm->outside_fib_index = fib_table_find_or_create_and_lock (
+ FIB_PROTOCOL_IP6, outside_vrf, nm->nat_fib_src_hi);
+ nm->enabled = 1;
+ return 0;
+}
- nat_fib_src_hi = fib_source_allocate ("nat66-hi",
- FIB_SOURCE_PRIORITY_HI,
- FIB_SOURCE_BH_SIMPLE);
+int
+nat66_plugin_disable ()
+{
+ nat66_main_t *nm = &nat66_main;
+ nat66_interface_t *i, *temp;
+ int error = 0;
- nm->in2out_packets.name = "in2out";
- nm->in2out_packets.stat_segment_name = "/nat64/in2out";
- nm->out2in_packets.name = "out2in";
- nm->out2in_packets.stat_segment_name = "/nat64/out2in";
- return nat66_plugin_api_hookup (vm);
+ temp = pool_dup (nm->interfaces);
+ pool_foreach (i, temp)
+ {
+ if (nat66_interface_is_inside (i))
+ error = nat66_interface_add_del (i->sw_if_index, 1, 0);
+
+ if (nat66_interface_is_outside (i))
+ error = nat66_interface_add_del (i->sw_if_index, 0, 0);
+
+ if (error)
+ {
+ nat66_elog_warn ("error occurred while removing interface");
+ }
+ }
+ pool_free (temp);
+ pool_free (nm->interfaces);
+
+ pool_free (nm->sm);
+ clib_bihash_free_24_8 (&nm->sm_l);
+ clib_bihash_free_24_8 (&nm->sm_e);
+
+ nm->interfaces = 0;
+ nm->sm = 0;
+
+ vlib_clear_combined_counters (&nm->session_counters);
+ vlib_clear_simple_counters (&nm->in2out_packets);
+ vlib_clear_simple_counters (&nm->out2in_packets);
+
+ nm->enabled = 0;
+ return error;
}
static void
@@ -93,7 +159,8 @@ nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
nat66_interface_t *interface = 0, *i;
const char *feature_name;
- /* *INDENT-OFF* */
+ fail_if_disabled ();
+
pool_foreach (i, nm->interfaces)
{
if (i->sw_if_index == sw_if_index)
@@ -102,7 +169,6 @@ nat66_interface_add_del (u32 sw_if_index, u8 is_inside, u8 is_add)
break;
}
}
- /* *INDENT-ON* */
if (is_add)
{
@@ -138,13 +204,11 @@ nat66_interfaces_walk (nat66_interface_walk_fn_t fn, void *ctx)
nat66_main_t *nm = &nat66_main;
nat66_interface_t *i = 0;
- /* *INDENT-OFF* */
pool_foreach (i, nm->interfaces)
{
if (fn (i, ctx))
break;
}
- /* *INDENT-ON* */
}
nat66_static_mapping_t *
@@ -182,6 +246,8 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
clib_bihash_kv_24_8_t kv, value;
u32 fib_index = fib_table_find (FIB_PROTOCOL_IP6, vrf_id);
+ fail_if_disabled ();
+
sm_key.addr.as_u64[0] = l_addr->as_u64[0];
sm_key.addr.as_u64[1] = l_addr->as_u64[1];
sm_key.fib_index = fib_index;
@@ -199,7 +265,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
return VNET_API_ERROR_VALUE_EXIST;
fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6, vrf_id,
- nat_fib_src_hi);
+ nm->nat_fib_src_hi);
pool_get (nm->sm, sm);
clib_memset (sm, 0, sizeof (*sm));
sm->l_addr.as_u64[0] = l_addr->as_u64[0];
@@ -243,7 +309,7 @@ nat66_static_mapping_add_del (ip6_address_t * l_addr, ip6_address_t * e_addr,
kv.key[2] = sm_key.as_u64[2];
if (clib_bihash_add_del_24_8 (&nm->sm_e, &kv, 0))
nat66_elog_warn ("nat66-static-map-by-external delete key failed");
- fib_table_unlock (sm->fib_index, FIB_PROTOCOL_IP6, nat_fib_src_hi);
+ fib_table_unlock (sm->fib_index, FIB_PROTOCOL_IP6, nm->nat_fib_src_hi);
pool_put (nm->sm, sm);
}
@@ -256,29 +322,13 @@ nat66_static_mappings_walk (nat66_static_mapping_walk_fn_t fn, void *ctx)
nat66_main_t *nm = &nat66_main;
nat66_static_mapping_t *sm = 0;
- /* *INDENT-OFF* */
pool_foreach (sm, nm->sm)
{
if (fn (sm, ctx))
break;
}
- /* *INDENT-ON* */
-}
-
-/*static*/ void
-nat66_config (void)
-{
- nat66_main_t *nm = &nat66_main;
- u32 outside_ip6_vrf_id = 0;
-
- nm->outside_vrf_id = outside_ip6_vrf_id;
- nm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP6,
- outside_ip6_vrf_id,
- nat_fib_src_hi);
-
}
-/* *INDENT-OFF* */
VLIB_PLUGIN_REGISTER () =
{
.version = VPP_BUILD_VER,
@@ -287,8 +337,6 @@ VLIB_PLUGIN_REGISTER () =
VLIB_INIT_FUNCTION (nat66_init);
-/* *INDENT-ON* */
-
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/src/plugins/nat/nat66/nat66.h b/src/plugins/nat/nat66/nat66.h
index 42dd7ca0eb2..17a69234b44 100644
--- a/src/plugins/nat/nat66/nat66.h
+++ b/src/plugins/nat/nat66/nat66.h
@@ -20,6 +20,7 @@
#define __included_nat66_h__
#include <vnet/ip/ip.h>
+#include <vnet/fib/fib_table.h>
#include <vppinfra/bihash_24_8.h>
typedef struct
@@ -48,6 +49,7 @@ typedef struct
u32 sw_if_index;
u8 flags;
} nat66_interface_t;
+
#define NAT66_INTERFACE_FLAG_IS_INSIDE 1
#define NAT66_INTERFACE_FLAG_IS_OUTSIDE 2
#define nat66_interface_is_inside(i) i->flags & NAT66_INTERFACE_FLAG_IS_INSIDE
@@ -65,16 +67,16 @@ typedef struct
clib_bihash_24_8_t sm_e;
/** Session counters */
vlib_combined_counter_main_t session_counters;
- /** node index **/
- u32 in2out_node_index;
- u32 out2in_node_index;
u32 outside_vrf_id;
u32 outside_fib_index;
+ fib_source_t nat_fib_src_hi;
u16 msg_id_base;
u8 log_level;
+ u8 enabled;
+
vlib_simple_counter_main_t in2out_packets;
vlib_simple_counter_main_t out2in_packets;;
} nat66_main_t;
@@ -114,6 +116,8 @@ nat66_static_mapping_t *nat66_static_mapping_get (ip6_address_t * addr,
int nat66_static_mapping_add_del (ip6_address_t * l_addr,
ip6_address_t * e_addr, u32 vrf_id,
u8 is_add);
+int nat66_plugin_enable (u32 outside_vrf);
+int nat66_plugin_disable ();
#endif /* __included_nat66_h__ */
diff --git a/src/plugins/nat/nat66/nat66_api.c b/src/plugins/nat/nat66/nat66_api.c
index 2a2b3cc07ad..470c1fe48fa 100644
--- a/src/plugins/nat/nat66/nat66_api.c
+++ b/src/plugins/nat/nat66/nat66_api.c
@@ -23,9 +23,23 @@
#define REPLY_MSG_ID_BASE nm->msg_id_base
#include <vlibapi/api_helper_macros.h>
-/*************/
-/*** NAT66 ***/
-/*************/
+static void
+vl_api_nat66_plugin_enable_disable_t_handler (
+ vl_api_nat66_plugin_enable_disable_t *mp)
+{
+ nat66_main_t *nm = &nat66_main;
+ vl_api_nat66_plugin_enable_disable_reply_t *rmp;
+ int rv = 0;
+
+ if (mp->enable)
+ {
+ rv = nat66_plugin_enable (ntohl (mp->outside_vrf));
+ }
+ else
+ rv = nat66_plugin_disable ();
+
+ REPLY_MACRO (VL_API_NAT66_PLUGIN_ENABLE_DISABLE_REPLY);
+}
static void
vl_api_nat66_add_del_interface_t_handler (vl_api_nat66_add_del_interface_t *
@@ -96,6 +110,10 @@ static void
vl_api_nat66_interface_dump_t_handler (vl_api_nat66_interface_dump_t * mp)
{
vl_api_registration_t *rp;
+ nat66_main_t *nm = &nat66_main;
+
+ if (PREDICT_FALSE (!nm->enabled))
+ return;
rp = vl_api_client_index_to_registration (mp->client_index);
if (rp == 0)
@@ -145,6 +163,10 @@ vl_api_nat66_static_mapping_dump_t_handler (vl_api_nat66_static_mapping_dump_t
* mp)
{
vl_api_registration_t *rp;
+ nat66_main_t *nm = &nat66_main;
+
+ if (PREDICT_FALSE (!nm->enabled))
+ return;
rp = vl_api_client_index_to_registration (mp->client_index);
if (rp == 0)
@@ -167,8 +189,6 @@ clib_error_t *
nat66_plugin_api_hookup (vlib_main_t * vm)
{
nat66_main_t *nm = &nat66_main;
-
nm->msg_id_base = setup_message_id_table ();
-
return 0;
}
diff --git a/src/plugins/nat/nat66/nat66_cli.c b/src/plugins/nat/nat66/nat66_cli.c
index da963877c8a..4ba46cb0b75 100644
--- a/src/plugins/nat/nat66/nat66_cli.c
+++ b/src/plugins/nat/nat66/nat66_cli.c
@@ -21,12 +21,68 @@
#include <vnet/fib/fib_table.h>
static clib_error_t *
+nat66_enable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ nat66_main_t *nm = &nat66_main;
+ unformat_input_t _line_input, *line_input = &_line_input;
+ clib_error_t *error = 0;
+ u32 outside_vrf = 0;
+
+ if (nm->enabled)
+ return clib_error_return (0, "nat66 already enabled");
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ {
+ if (nat66_plugin_enable (outside_vrf) != 0)
+ return clib_error_return (0, "nat66 enable failed");
+ return 0;
+ }
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "outside-vrf %u", &outside_vrf))
+ ;
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ if (nat66_plugin_enable (outside_vrf) != 0)
+ error = clib_error_return (0, "nat66 enable failed");
+done:
+ unformat_free (line_input);
+ return error;
+}
+
+static clib_error_t *
+nat66_disable_command_fn (vlib_main_t *vm, unformat_input_t *input,
+ vlib_cli_command_t *cmd)
+{
+ nat66_main_t *nm = &nat66_main;
+ clib_error_t *error = 0;
+
+ if (!nm->enabled)
+ return clib_error_return (0, "nat66 already disabled");
+
+ if (nat66_plugin_disable () != 0)
+ error = clib_error_return (0, "nat66 disable failed");
+
+ return error;
+}
+
+static clib_error_t *
nat66_interface_feature_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
unformat_input_t _line_input, *line_input = &_line_input;
vnet_main_t *vnm = vnet_get_main ();
+ nat66_main_t *nm = &nat66_main;
clib_error_t *error = 0;
u32 sw_if_index;
u32 *inside_sw_if_indices = 0;
@@ -34,6 +90,9 @@ nat66_interface_feature_command_fn (vlib_main_t * vm,
u8 is_add = 1;
int i, rv;
+ if (!nm->enabled)
+ return clib_error_return (0, "nat66 disabled");
+
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
@@ -139,7 +198,6 @@ nat66_cli_interface_walk (nat66_interface_t * i, void *ctx)
{
vlib_main_t *vm = ctx;
vnet_main_t *vnm = vnet_get_main ();
-
vlib_cli_output (vm, " %U %s", format_vnet_sw_interface_name, vnm,
vnet_get_sw_interface (vnm, i->sw_if_index),
nat66_interface_is_inside (i) ? "in" : "out");
@@ -150,9 +208,11 @@ static clib_error_t *
nat66_show_interfaces_command_fn (vlib_main_t * vm, unformat_input_t * input,
vlib_cli_command_t * cmd)
{
+ nat66_main_t *nm = &nat66_main;
+ if (!nm->enabled)
+ return clib_error_return (0, "nat66 disabled");
vlib_cli_output (vm, "NAT66 interfaces:");
nat66_interfaces_walk (nat66_cli_interface_walk, vm);
-
return 0;
}
@@ -161,6 +221,7 @@ nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
+ nat66_main_t *nm = &nat66_main;
unformat_input_t _line_input, *line_input = &_line_input;
clib_error_t *error = 0;
u8 is_add = 1;
@@ -168,6 +229,9 @@ nat66_add_del_static_mapping_command_fn (vlib_main_t * vm,
u32 vrf_id = 0;
int rv;
+ if (!nm->enabled)
+ return clib_error_return (0, "nat66 disabled");
+
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
@@ -238,12 +302,44 @@ nat66_show_static_mappings_command_fn (vlib_main_t * vm,
unformat_input_t * input,
vlib_cli_command_t * cmd)
{
+ nat66_main_t *nm = &nat66_main;
+ if (!nm->enabled)
+ return clib_error_return (0, "nat66 disabled");
vlib_cli_output (vm, "NAT66 static mappings:");
nat66_static_mappings_walk (nat66_cli_static_mapping_walk, vm);
return 0;
}
-/* *INDENT-OFF* */
+/*?
+ * @cliexpar
+ * @cliexstart{nat66 enable}
+ * Enable NAT66 plugin
+ * To enable NAT66 plugin
+ * vpp# nat66 enable
+ * To enable NAT66 plugin with outside-vrf id 10
+ * vpp# nat66 enable outside-vrf 10
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat66_enable_command, static) = {
+ .path = "nat66 enable",
+ .short_help = "nat66 enable [outside-vrf <vrf-id>]",
+ .function = nat66_enable_command_fn,
+};
+
+/*?
+ * @cliexpar
+ * @cliexstart{nat66 disable}
+ * Disable NAT66 plugin
+ * To disable NAT66 plugin
+ * vpp# nat66 disable
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat66_disable_command, static) = {
+ .path = "nat66 disable",
+ .short_help = "nat66 disable",
+ .function = nat66_disable_command_fn,
+};
+
/*?
* @cliexpar
* @cliexstart{set interface nat66}
diff --git a/src/plugins/nat/test/test_nat66.py b/src/plugins/nat/test/test_nat66.py
index bd1b50b9ee2..acda72bcdf6 100644
--- a/src/plugins/nat/test/test_nat66.py
+++ b/src/plugins/nat/test/test_nat66.py
@@ -32,14 +32,7 @@ from vpp_neighbor import VppNeighbor
from vpp_papi import VppEnum
-class MethodHolder(VppTestCase):
- """ NAT create capture and verify method holder """
- @property
- def config_flags(self):
- return VppEnum.vl_api_nat_config_flags_t
-
-
-class TestNAT66(MethodHolder):
+class TestNAT66(VppTestCase):
""" NAT66 Test Cases """
@classmethod
@@ -47,7 +40,6 @@ class TestNAT66(MethodHolder):
super(TestNAT66, cls).setUpClass()
cls.nat_addr = 'fd01:ff::2'
-
cls.create_pg_interfaces(range(2))
cls.interfaces = list(cls.pg_interfaces)
@@ -56,9 +48,24 @@ class TestNAT66(MethodHolder):
i.config_ip6()
i.configure_ipv6_neighbors()
- @classmethod
- def tearDownClass(cls):
- super(TestNAT66, cls).tearDownClass()
+ @property
+ def config_flags(self):
+ return VppEnum.vl_api_nat_config_flags_t
+
+ def plugin_enable(self):
+ self.vapi.nat66_plugin_enable_disable(enable=1)
+
+ def plugin_disable(self):
+ self.vapi.nat66_plugin_enable_disable(enable=0)
+
+ def setUp(self):
+ super(TestNAT66, self).setUp()
+ self.plugin_enable()
+
+ def tearDown(self):
+ super(TestNAT66, self).tearDown()
+ if not self.vpp_dead:
+ self.plugin_disable()
def test_static(self):
""" 1:1 NAT66 test """
@@ -167,30 +174,6 @@ class TestNAT66(MethodHolder):
self.logger.error(ppp("Unexpected or invalid packet:", packet))
raise
- def clear_nat66(self):
- """
- Clear NAT66 configuration.
- """
- interfaces = self.vapi.nat66_interface_dump()
- for intf in interfaces:
- self.vapi.nat66_add_del_interface(is_add=0, flags=intf.flags,
- sw_if_index=intf.sw_if_index)
-
- static_mappings = self.vapi.nat66_static_mapping_dump()
- for sm in static_mappings:
- self.vapi.nat66_add_del_static_mapping(
- local_ip_address=sm.local_ip_address,
- external_ip_address=sm.external_ip_address, vrf_id=sm.vrf_id,
- is_add=0)
-
- def tearDown(self):
- super(TestNAT66, self).tearDown()
- self.clear_nat66()
-
- def show_commands_at_teardown(self):
- self.logger.info(self.vapi.cli("show nat66 interfaces"))
- self.logger.info(self.vapi.cli("show nat66 static mappings"))
-
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)