summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/snat/in2out.c37
-rw-r--r--src/plugins/snat/out2in.c34
-rw-r--r--src/plugins/snat/snat.api4
-rw-r--r--src/plugins/snat/snat.c196
-rw-r--r--src/plugins/snat/snat.h46
-rw-r--r--src/plugins/snat/snat_ipfix_logging.c4
-rw-r--r--src/plugins/snat/snat_test.c29
-rw-r--r--test/test_snat.py27
-rw-r--r--test/vpp_papi_provider.py5
9 files changed, 242 insertions, 140 deletions
diff --git a/src/plugins/snat/in2out.c b/src/plugins/snat/in2out.c
index fba852c6fe1..b0047737121 100644
--- a/src/plugins/snat/in2out.c
+++ b/src/plugins/snat/in2out.c
@@ -224,7 +224,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
u32 address_index = ~0;
u32 outside_fib_index;
uword * p;
- snat_static_mapping_key_t worker_by_out_key;
+ snat_worker_key_t worker_by_out_key;
p = hash_get (sm->ip4_main->fib_index_by_table_id, sm->outside_vrf_id);
if (! p)
@@ -234,6 +234,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
}
outside_fib_index = p[0];
+ key1.protocol = key0->protocol;
user_key.addr = ip0->src_address;
user_key.fib_index = rx_fib_index0;
kv0.key = user_key.as_u64;
@@ -520,7 +521,7 @@ snat_hairpinning (snat_main_t *sm,
u32 proto0)
{
snat_session_key_t key0, sm0;
- snat_static_mapping_key_t k0;
+ snat_worker_key_t k0;
snat_session_t * s0;
clib_bihash_kv_8_8_t kv0, value0;
ip_csum_t sum0;
@@ -682,13 +683,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
next0 = next1 = SNAT_IN2OUT_NEXT_LOOKUP;
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
/* Next configured feature, probably ip4-lookup */
if (is_slow_path)
@@ -818,13 +813,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index1);
- proto1 = ~0;
- proto1 = (ip1->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto1;
- proto1 = (ip1->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto1;
- proto1 = (ip1->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto1;
+ proto1 = ip_proto_to_snat_proto (ip1->protocol);
/* Next configured feature, probably ip4-lookup */
if (is_slow_path)
@@ -989,13 +978,7 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index0);
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
/* Next configured feature, probably ip4-lookup */
if (is_slow_path)
@@ -1497,13 +1480,7 @@ snat_in2out_fast_static_map_fn (vlib_main_t * vm,
sw_if_index0 = vnet_buffer(b0)->sw_if_index[VLIB_RX];
rx_fib_index0 = ip4_fib_table_get_index_for_sw_if_index(sw_if_index0);
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
if (PREDICT_FALSE (proto0 == ~0))
goto trace0;
diff --git a/src/plugins/snat/out2in.c b/src/plugins/snat/out2in.c
index f08e16d3c51..4f3322a3231 100644
--- a/src/plugins/snat/out2in.c
+++ b/src/plugins/snat/out2in.c
@@ -405,13 +405,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index0);
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
if (PREDICT_FALSE (proto0 == ~0))
goto trace0;
@@ -536,13 +530,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index1 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index1);
- proto1 = ~0;
- proto1 = (ip1->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto1;
- proto1 = (ip1->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto1;
- proto1 = (ip1->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto1;
+ proto1 = ip_proto_to_snat_proto (ip1->protocol);
if (PREDICT_FALSE (proto1 == ~0))
goto trace1;
@@ -701,13 +689,7 @@ snat_out2in_node_fn (vlib_main_t * vm,
rx_fib_index0 = vec_elt (sm->ip4_main->fib_index_by_sw_if_index,
sw_if_index0);
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
if (PREDICT_FALSE (proto0 == ~0))
goto trace00;
@@ -901,7 +883,7 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
u32 rx_fib_index0;
ip4_header_t * ip0;
udp_header_t * udp0;
- snat_static_mapping_key_t key0;
+ snat_worker_key_t key0;
clib_bihash_kv_8_8_t kv0, value0;
u8 do_handoff;
@@ -1196,13 +1178,7 @@ snat_out2in_fast_node_fn (vlib_main_t * vm,
vnet_feature_next (sw_if_index0, &next0, b0);
- proto0 = ~0;
- proto0 = (ip0->protocol == IP_PROTOCOL_UDP)
- ? SNAT_PROTOCOL_UDP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_TCP)
- ? SNAT_PROTOCOL_TCP : proto0;
- proto0 = (ip0->protocol == IP_PROTOCOL_ICMP)
- ? SNAT_PROTOCOL_ICMP : proto0;
+ proto0 = ip_proto_to_snat_proto (ip0->protocol);
if (PREDICT_FALSE (proto0 == ~0))
goto trace00;
diff --git a/src/plugins/snat/snat.api b/src/plugins/snat/snat.api
index b562e7a08e1..decbacf5c2f 100644
--- a/src/plugins/snat/snat.api
+++ b/src/plugins/snat/snat.api
@@ -118,6 +118,7 @@ define snat_interface_details {
@param addr_only - 1 if address only mapping
@param local_ip_address - local IP address
@param external_ip_address - external IP address
+ @param protocol - IP protocol
@param local_port - local port number
@param external_port - external port number
@param external_sw_if_index - external interface (if set
@@ -132,6 +133,7 @@ define snat_add_static_mapping {
u8 addr_only;
u8 local_ip_address[16];
u8 external_ip_address[16];
+ u8 protocol;
u16 local_port;
u16 external_port;
u32 external_sw_if_index;
@@ -162,6 +164,7 @@ define snat_static_mapping_dump {
@param addr_only - 1 if address only mapping
@param local_ip_address - local IP address
@param external_ip_address - external IP address
+ @param protocol - IP protocol
@param local_port - local port number
@param external_port - external port number
@param vfr_id - VRF ID
@@ -172,6 +175,7 @@ define snat_static_mapping_details {
u8 addr_only;
u8 local_ip_address[16];
u8 external_ip_address[16];
+ u8 protocol;
u16 local_port;
u16 external_port;
u32 vrf_id;
diff --git a/src/plugins/snat/snat.c b/src/plugins/snat/snat.c
index 5ee6647576a..0fcd6ce8606 100644
--- a/src/plugins/snat/snat.c
+++ b/src/plugins/snat/snat.c
@@ -270,7 +270,10 @@ void snat_add_address (snat_main_t *sm, ip4_address_t *addr)
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,
@@ -311,6 +314,7 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
u32 sw_if_index,
u16 e_port,
u32 vrf_id,
+ snat_protocol_t proto,
int addr_only,
int is_add)
{
@@ -322,6 +326,7 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
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;
}
@@ -344,11 +349,11 @@ snat_add_static_mapping_when_resolved (snat_main_t * sm,
*/
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;
@@ -378,7 +383,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
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;
}
@@ -388,6 +393,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
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))
@@ -435,12 +441,22 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
{
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;
}
}
@@ -460,10 +476,12 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
{
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;
@@ -480,7 +498,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
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;
@@ -518,9 +536,20 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
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;
}
}
@@ -528,6 +557,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
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);
@@ -666,7 +696,8 @@ int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
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
@@ -680,7 +711,7 @@ int snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm)
}
/* 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)
{
@@ -1019,6 +1050,7 @@ vl_api_snat_add_static_mapping_t_handler
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)
{
@@ -1035,11 +1067,11 @@ vl_api_snat_add_static_mapping_t_handler
}
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);
@@ -1051,7 +1083,8 @@ static void *vl_api_snat_add_static_mapping_t_print
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);
@@ -1086,6 +1119,7 @@ send_snat_static_mapping_details
rmp->local_port = htons (m->local_port);
rmp->external_port = htons (m->external_port);
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);
@@ -1532,11 +1566,22 @@ void snat_free_outside_address_and_port (snat_main_t * sm,
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;
+ }
}
/**
@@ -1557,7 +1602,7 @@ int snat_static_mapping_match (snat_main_t * sm,
{
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)
@@ -1565,6 +1610,7 @@ int snat_static_mapping_match (snat_main_t * sm,
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;
@@ -1573,6 +1619,7 @@ int snat_static_mapping_match (snat_main_t * sm,
{
/* 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;
@@ -1610,27 +1657,37 @@ int snat_alloc_outside_address_and_port (snat_main_t * sm,
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);
@@ -1787,6 +1844,38 @@ VLIB_CLI_COMMAND (set_interface_snat_command, static) = {
.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,
@@ -1801,6 +1890,7 @@ add_static_mapping_command_fn (vlib_main_t * vm,
u32 sw_if_index = ~0;
vnet_main_t * vnm = vnet_get_main();
int rv;
+ snat_protocol_t proto;
/* Get a line of input. */
if (!unformat_user (input, unformat_line_input, line_input))
@@ -1829,6 +1919,8 @@ add_static_mapping_command_fn (vlib_main_t * vm,
;
else if (unformat (line_input, "vrf %u", &vrf_id))
;
+ else if (unformat (line_input, "%U", unformat_snat_protocol, &proto))
+ ;
else if (unformat (line_input, "del"))
is_add = 0;
else
@@ -1838,7 +1930,7 @@ add_static_mapping_command_fn (vlib_main_t * vm,
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)
{
@@ -2175,7 +2267,8 @@ u8 * format_snat_static_mapping (u8 * s, va_list * args)
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);
@@ -2238,13 +2331,11 @@ show_snat_command_fn (vlib_main_t * vm,
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 _
}
}
@@ -2383,6 +2474,7 @@ snat_ip4_add_del_interface_address_cb (ip4_main_t * im,
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",
diff --git a/src/plugins/snat/snat.h b/src/plugins/snat/snat.h
index fc379dfa3ed..32dc9f9e0a6 100644
--- a/src/plugins/snat/snat.h
+++ b/src/plugins/snat/snat.h
@@ -66,13 +66,18 @@ typedef struct {
};
u64 as_u64;
};
-} snat_static_mapping_key_t;
+} snat_worker_key_t;
+#define foreach_snat_protocol \
+ _(UDP, 0, udp, "udp") \
+ _(TCP, 1, tcp, "tcp") \
+ _(ICMP, 2, icmp, "icmp")
+
typedef enum {
- SNAT_PROTOCOL_UDP = 0,
- SNAT_PROTOCOL_TCP,
- SNAT_PROTOCOL_ICMP,
+#define _(N, i, n, s) SNAT_PROTOCOL_##N = i,
+ foreach_snat_protocol
+#undef _
} snat_protocol_t;
@@ -112,8 +117,11 @@ typedef struct {
typedef struct {
ip4_address_t addr;
- u32 busy_ports;
- uword * busy_port_bitmap;
+#define _(N, i, n, s) \
+ u32 busy_##n##_ports; \
+ uword * busy_##n##_port_bitmap;
+ foreach_snat_protocol
+#undef _
} snat_address_t;
typedef struct {
@@ -124,6 +132,7 @@ typedef struct {
u8 addr_only;
u32 vrf_id;
u32 fib_index;
+ snat_protocol_t proto;
} snat_static_mapping_t;
typedef struct {
@@ -137,6 +146,7 @@ typedef struct {
u16 e_port;
u32 sw_if_index;
u32 vrf_id;
+ snat_protocol_t proto;
int addr_only;
int is_add;
} snat_static_map_resolve_t;
@@ -272,4 +282,28 @@ typedef struct {
u16 sequence;
} icmp_echo_header_t;
+always_inline snat_protocol_t
+ip_proto_to_snat_proto (u8 ip_proto)
+{
+ snat_protocol_t snat_proto = ~0;
+
+ snat_proto = (ip_proto == IP_PROTOCOL_UDP) ? SNAT_PROTOCOL_UDP : snat_proto;
+ snat_proto = (ip_proto == IP_PROTOCOL_TCP) ? SNAT_PROTOCOL_TCP : snat_proto;
+ snat_proto = (ip_proto == IP_PROTOCOL_ICMP) ? SNAT_PROTOCOL_ICMP : snat_proto;
+
+ return snat_proto;
+}
+
+always_inline u8
+snat_proto_to_ip_proto (snat_protocol_t snat_proto)
+{
+ u8 ip_proto = ~0;
+
+ ip_proto = (snat_proto == SNAT_PROTOCOL_UDP) ? IP_PROTOCOL_UDP : ip_proto;
+ ip_proto = (snat_proto == SNAT_PROTOCOL_TCP) ? IP_PROTOCOL_TCP : ip_proto;
+ ip_proto = (snat_proto == SNAT_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP : ip_proto;
+
+ return ip_proto;
+}
+
#endif /* __included_snat_h__ */
diff --git a/src/plugins/snat/snat_ipfix_logging.c b/src/plugins/snat/snat_ipfix_logging.c
index d72eb226675..9f1abb7d9f4 100644
--- a/src/plugins/snat/snat_ipfix_logging.c
+++ b/src/plugins/snat/snat_ipfix_logging.c
@@ -295,9 +295,7 @@ snat_ipfix_logging_nat44_ses (u8 nat_event, u32 src_ip, u32 nat_src_ip,
if (!silm->enabled)
return;
- proto = (snat_proto == SNAT_PROTOCOL_UDP) ? IP_PROTOCOL_UDP : proto;
- proto = (snat_proto == SNAT_PROTOCOL_TCP) ? IP_PROTOCOL_TCP : proto;
- proto = (snat_proto == SNAT_PROTOCOL_ICMP) ? IP_PROTOCOL_ICMP : proto;
+ proto = snat_proto_to_ip_proto (snat_proto);
now = (u64) ((vlib_time_now (vm) - silm->vlib_time_0) * 1e3);
now += silm->milisecond_time_0;
diff --git a/src/plugins/snat/snat_test.c b/src/plugins/snat/snat_test.c
index 50e81eaec46..85f9d57a35e 100644
--- a/src/plugins/snat/snat_test.c
+++ b/src/plugins/snat/snat_test.c
@@ -214,13 +214,14 @@ static int api_snat_add_static_mapping(vat_main_t * vam)
unformat_input_t * i = vam->input;
vl_api_snat_add_static_mapping_t * mp;
u8 external_addr_set = 0;
- u8 local_addr_set;
+ u8 local_addr_set = 0;
u8 is_add = 1;
u8 addr_only = 1;
ip4_address_t local_addr, external_addr;
u32 local_port = 0, external_port = 0, vrf_id = ~0;
u32 sw_if_index = ~0;
u8 sw_if_index_set = 0;
+ u32 proto = ~0;
int ret;
while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
@@ -239,7 +240,9 @@ static int api_snat_add_static_mapping(vat_main_t * vam)
sw_if_index_set = 1;
else if (unformat (i, "external_sw_if_index %d", &sw_if_index))
sw_if_index_set = 1;
- else if (unformat (i, "vrf %u", &vrf_id))
+ else if (unformat (i, "vrf %u", &vrf_id))
+ ;
+ else if (unformat (i, "protocol %u", &proto))
;
else if (unformat (i, "del"))
is_add = 0;
@@ -269,6 +272,7 @@ static int api_snat_add_static_mapping(vat_main_t * vam)
mp->external_port = ntohs ((u16) external_port);
mp->external_sw_if_index = ntohl (sw_if_index);
mp->vrf_id = ntohl (vrf_id);
+ mp->protocol = (u8) proto;
memcpy (mp->local_ip_address, &local_addr, 4);
memcpy (mp->external_ip_address, &external_addr, 4);
@@ -300,17 +304,19 @@ static void vl_api_snat_static_mapping_details_t_handler
vat_main_t *vam = sm->vat_main;
if (mp->addr_only)
- fformat (vam->ofp, "%15U%6s%15U%6s%11d\n",
+ fformat (vam->ofp, "%15U%6s%15U%6s%11d%6d\n",
format_ip4_address, &mp->local_ip_address, "",
format_ip4_address, &mp->external_ip_address, "",
- ntohl (mp->vrf_id));
+ ntohl (mp->vrf_id),
+ mp->protocol);
else
- fformat (vam->ofp, "%15U%6d%15U%6d%11d\n",
+ fformat (vam->ofp, "%15U%6d%15U%6d%11d%6d\n",
format_ip4_address, &mp->local_ip_address,
ntohs (mp->local_port),
format_ip4_address, &mp->external_ip_address,
ntohs (mp->external_port),
- ntohl (mp->vrf_id));
+ ntohl (mp->vrf_id),
+ mp->protocol);
}
@@ -327,8 +333,8 @@ static int api_snat_static_mapping_dump(vat_main_t * vam)
}
fformat (vam->ofp, "%21s%21s\n", "local", "external");
- fformat (vam->ofp, "%15s%6s%15s%6s%11s\n", "address", "port", "address",
- "port", "vrf");
+ fformat (vam->ofp, "%15s%6s%15s%6s%11s%6s\n", "address", "port", "address",
+ "port", "vrf", "proto");
M(SNAT_STATIC_MAPPING_DUMP, mp);
S(mp);
@@ -626,9 +632,10 @@ static int api_snat_add_del_interface_addr (vat_main_t * vam)
_(snat_add_address_range, "<start-addr> [- <end-addr] [del]") \
_(snat_interface_add_del_feature, \
"<intfc> | sw_if_index <id> [in] [out] [del]") \
-_(snat_add_static_mapping, "local_addr <ip> external_addr <ip> " \
- "| external_if <intfc> | external_sw_if_ndex <id>) " \
- "[local_port <n>] [external_port <n>] [vrf <table-id>] [del]") \
+_(snat_add_static_mapping, "local_addr <ip> (external_addr <ip>" \
+ " | external_if <intfc> | external_sw_if_ndex <id>) " \
+ "[local_port <n>] [external_port <n>] [vrf <table-id>] [del] " \
+ "protocol <n>") \
_(snat_set_workers, "<wokrers_bitmap>") \
_(snat_static_mapping_dump, "") \
_(snat_show_config, "") \
diff --git a/test/test_snat.py b/test/test_snat.py
index a67deede7a5..967d4b37c71 100644
--- a/test/test_snat.py
+++ b/test/test_snat.py
@@ -292,6 +292,7 @@ class TestSNAT(VppTestCase):
external_port=sm.external_port,
addr_only=sm.addr_only,
vrf_id=sm.vrf_id,
+ protocol=sm.protocol,
is_add=0)
adresses = self.vapi.snat_address_dump()
@@ -302,7 +303,8 @@ class TestSNAT(VppTestCase):
def snat_add_static_mapping(self, local_ip, external_ip='0.0.0.0',
local_port=0, external_port=0, vrf_id=0,
- is_add=1, external_sw_if_index=0xFFFFFFFF):
+ is_add=1, external_sw_if_index=0xFFFFFFFF,
+ proto=0):
"""
Add/delete S-NAT static mapping
@@ -313,6 +315,7 @@ class TestSNAT(VppTestCase):
:param vrf_id: VRF ID (Default 0)
:param is_add: 1 if add, 0 if delete (Default add)
:param external_sw_if_index: External interface instead of IP address
+ :param proto: IP protocol (Mandatory if port specified)
"""
addr_only = 1
if local_port and external_port:
@@ -327,6 +330,7 @@ class TestSNAT(VppTestCase):
external_port,
addr_only,
vrf_id,
+ proto,
is_add)
def snat_add_address(self, ip, is_add=1):
@@ -430,11 +434,14 @@ class TestSNAT(VppTestCase):
self.snat_add_address(self.snat_addr)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.tcp_port_in, self.tcp_port_out)
+ self.tcp_port_in, self.tcp_port_out,
+ proto=IP_PROTOS.tcp)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.udp_port_in, self.udp_port_out)
+ self.udp_port_in, self.udp_port_out,
+ proto=IP_PROTOS.udp)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.icmp_id_in, self.icmp_id_out)
+ self.icmp_id_in, self.icmp_id_out,
+ proto=IP_PROTOS.icmp)
self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
is_inside=0)
@@ -464,11 +471,14 @@ class TestSNAT(VppTestCase):
self.snat_add_address(self.snat_addr)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.tcp_port_in, self.tcp_port_out)
+ self.tcp_port_in, self.tcp_port_out,
+ proto=IP_PROTOS.tcp)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.udp_port_in, self.udp_port_out)
+ self.udp_port_in, self.udp_port_out,
+ proto=IP_PROTOS.udp)
self.snat_add_static_mapping(self.pg0.remote_ip4, self.snat_addr,
- self.icmp_id_in, self.icmp_id_out)
+ self.icmp_id_in, self.icmp_id_out,
+ proto=IP_PROTOS.icmp)
self.vapi.snat_interface_add_del_feature(self.pg0.sw_if_index)
self.vapi.snat_interface_add_del_feature(self.pg1.sw_if_index,
is_inside=0)
@@ -685,7 +695,8 @@ class TestSNAT(VppTestCase):
is_inside=0)
# add static mapping for server
self.snat_add_static_mapping(server.ip4, self.snat_addr,
- server_in_port, server_out_port)
+ server_in_port, server_out_port,
+ proto=IP_PROTOS.tcp)
# send packet from host to server
p = (Ether(src=host.mac, dst=self.pg0.local_mac) /
diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py
index 72c18e6cef7..2cd02cc7954 100644
--- a/test/vpp_papi_provider.py
+++ b/test/vpp_papi_provider.py
@@ -883,6 +883,7 @@ class VppPapiProvider(object):
external_port=0,
addr_only=1,
vrf_id=0,
+ protocol=0,
is_add=1,
is_ip4=1):
"""Add/delete S-NAT static mapping
@@ -894,6 +895,7 @@ class VppPapiProvider(object):
:param external_port: External port number (Default value = 0)
:param addr_only: 1 if address only mapping, 0 if address and port
:param vrf_id: VRF ID
+ :param protocol: IP protocol (Default value = 0)
:param is_add: 1 if add, 0 if delete (Default value = 1)
:param is_ip4: 1 if address type is IPv4 (Default value = 1)
"""
@@ -907,7 +909,8 @@ class VppPapiProvider(object):
'local_port': local_port,
'external_port': external_port,
'external_sw_if_index': external_sw_if_index,
- 'vrf_id': vrf_id})
+ 'vrf_id': vrf_id,
+ 'protocol': protocol})
def snat_add_address_range(
self,