aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2017-11-08 01:59:38 -0800
committerOle Trøan <otroan@employees.org>2017-11-08 11:01:46 +0000
commit0938dcf192d203dcbe89d2819d3819d2f93408bf (patch)
tree1e3044664b7a3e84bdf0bc353b366916d9411f29
parent2ea2e423a95d497b97b858ebadc0b6aca1027e66 (diff)
NAT64 to use IPv4 address from interface (VPP-1051)
Change-Id: I326429c31dea6958a342ee152ef86cb975f4b12c Signed-off-by: Matus Fabian <matfabia@cisco.com>
-rw-r--r--src/plugins/nat/nat.api14
-rw-r--r--src/plugins/nat/nat64.c82
-rw-r--r--src/plugins/nat/nat64.h14
-rw-r--r--src/plugins/nat/nat64_cli.c68
-rw-r--r--src/plugins/nat/nat_api.c39
-rw-r--r--test/test_nat.py21
-rw-r--r--test/vpp_papi_provider.py12
7 files changed, 249 insertions, 1 deletions
diff --git a/src/plugins/nat/nat.api b/src/plugins/nat/nat.api
index d8fdf7283cf..9a000d5611f 100644
--- a/src/plugins/nat/nat.api
+++ b/src/plugins/nat/nat.api
@@ -1649,6 +1649,20 @@ define nat64_prefix_details {
u32 vrf_id;
};
+/** \brief Add/delete NAT64 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
+*/
+autoreply define nat64_add_del_interface_addr {
+ u32 client_index;
+ u32 context;
+ u8 is_add;
+ u8 is_inside;
+ u32 sw_if_index;
+};
+
/*
* DS-Lite APIs
diff --git a/src/plugins/nat/nat64.c b/src/plugins/nat/nat64.c
index 952ca8fb11b..936ea9e9988 100644
--- a/src/plugins/nat/nat64.c
+++ b/src/plugins/nat/nat64.c
@@ -47,12 +47,47 @@ static u8 well_known_prefix[] = {
/* *INDENT-ON* */
+static void
+nat64_ip4_add_del_interface_address_cb (ip4_main_t * im, uword opaque,
+ u32 sw_if_index,
+ ip4_address_t * address,
+ u32 address_length,
+ u32 if_address_index, u32 is_delete)
+{
+ nat64_main_t *nm = &nat64_main;
+ int i, j;
+
+ for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
+ {
+ if (sw_if_index == nm->auto_add_sw_if_indices[i])
+ {
+ if (!is_delete)
+ {
+ /* Don't trip over lease renewal, static config */
+ for (j = 0; j < vec_len (nm->addr_pool); j++)
+ if (nm->addr_pool[j].addr.as_u32 == address->as_u32)
+ return;
+
+ (void) nat64_add_del_pool_addr (address, ~0, 1);
+ return;
+ }
+ else
+ {
+ (void) nat64_add_del_pool_addr (address, ~0, 0);
+ return;
+ }
+ }
+ }
+}
+
clib_error_t *
nat64_init (vlib_main_t * vm)
{
nat64_main_t *nm = &nat64_main;
clib_error_t *error = 0;
vlib_thread_main_t *tm = vlib_get_thread_main ();
+ ip4_add_del_interface_address_callback_t cb4;
+ ip4_main_t *im = &ip4_main;
nm->is_disabled = 0;
@@ -75,6 +110,12 @@ nat64_init (vlib_main_t * vm)
nm->tcp_est_timeout = SNAT_TCP_ESTABLISHED_TIMEOUT;
nm->tcp_incoming_syn_timeout = SNAT_TCP_INCOMING_SYN;
+ /* Set up the interface address add/del callback */
+ cb4.function = nat64_ip4_add_del_interface_address_cb;
+ cb4.function_opaque = 0;
+ vec_add1 (im->add_del_interface_address_callbacks, cb4);
+ nm->ip4_main = im;
+
error:
return error;
}
@@ -163,6 +204,47 @@ nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx)
}
int
+nat64_add_interface_address (u32 sw_if_index, int is_add)
+{
+ nat64_main_t *nm = &nat64_main;
+ ip4_main_t *ip4_main = nm->ip4_main;
+ ip4_address_t *first_int_addr;
+ int i;
+
+ first_int_addr = ip4_interface_first_address (ip4_main, sw_if_index, 0);
+
+ for (i = 0; i < vec_len (nm->auto_add_sw_if_indices); i++)
+ {
+ if (nm->auto_add_sw_if_indices[i] == sw_if_index)
+ {
+ if (is_add)
+ return VNET_API_ERROR_VALUE_EXIST;
+ else
+ {
+ /* if have address remove it */
+ if (first_int_addr)
+ (void) nat64_add_del_pool_addr (first_int_addr, ~0, 0);
+
+ vec_del1 (nm->auto_add_sw_if_indices, i);
+ return 0;
+ }
+ }
+ }
+
+ if (!is_add)
+ return VNET_API_ERROR_NO_SUCH_ENTRY;
+
+ /* add to the auto-address list */
+ vec_add1 (nm->auto_add_sw_if_indices, sw_if_index);
+
+ /* If the address is already bound - or static - add it now */
+ if (first_int_addr)
+ (void) nat64_add_del_pool_addr (first_int_addr, ~0, 1);
+
+ return 0;
+}
+
+int
nat64_add_del_interface (u32 sw_if_index, u8 is_inside, u8 is_add)
{
nat64_main_t *nm = &nat64_main;
diff --git a/src/plugins/nat/nat64.h b/src/plugins/nat/nat64.h
index 68224cab013..118076705cc 100644
--- a/src/plugins/nat/nat64.h
+++ b/src/plugins/nat/nat64.h
@@ -55,6 +55,9 @@ typedef struct
/** Address pool vector */
snat_address_t *addr_pool;
+ /** sw_if_indices whose interface addresses should be auto-added */
+ u32 *auto_add_sw_if_indices;
+
/** Pref64 vector */
nat64_prefix_t *pref64;
@@ -70,6 +73,7 @@ typedef struct
u8 is_disabled;
+ ip4_main_t *ip4_main;
snat_main_t *sm;
} nat64_main_t;
@@ -103,6 +107,16 @@ typedef int (*nat64_pool_addr_walk_fn_t) (snat_address_t * addr, void *ctx);
void nat64_pool_addr_walk (nat64_pool_addr_walk_fn_t fn, void *ctx);
/**
+ * @brief NAT64 pool address from specific (DHCP addressed) interface.
+ *
+ * @param sw_if_index Index of the interface.
+ * @param is_add 1 if add, 0 if delete.
+ *
+ * @returns 0 on success, non-zero value otherwise.
+ */
+int nat64_add_interface_address (u32 sw_if_index, int is_add);
+
+/**
* @brief Enable/disable NAT64 feature on the interface.
*
* @param sw_if_index Index of the interface.
diff --git a/src/plugins/nat/nat64_cli.c b/src/plugins/nat/nat64_cli.c
index 7fea6bbb983..3e15beeee3b 100644
--- a/src/plugins/nat/nat64_cli.c
+++ b/src/plugins/nat/nat64_cli.c
@@ -807,6 +807,61 @@ nat64_show_prefix_command_fn (vlib_main_t * vm, unformat_input_t * input,
return 0;
}
+static clib_error_t *
+nat64_add_interface_address_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ nat64_main_t *nm = &nat64_main;
+ vnet_main_t *vnm = vnet_get_main ();
+ unformat_input_t _line_input, *line_input = &_line_input;
+ u32 sw_if_index;
+ int rv;
+ int is_add = 1;
+ clib_error_t *error = 0;
+
+ if (nm->is_disabled)
+ return clib_error_return (0,
+ "NAT64 disabled, multi thread not supported");
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat
+ (line_input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index))
+ ;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ else
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ rv = nat64_add_interface_address (sw_if_index, is_add);
+
+ switch (rv)
+ {
+ case VNET_API_ERROR_NO_SUCH_ENTRY:
+ error = clib_error_return (0, "entry not exist");
+ break;
+ case VNET_API_ERROR_VALUE_EXIST:
+ error = clib_error_return (0, "entry exist");
+ break;
+ default:
+ break;
+ }
+
+done:
+ unformat_free (line_input);
+
+ return error;
+}
+
/* *INDENT-OFF* */
/*?
@@ -1017,6 +1072,19 @@ VLIB_CLI_COMMAND (show_nat64_prefix_command, static) = {
.function = nat64_show_prefix_command_fn,
};
+/*?
+ * @cliexpar
+ * @cliexstart{nat64 add interface address}
+ * Add/delete NAT64 pool address from specific (DHCP addressed) interface.
+ * To add NAT64 pool address from specific interface use:
+ * vpp# nat64 add interface address GigabitEthernet0/8/0
+ * @cliexend
+?*/
+VLIB_CLI_COMMAND (nat64_add_interface_address_command, static) = {
+ .path = "nat64 add interface address",
+ .short_help = "nat64 add interface address <interface> [del]",
+ .function = nat64_add_interface_address_command_fn,
+};
/* *INDENT-ON* */
/*
diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c
index 548a9e03bc4..127a2b80bbf 100644
--- a/src/plugins/nat/nat_api.c
+++ b/src/plugins/nat/nat_api.c
@@ -3431,6 +3431,44 @@ vl_api_nat64_prefix_dump_t_print (vl_api_nat64_prefix_dump_t * mp,
FINISH;
}
+static void
+ vl_api_nat64_add_del_interface_addr_t_handler
+ (vl_api_nat64_add_del_interface_addr_t * mp)
+{
+ nat64_main_t *nm = &nat64_main;
+ snat_main_t *sm = &snat_main;
+ vl_api_nat64_add_del_interface_addr_reply_t *rmp;
+ u32 sw_if_index = ntohl (mp->sw_if_index);
+ int rv = 0;
+
+ if (nm->is_disabled)
+ {
+ rv = VNET_API_ERROR_FEATURE_DISABLED;
+ goto send_reply;
+ }
+
+ VALIDATE_SW_IF_INDEX (mp);
+
+ rv = nat64_add_interface_address (sw_if_index, mp->is_add);
+
+ BAD_SW_IF_INDEX_LABEL;
+send_reply:
+ REPLY_MACRO (VL_API_NAT64_ADD_DEL_INTERFACE_ADDR_REPLY);
+}
+
+static void *vl_api_nat64_add_del_interface_addr_t_print
+ (vl_api_nat64_add_del_interface_addr_t * mp, void *handle)
+{
+ u8 *s;
+
+ s = format (0, "SCRIPT: nat64_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;
+}
+
/***************/
/*** DS-Lite ***/
/***************/
@@ -3587,6 +3625,7 @@ _(NAT64_GET_TIMEOUTS, nat64_get_timeouts) \
_(NAT64_ST_DUMP, nat64_st_dump) \
_(NAT64_ADD_DEL_PREFIX, nat64_add_del_prefix) \
_(NAT64_PREFIX_DUMP, nat64_prefix_dump) \
+_(NAT64_ADD_DEL_INTERFACE_ADDR, nat64_add_del_interface_addr) \
_(DSLITE_ADD_DEL_POOL_ADDR_RANGE, dslite_add_del_pool_addr_range) \
_(DSLITE_SET_AFTR_ADDR, dslite_set_aftr_addr)
diff --git a/test/test_nat.py b/test/test_nat.py
index 3c002bb8eca..76c52828ad9 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -3428,7 +3428,7 @@ class TestNAT64(MethodHolder):
cls.vrf1_nat_addr_n = socket.inet_pton(socket.AF_INET,
cls.vrf1_nat_addr)
- cls.create_pg_interfaces(range(4))
+ cls.create_pg_interfaces(range(5))
cls.ip6_interfaces = list(cls.pg_interfaces[0:1])
cls.ip6_interfaces.append(cls.pg_interfaces[2])
cls.ip4_interfaces = list(cls.pg_interfaces[1:2])
@@ -4337,6 +4337,25 @@ class TestNAT64(MethodHolder):
self.assertEqual(p[TCP].dport, self.tcp_port_in)
self.assertEqual(data, p[Raw].load)
+ def test_interface_addr(self):
+ """ Acquire NAT64 pool addresses from interface """
+ self.vapi.nat64_add_interface_addr(self.pg4.sw_if_index)
+
+ # no address in NAT64 pool
+ adresses = self.vapi.nat44_address_dump()
+ self.assertEqual(0, len(adresses))
+
+ # configure interface address and check NAT64 address pool
+ self.pg4.config_ip4()
+ addresses = self.vapi.nat64_pool_addr_dump()
+ self.assertEqual(len(addresses), 1)
+ self.assertEqual(addresses[0].address, self.pg4.local_ip4n)
+
+ # remove interface address and check NAT64 address pool
+ self.pg4.unconfig_ip4()
+ addresses = self.vapi.nat64_pool_addr_dump()
+ self.assertEqual(0, len(adresses))
+
def nat64_get_ses_num(self):
"""
Return number of active NAT64 sessions.
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 63f938376ae..495db95052e 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -1723,6 +1723,18 @@ class VppPapiProvider(object):
"""
return self.api(self.papi.nat64_prefix_dump, {})
+ def nat64_add_interface_addr(
+ self,
+ sw_if_index,
+ is_add=1):
+ """Add/del NAT64 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.nat64_add_del_interface_addr,
+ {'is_add': is_add, 'sw_if_index': sw_if_index})
+
def dslite_set_aftr_addr(self, ip6, ip4):
"""Set DS-Lite AFTR addresses