#include <vlibapi/api.h>
#include <snat/snat.h>
#include <snat/snat_ipfix_logging.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/ip4_fib.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
#include <vlibsocket/api.h>
+#include <vpp/app/version.h>
snat_main_t snat_main;
.runs_before = VNET_FEATURES ("ip4-lookup"),
};
-
-/*
- * This routine exists to convince the vlib plugin framework that
- * we haven't accidentally copied a random .dll into the plugin directory.
- *
- * Also collects global variable pointers passed from the vpp engine
- */
-
-clib_error_t *
-vlib_plugin_register (vlib_main_t * vm, vnet_plugin_handoff_t * h,
- int from_early_init)
-{
- snat_main_t * sm = &snat_main;
- clib_error_t * error = 0;
-
- sm->vlib_main = vm;
- sm->vnet_main = h->vnet_main;
- sm->ethernet_main = h->ethernet_main;
-
- return error;
-}
+/* *INDENT-OFF* */
+VLIB_PLUGIN_REGISTER () = {
+ .version = VPP_BUILD_VER,
+};
+/* *INDENT-ON* */
/*$$$$$ move to an installed header file */
#if (1 || CLIB_DEBUG > 0) /* "trust, but verify" */
#endif /* CLIB_DEBUG > 0 */
+/**
+ * @brief Add/del NAT address to FIB.
+ *
+ * Add the external NAT address to the FIB as receive entries. This ensures
+ * that VPP will reply to ARP for this address and we don't need to enable
+ * proxy ARP on the outside interface.
+ *
+ * @param addr IPv4 address.
+ * @param sw_if_index Interface.
+ * @param is_add If 0 delete, otherwise add.
+ */
+static void
+snat_add_del_addr_to_fib (ip4_address_t * addr, u32 sw_if_index, int is_add)
+{
+ fib_prefix_t prefix = {
+ .fp_len = 32,
+ .fp_proto = FIB_PROTOCOL_IP4,
+ .fp_addr = {
+ .ip4.as_u32 = addr->as_u32,
+ },
+ };
+ u32 fib_index = ip4_fib_table_get_index_for_sw_if_index(sw_if_index);
+
+ if (is_add)
+ fib_table_entry_update_one_path(fib_index,
+ &prefix,
+ FIB_SOURCE_PLUGIN_HI,
+ (FIB_ENTRY_FLAG_CONNECTED |
+ FIB_ENTRY_FLAG_LOCAL |
+ FIB_ENTRY_FLAG_EXCLUSIVE),
+ FIB_PROTOCOL_IP4,
+ NULL,
+ sw_if_index,
+ ~0,
+ 1,
+ NULL,
+ FIB_ROUTE_PATH_FLAG_NONE);
+ else
+ fib_table_entry_delete(fib_index,
+ &prefix,
+ FIB_SOURCE_PLUGIN_HI);
+}
+
void snat_add_address (snat_main_t *sm, ip4_address_t *addr)
{
snat_address_t * ap;
+ snat_interface_t *i;
/* Check if address already exists */
vec_foreach (ap, sm->addresses)
vec_add2 (sm->addresses, ap, 1);
ap->addr = *addr;
- clib_bitmap_alloc (ap->busy_port_bitmap, 65535);
+#define _(N, i, n, s) \
+ clib_bitmap_alloc (ap->busy_##n##_port_bitmap, 65535);
+ foreach_snat_protocol
+#undef _
+
+ /* Add external address to FIB */
+ pool_foreach (i, sm->interfaces,
+ ({
+ if (i->is_inside)
+ continue;
+
+ snat_add_del_addr_to_fib(addr, i->sw_if_index, 1);
+ break;
+ }));
}
static int is_snat_address_used_in_static_mapping (snat_main_t *sm,
u32 sw_if_index,
u16 e_port,
u32 vrf_id,
+ snat_protocol_t proto,
int addr_only,
int is_add)
{
rp->sw_if_index = sw_if_index;
rp->e_port = e_port;
rp->vrf_id = vrf_id;
+ rp->proto = proto;
rp->addr_only = addr_only;
rp->is_add = is_add;
}
*/
int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
u16 l_port, u16 e_port, u32 vrf_id, int addr_only,
- u32 sw_if_index, int is_add)
+ u32 sw_if_index, snat_protocol_t proto, int is_add)
{
snat_main_t * sm = &snat_main;
snat_static_mapping_t *m;
- snat_static_mapping_key_t m_key;
+ snat_session_key_t m_key;
clib_bihash_kv_8_8_t kv, value;
snat_address_t *a = 0;
u32 fib_index = ~0;
uword * p;
+ snat_interface_t *interface;
int i;
- /* If outside FIB index is not resolved yet */
- if (sm->outside_fib_index == ~0)
- {
- p = hash_get (sm->ip4_main->fib_index_by_table_id, sm->outside_vrf_id);
- if (!p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- sm->outside_fib_index = p[0];
- }
-
/* If the external address is a specific interface address */
if (sw_if_index != ~0)
{
if (first_int_addr == 0)
{
snat_add_static_mapping_when_resolved
- (sm, l_addr, l_port, sw_if_index, e_port, vrf_id,
+ (sm, l_addr, l_port, sw_if_index, e_port, vrf_id, proto,
addr_only, is_add);
return 0;
}
m_key.addr = e_addr;
m_key.port = addr_only ? 0 : e_port;
+ m_key.protocol = addr_only ? 0 : proto;
m_key.fib_index = sm->outside_fib_index;
kv.key = m_key.as_u64;
if (clib_bihash_search_8_8 (&sm->static_mapping_by_external, &kv, &value))
/* If not specified use inside VRF id from SNAT plugin startup config */
else
{
- if (sm->inside_fib_index == ~0)
- {
- p = hash_get (sm->ip4_main->fib_index_by_table_id, sm->inside_vrf_id);
- if (!p)
- return VNET_API_ERROR_NO_SUCH_FIB;
- fib_index = p[0];
- sm->inside_fib_index = fib_index;
- }
- else
- fib_index = sm->inside_fib_index;
-
+ fib_index = sm->inside_fib_index;
vrf_id = sm->inside_vrf_id;
}
{
a = sm->addresses + i;
/* External port must be unused */
- if (clib_bitmap_get_no_check (a->busy_port_bitmap, e_port))
- return VNET_API_ERROR_INVALID_VALUE;
- clib_bitmap_set_no_check (a->busy_port_bitmap, e_port, 1);
- if (e_port > 1024)
- a->busy_ports++;
-
+ switch (proto)
+ {
+#define _(N, j, n, s) \
+ case SNAT_PROTOCOL_##N: \
+ if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, e_port)) \
+ return VNET_API_ERROR_INVALID_VALUE; \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 1); \
+ if (e_port > 1024) \
+ a->busy_##n##_ports++; \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown_protocol");
+ return VNET_API_ERROR_INVALID_VALUE_2;
+ }
break;
}
}
{
m->local_port = l_port;
m->external_port = e_port;
+ m->proto = proto;
}
m_key.addr = m->local_addr;
m_key.port = m->local_port;
+ m_key.protocol = m->proto;
m_key.fib_index = m->fib_index;
kv.key = m_key.as_u64;
kv.value = m - sm->static_mappings;
if (sm->workers)
{
snat_user_key_t w_key0;
- snat_static_mapping_key_t w_key1;
+ snat_worker_key_t w_key1;
w_key0.addr = m->local_addr;
w_key0.fib_index = m->fib_index;
if (sm->addresses[i].addr.as_u32 == e_addr.as_u32)
{
a = sm->addresses + i;
- clib_bitmap_set_no_check (a->busy_port_bitmap, e_port, 0);
- a->busy_ports--;
-
+ switch (proto)
+ {
+#define _(N, j, n, s) \
+ case SNAT_PROTOCOL_##N: \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, e_port, 0); \
+ if (e_port > 1024) \
+ a->busy_##n##_ports--; \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown_protocol");
+ return VNET_API_ERROR_INVALID_VALUE_2;
+ }
break;
}
}
m_key.addr = m->local_addr;
m_key.port = m->local_port;
+ m_key.protocol = m->proto;
m_key.fib_index = m->fib_index;
kv.key = m_key.as_u64;
clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0);
pool_put (sm->static_mappings, m);
}
+ if (!addr_only)
+ return 0;
+
+ /* Add/delete external address to FIB */
+ pool_foreach (interface, sm->interfaces,
+ ({
+ if (interface->is_inside)
+ continue;
+
+ snat_add_del_addr_to_fib(&e_addr, interface->sw_if_index, is_add);
+ break;
+ }));
+
return 0;
}
snat_user_t *u;
snat_main_per_thread_data_t *tsm;
snat_static_mapping_t *m;
+ snat_interface_t *interface;
int i;
/* Find SNAT address */
if (m->external_addr.as_u32 == addr.as_u32)
(void) snat_add_static_mapping (m->local_addr, m->external_addr,
m->local_port, m->external_port,
- m->vrf_id, m->addr_only, ~0, 0);
+ m->vrf_id, m->addr_only, ~0,
+ m->proto, 0);
}));
}
else
}
/* Delete sessions using address */
- if (a->busy_ports)
+ if (a->busy_tcp_ports || a->busy_udp_ports || a->busy_icmp_ports)
{
vec_foreach (tsm, sm->per_thread_data)
{
vec_del1 (sm->addresses, i);
+ /* Delete external address from FIB */
+ pool_foreach (interface, sm->interfaces,
+ ({
+ if (interface->is_inside)
+ continue;
+
+ snat_add_del_addr_to_fib(&addr, interface->sw_if_index, 0);
+ break;
+ }));
+
return 0;
}
snat_main_t *sm = &snat_main;
snat_interface_t *i;
const char * feature_name;
+ snat_address_t * ap;
+ snat_static_mapping_t * m;
if (sm->static_mapping_only && !(sm->static_mapping_connection_tracking))
feature_name = is_inside ? "snat-in2out-fast" : "snat-out2in-fast";
else
return VNET_API_ERROR_VALUE_EXIST;
- return 0;
+ goto fib;
}
}));
i->sw_if_index = sw_if_index;
i->is_inside = is_inside;
+ /* Add/delete external addresses to FIB */
+fib:
+ if (is_inside)
+ return 0;
+
+ vec_foreach (ap, sm->addresses)
+ snat_add_del_addr_to_fib(&ap->addr, sw_if_index, !is_del);
+
+ pool_foreach (m, sm->static_mappings,
+ ({
+ if (!(m->addr_only))
+ continue;
+
+ snat_add_del_addr_to_fib(&m->external_addr, sw_if_index, !is_del);
+ }));
+
return 0;
}
u16 local_port = 0, external_port = 0;
u32 vrf_id, external_sw_if_index;
int rv = 0;
+ snat_protocol_t proto;
if (mp->is_ip4 != 1)
{
}
vrf_id = clib_net_to_host_u32 (mp->vrf_id);
external_sw_if_index = clib_net_to_host_u32 (mp->external_sw_if_index);
+ proto = ip_proto_to_snat_proto (mp->protocol);
rv = snat_add_static_mapping(local_addr, external_addr, local_port,
external_port, vrf_id, mp->addr_only,
- external_sw_if_index,
- mp->is_add);
+ external_sw_if_index, proto, mp->is_add);
send_reply:
REPLY_MACRO (VL_API_SNAT_ADD_ADDRESS_RANGE_REPLY);
u8 * s;
s = format (0, "SCRIPT: snat_add_static_mapping ");
- s = format (s, "local_addr %U external_addr %U ",
+ s = format (s, "protocol %d local_addr %U external_addr %U ",
+ mp->protocol,
format_ip4_address, mp->local_ip_address,
format_ip4_address, mp->external_ip_address);
clib_memcpy (rmp->external_ip_address, &(m->external_addr), 4);
rmp->local_port = htons (m->local_port);
rmp->external_port = htons (m->external_port);
+ rmp->external_sw_if_index = ~0;
+ rmp->vrf_id = htonl (m->vrf_id);
+ rmp->protocol = snat_proto_to_ip_proto (m->proto);
+ rmp->context = context;
+
+ vl_msg_api_send_shmem (q, (u8 *) & rmp);
+}
+
+static void
+send_snat_static_map_resolve_details
+(snat_static_map_resolve_t * m, unix_shared_memory_queue_t * q, u32 context)
+{
+ vl_api_snat_static_mapping_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_STATIC_MAPPING_DETAILS+sm->msg_id_base);
+ rmp->is_ip4 = 1;
+ rmp->addr_only = m->addr_only;
+ clib_memcpy (rmp->local_ip_address, &(m->l_addr), 4);
+ rmp->local_port = htons (m->l_port);
+ rmp->external_port = htons (m->e_port);
+ rmp->external_sw_if_index = htonl (m->sw_if_index);
rmp->vrf_id = htonl (m->vrf_id);
+ rmp->protocol = snat_proto_to_ip_proto (m->proto);
rmp->context = context;
vl_msg_api_send_shmem (q, (u8 *) & rmp);
unix_shared_memory_queue_t *q;
snat_main_t * sm = &snat_main;
snat_static_mapping_t * m;
+ snat_static_map_resolve_t *rp;
+ int j;
q = vl_api_client_index_to_input_queue (mp->client_index);
if (q == 0)
({
send_snat_static_mapping_details (m, q, mp->context);
}));
+
+ for (j = 0; j < vec_len (sm->to_resolve); j++)
+ {
+ rp = sm->to_resolve + j;
+ send_snat_static_map_resolve_details (rp, q, mp->context);
+ }
}
static void *vl_api_snat_static_mapping_dump_t_print
a = sm->addresses + address_index;
- ASSERT (clib_bitmap_get_no_check (a->busy_port_bitmap,
- port_host_byte_order) == 1);
-
- clib_bitmap_set_no_check (a->busy_port_bitmap, port_host_byte_order, 0);
- a->busy_ports--;
+ switch (k->protocol)
+ {
+#define _(N, i, n, s) \
+ case SNAT_PROTOCOL_##N: \
+ ASSERT (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, \
+ port_host_byte_order) == 1); \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, \
+ port_host_byte_order, 0); \
+ a->busy_##n##_ports--; \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown_protocol");
+ return;
+ }
}
/**
{
clib_bihash_kv_8_8_t kv, value;
snat_static_mapping_t *m;
- snat_static_mapping_key_t m_key;
+ snat_session_key_t m_key;
clib_bihash_8_8_t *mapping_hash = &sm->static_mapping_by_local;
if (by_external)
m_key.addr = match.addr;
m_key.port = clib_net_to_host_u16 (match.port);
+ m_key.protocol = match.protocol;
m_key.fib_index = match.fib_index;
kv.key = m_key.as_u64;
{
/* Try address only mapping */
m_key.port = 0;
+ m_key.protocol = 0;
kv.key = m_key.as_u64;
if (clib_bihash_search_8_8 (mapping_hash, &kv, &value))
return 1;
for (i = 0; i < vec_len (sm->addresses); i++)
{
- if (sm->addresses[i].busy_ports < (65535-1024))
+ a = sm->addresses + i;
+ switch (k->protocol)
{
- a = sm->addresses + i;
-
- while (1)
- {
- portnum = random_u32 (&sm->random_seed);
- portnum &= 0xFFFF;
- if (portnum < 1024)
- continue;
- if (clib_bitmap_get_no_check (a->busy_port_bitmap, portnum))
- continue;
- clib_bitmap_set_no_check (a->busy_port_bitmap, portnum, 1);
- a->busy_ports++;
- /* Caller sets protocol and fib index */
- k->addr = a->addr;
- k->port = clib_host_to_net_u16(portnum);
- *address_indexp = i;
- return 0;
- }
+#define _(N, j, n, s) \
+ case SNAT_PROTOCOL_##N: \
+ if (a->busy_##n##_ports < (65535-1024)) \
+ { \
+ while (1) \
+ { \
+ portnum = random_u32 (&sm->random_seed); \
+ portnum &= 0xFFFF; \
+ if (portnum < 1024) \
+ continue; \
+ if (clib_bitmap_get_no_check (a->busy_##n##_port_bitmap, portnum)) \
+ continue; \
+ clib_bitmap_set_no_check (a->busy_##n##_port_bitmap, portnum, 1); \
+ a->busy_##n##_ports++; \
+ k->addr = a->addr; \
+ k->port = clib_host_to_net_u16(portnum); \
+ *address_indexp = i; \
+ return 0; \
+ } \
+ } \
+ break;
+ foreach_snat_protocol
+#undef _
+ default:
+ clib_warning("unknown protocol");
+ return 1;
}
+
}
/* Totally out of translations to use... */
snat_ipfix_logging_addresses_exhausted(0);
int i, count;
int is_add = 1;
int rv = 0;
+ clib_error_t *error = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
else if (unformat (line_input, "del"))
is_add = 0;
else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
if (sm->static_mapping_only)
- return clib_error_return (0, "static mapping only mode");
+ {
+ error = clib_error_return (0, "static mapping only mode");
+ goto done;
+ }
start_host_order = clib_host_to_net_u32 (start_addr.as_u32);
end_host_order = clib_host_to_net_u32 (end_addr.as_u32);
if (end_host_order < start_host_order)
- return clib_error_return (0, "end address less than start address");
+ {
+ error = clib_error_return (0, "end address less than start address");
+ goto done;
+ }
count = (end_host_order - start_host_order) + 1;
switch (rv)
{
case VNET_API_ERROR_NO_SUCH_ENTRY:
- return clib_error_return (0, "S-NAT address not exist.");
- break;
+ error = clib_error_return (0, "S-NAT address not exist.");
+ goto done;
case VNET_API_ERROR_UNSPECIFIED:
- return clib_error_return (0, "S-NAT address used in static mapping.");
- break;
+ error = clib_error_return (0, "S-NAT address used in static mapping.");
+ goto done;
default:
break;
}
increment_v4_address (&this_addr);
}
- return 0;
+done:
+ unformat_free (line_input);
+
+ return error;
}
VLIB_CLI_COMMAND (add_address_command, static) = {
else if (unformat (line_input, "del"))
is_del = 1;
else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
if (vec_len (inside_sw_if_indices))
{
}
}
+done:
+ unformat_free (line_input);
vec_free (inside_sw_if_indices);
vec_free (outside_sw_if_indices);
.short_help = "set interface snat in <intfc> out <intfc> [del]",
};
+uword
+unformat_snat_protocol (unformat_input_t * input, va_list * args)
+{
+ u32 *r = va_arg (*args, u32 *);
+
+ if (0);
+#define _(N, i, n, s) else if (unformat (input, s)) *r = SNAT_PROTOCOL_##N;
+ foreach_snat_protocol
+#undef _
+ else
+ return 0;
+ return 1;
+}
+
+u8 *
+format_snat_protocol (u8 * s, va_list * args)
+{
+ u32 i = va_arg (*args, u32);
+ u8 *t = 0;
+
+ switch (i)
+ {
+#define _(N, j, n, str) case SNAT_PROTOCOL_##N: t = (u8 *) str; break;
+ foreach_snat_protocol
+#undef _
+ default:
+ s = format (s, "unknown");
+ }
+ s = format (s, "%s", t);
+ return s;
+}
+
static clib_error_t *
add_static_mapping_command_fn (vlib_main_t * vm,
unformat_input_t * input,
u32 sw_if_index = ~0;
vnet_main_t * vnm = vnet_get_main();
int rv;
+ snat_protocol_t proto;
+ u8 proto_set = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
;
else if (unformat (line_input, "vrf %u", &vrf_id))
;
+ else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
+ proto_set = 1;
else if (unformat (line_input, "del"))
is_add = 0;
else
- return clib_error_return (0, "unknown input: '%U'",
- format_unformat_error, line_input);
+ {
+ error = clib_error_return (0, "unknown input: '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
+ }
+
+ if (!addr_only && !proto_set)
+ {
+ error = clib_error_return (0, "missing protocol");
+ goto done;
}
- unformat_free (line_input);
rv = snat_add_static_mapping(l_addr, e_addr, (u16) l_port, (u16) e_port,
- vrf_id, addr_only, sw_if_index, is_add);
+ vrf_id, addr_only, sw_if_index, proto, is_add);
switch (rv)
{
case VNET_API_ERROR_INVALID_VALUE:
- return clib_error_return (0, "External port already in use.");
- break;
+ error = clib_error_return (0, "External port already in use.");
+ goto done;
case VNET_API_ERROR_NO_SUCH_ENTRY:
if (is_add)
- return clib_error_return (0, "External addres must be allocated.");
+ error = clib_error_return (0, "External addres must be allocated.");
else
- return clib_error_return (0, "Mapping not exist.");
- break;
+ error = clib_error_return (0, "Mapping not exist.");
+ goto done;
case VNET_API_ERROR_NO_SUCH_FIB:
- return clib_error_return (0, "No such VRF id.");
+ error = clib_error_return (0, "No such VRF id.");
+ goto done;
case VNET_API_ERROR_VALUE_EXIST:
- return clib_error_return (0, "Mapping already exist.");
+ error = clib_error_return (0, "Mapping already exist.");
+ goto done;
default:
break;
}
+done:
+ unformat_free (line_input);
+
return error;
}
* Static mapping allows hosts on the external network to initiate connection
* to to the local network host.
* To create static mapping between local host address 10.0.0.3 port 6303 and
- * external address 4.4.4.4 port 3606 use:
- * vpp# snat add static mapping local 10.0.0.3 6303 external 4.4.4.4 3606
+ * external address 4.4.4.4 port 3606 for TCP protocol use:
+ * vpp# snat add static mapping local tcp 10.0.0.3 6303 external 4.4.4.4 3606
* If not runnig "static mapping only" S-NAT plugin mode use before:
* vpp# snat add address 4.4.4.4
* To create static mapping between local and external address use:
.path = "snat add static mapping",
.function = add_static_mapping_command_fn,
.short_help =
- "snat add static mapping local <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
+ "snat add static mapping local tcp|udp|icmp <addr> [<port>] external <addr> [<port>] [vrf <table-id>] [del]",
};
static clib_error_t *
unformat_input_t _line_input, *line_input = &_line_input;
uword *bitmap = 0;
int rv = 0;
+ clib_error_t *error = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
if (unformat (line_input, "%U", unformat_bitmap_list, &bitmap))
;
else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
if (bitmap == 0)
- return clib_error_return (0, "List of workers must be specified.");
+ {
+ error = clib_error_return (0, "List of workers must be specified.");
+ goto done;
+ }
rv = snat_set_workers(bitmap);
switch (rv)
{
case VNET_API_ERROR_INVALID_WORKER:
- return clib_error_return (0, "Invalid worker(s).");
- break;
+ error = clib_error_return (0, "Invalid worker(s).");
+ goto done;
case VNET_API_ERROR_FEATURE_DISABLED:
- return clib_error_return (0,
+ error = clib_error_return (0,
"Supported only if 2 or more workes available.");
- break;
+ goto done;
default:
break;
}
- return 0;
+done:
+ unformat_free (line_input);
+
+ return error;
}
/*?
u32 src_port = 0;
u8 enable = 1;
int rv = 0;
+ clib_error_t *error = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
else if (unformat (line_input, "disable"))
enable = 0;
else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, input);
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
- unformat_free (line_input);
rv = snat_ipfix_logging_enable_disable (enable, domain_id, (u16) src_port);
if (rv)
- return clib_error_return (0, "ipfix logging enable failed");
+ {
+ error = clib_error_return (0, "ipfix logging enable failed");
+ goto done;
+ }
- return 0;
+done:
+ unformat_free (line_input);
+
+ return error;
}
/*?
sm->user_memory_size = user_memory_size;
sm->max_translations_per_user = max_translations_per_user;
sm->outside_vrf_id = outside_vrf_id;
- sm->outside_fib_index = ~0;
+ sm->outside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ outside_vrf_id);
sm->inside_vrf_id = inside_vrf_id;
- sm->inside_fib_index = ~0;
+ sm->inside_fib_index = fib_table_find_or_create_and_lock (FIB_PROTOCOL_IP4,
+ inside_vrf_id);
sm->static_mapping_only = static_mapping_only;
sm->static_mapping_connection_tracking = static_mapping_connection_tracking;
format_ip4_address, &m->external_addr,
m->vrf_id);
else
- s = format (s, "local %U:%d external %U:%d vrf %d",
+ s = format (s, "%U local %U:%d external %U:%d vrf %d",
+ format_snat_protocol, m->proto,
format_ip4_address, &m->local_addr, m->local_port,
format_ip4_address, &m->external_addr, m->external_port,
m->vrf_id);
return s;
}
+u8 * format_snat_static_map_to_resolve (u8 * s, va_list * args)
+{
+ snat_static_map_resolve_t *m = va_arg (*args, snat_static_map_resolve_t *);
+ vnet_main_t *vnm = vnet_get_main();
+
+ if (m->addr_only)
+ s = format (s, "local %U external %U vrf %d",
+ format_ip4_address, &m->l_addr,
+ format_vnet_sw_interface_name, vnm,
+ vnet_get_sw_interface (vnm, m->sw_if_index),
+ m->vrf_id);
+ else
+ s = format (s, "%U local %U:%d external %U:%d vrf %d",
+ format_snat_protocol, m->proto,
+ format_ip4_address, &m->l_addr, m->l_port,
+ format_vnet_sw_interface_name, vnm,
+ vnet_get_sw_interface (vnm, m->sw_if_index), m->e_port,
+ m->vrf_id);
+
+ return s;
+}
+
static clib_error_t *
show_snat_command_fn (vlib_main_t * vm,
unformat_input_t * input,
snat_main_per_thread_data_t *tsm;
u32 users_num = 0, sessions_num = 0, *worker, *sw_if_index;
uword j = 0;
+ snat_static_map_resolve_t *rp;
if (unformat (input, "detail"))
verbose = 1;
vec_foreach (ap, sm->addresses)
{
- u8 * s = format (0, "");
vlib_cli_output (vm, "%U", format_ip4_address, &ap->addr);
- clib_bitmap_foreach (j, ap->busy_port_bitmap,
- ({
- s = format (s, " %d", j);
- }));
- vlib_cli_output (vm, " %d busy ports:%s", ap->busy_ports, s);
+#define _(N, i, n, s) \
+ vlib_cli_output (vm, " %d busy %s ports", ap->busy_##n##_ports, s);
+ foreach_snat_protocol
+#undef _
}
}
}));
}
- if (pool_elts (sm->static_mappings))
+ if (pool_elts (sm->static_mappings) || vec_len (sm->to_resolve))
{
vlib_cli_output (vm, "static mappings:");
pool_foreach (m, sm->static_mappings,
({
vlib_cli_output (vm, "%U", format_snat_static_mapping, m);
}));
+ for (j = 0; j < vec_len (sm->to_resolve); j++)
+ {
+ rp = sm->to_resolve + j;
+ vlib_cli_output (vm, "%U", format_snat_static_map_to_resolve,
+ rp);
+ }
}
}
}
rp->vrf_id,
rp->addr_only,
~0 /* sw_if_index */,
+ rp->proto,
rp->is_add);
if (rv)
clib_warning ("snat_add_static_mapping returned %d",
u32 sw_if_index;
int rv;
int is_del = 0;
+ clib_error_t *error = 0;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
else if (unformat (line_input, "del"))
is_del = 1;
else
- return clib_error_return (0, "unknown input '%U'",
- format_unformat_error, line_input);
+ {
+ error = clib_error_return (0, "unknown input '%U'",
+ format_unformat_error, line_input);
+ goto done;
+ }
}
rv = snat_add_interface_address (sm, sw_if_index, is_del);
break;
default:
- return clib_error_return (0, "snat_add_interface_address returned %d",
- rv);
+ error = clib_error_return (0, "snat_add_interface_address returned %d",
+ rv);
+ goto done;
}
- return 0;
+
+done:
+ unformat_free (line_input);
+
+ return error;
}
VLIB_CLI_COMMAND (snat_add_interface_address_command, static) = {