summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/nat/dslite_ce_decap.c1
-rw-r--r--src/plugins/nat/dslite_ce_encap.c1
-rw-r--r--src/plugins/nat/dslite_in2out.c1
-rw-r--r--src/plugins/nat/dslite_out2in.c1
-rwxr-xr-xsrc/plugins/nat/in2out.c167
-rwxr-xr-xsrc/plugins/nat/nat.c235
-rw-r--r--src/plugins/nat/nat.h207
-rw-r--r--src/plugins/nat/nat44_cli.c7
-rw-r--r--src/plugins/nat/nat64.c1
-rw-r--r--src/plugins/nat/nat64_cli.c1
-rw-r--r--src/plugins/nat/nat64_db.c1
-rw-r--r--src/plugins/nat/nat64_in2out.c1
-rw-r--r--src/plugins/nat/nat64_out2in.c1
-rw-r--r--src/plugins/nat/nat_api.c3
-rw-r--r--src/plugins/nat/nat_inlines.h250
-rw-r--r--src/plugins/nat/nat_ipfix_logging.c1
-rwxr-xr-xsrc/plugins/nat/out2in.c215
-rw-r--r--test/test_nat.py286
18 files changed, 781 insertions, 599 deletions
diff --git a/src/plugins/nat/dslite_ce_decap.c b/src/plugins/nat/dslite_ce_decap.c
index 615a424e871..c16ac17c2a6 100644
--- a/src/plugins/nat/dslite_ce_decap.c
+++ b/src/plugins/nat/dslite_ce_decap.c
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include <nat/dslite.h>
+#include <nat/nat_inlines.h>
vlib_node_registration_t dslite_ce_decap_node;
diff --git a/src/plugins/nat/dslite_ce_encap.c b/src/plugins/nat/dslite_ce_encap.c
index f098d75ca70..d83ca9c8046 100644
--- a/src/plugins/nat/dslite_ce_encap.c
+++ b/src/plugins/nat/dslite_ce_encap.c
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include <nat/dslite.h>
+#include <nat/nat_inlines.h>
vlib_node_registration_t dslite_ce_encap_node;
diff --git a/src/plugins/nat/dslite_in2out.c b/src/plugins/nat/dslite_in2out.c
index 98b3a1618f7..ab0055cfee2 100644
--- a/src/plugins/nat/dslite_in2out.c
+++ b/src/plugins/nat/dslite_in2out.c
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include <nat/dslite.h>
+#include <nat/nat_inlines.h>
vlib_node_registration_t dslite_in2out_node;
vlib_node_registration_t dslite_in2out_slowpath_node;
diff --git a/src/plugins/nat/dslite_out2in.c b/src/plugins/nat/dslite_out2in.c
index 802b2a91544..6bfc6e979cd 100644
--- a/src/plugins/nat/dslite_out2in.c
+++ b/src/plugins/nat/dslite_out2in.c
@@ -13,6 +13,7 @@
* limitations under the License.
*/
#include <nat/dslite.h>
+#include <nat/nat_inlines.h>
vlib_node_registration_t dslite_out2in_node;
diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c
index 1659ed0fec3..c724553e36b 100755
--- a/src/plugins/nat/in2out.c
+++ b/src/plugins/nat/in2out.c
@@ -25,6 +25,7 @@
#include <nat/nat_ipfix_logging.h>
#include <nat/nat_det.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
@@ -127,7 +128,8 @@ _(NO_TRANSLATION, "No translation") \
_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \
_(DROP_FRAGMENT, "Drop fragment") \
_(MAX_REASS, "Maximum reassemblies exceeded") \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(MAX_FRAG, "Maximum fragments per reassembly exceeded")\
+_(FQ_CONGESTED, "Handoff frame queue congested")
typedef enum {
#define _(sym,str) SNAT_IN2OUT_ERROR_##sym,
@@ -316,6 +318,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
nat_ipfix_logging_max_sessions(sm->max_translations);
+ nat_log_notice ("maximum sessions exceeded");
return SNAT_IN2OUT_NEXT_DROP;
}
@@ -333,7 +336,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return SNAT_IN2OUT_NEXT_DROP;
}
@@ -357,7 +360,7 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return SNAT_IN2OUT_NEXT_DROP;
}
@@ -378,14 +381,14 @@ static u32 slow_path (snat_main_t *sm, vlib_buffer_t *b0,
kv0.value = s - sm->per_thread_data[thread_index].sessions;
if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].in2out, &kv0,
1 /* is_add */))
- clib_warning ("in2out key add failed");
+ nat_log_notice ("in2out key add failed");
kv0.key = s->out2in.as_u64;
kv0.value = s - sm->per_thread_data[thread_index].sessions;
if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0,
1 /* is_add */))
- clib_warning ("out2in key add failed");
+ nat_log_notice ("out2in key add failed");
/* log NAT event */
snat_ipfix_logging_nat44_ses_create(s->in2out.addr.as_u32,
@@ -497,7 +500,6 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
clib_bihash_kv_16_8_t kv, value;
udp_header_t *udp;
snat_session_t *s = 0;
- snat_main_per_thread_data_t *tsm = &sm->per_thread_data[thread_index];
f64 now = vlib_time_now (sm->vlib_main);
if (!sm->forwarding_enabled)
@@ -540,12 +542,9 @@ nat_not_translate_output_feature_fwd (snat_main_t * sm, ip4_header_t * ip,
return 1;
}
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
+ nat44_session_update_counters (s, now, 0);
return 1;
}
else
@@ -1083,15 +1082,10 @@ static inline u32 icmp_in2out_slow_path (snat_main_t *sm,
if (vnet_buffer(b0)->sw_if_index[VLIB_TX] == 0)
snat_icmp_hairpinning(sm, b0, ip0, icmp0);
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (sm->vlib_main, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (sm->vlib_main, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
}
return next0;
}
@@ -1198,6 +1192,7 @@ snat_in2out_unknown_proto (snat_main_t *sm,
{
b->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
nat_ipfix_logging_max_sessions(sm->max_translations);
+ nat_log_notice ("maximum sessions exceeded");
return 0;
}
@@ -1205,7 +1200,7 @@ snat_in2out_unknown_proto (snat_main_t *sm,
thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return 0;
}
@@ -1280,7 +1275,7 @@ create_ses:
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return 0;
}
@@ -1306,14 +1301,14 @@ create_ses:
s_kv.key[1] = key.as_u64[1];
s_kv.value = s - tsm->sessions;
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1))
- clib_warning ("in2out key add failed");
+ nat_log_notice ("in2out key add failed");
key.l_addr.as_u32 = new_addr;
key.fib_index = sm->outside_fib_index;
s_kv.key[0] = key.as_u64[0];
s_kv.key[1] = key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
- clib_warning ("out2in key add failed");
+ nat_log_notice ("out2in key add failed");
}
/* Update IP checksum */
@@ -1322,13 +1317,9 @@ create_ses:
ip->checksum = ip_csum_fold (sum);
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
+ nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b));
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
/* Hairpinning */
if (vnet_buffer(b)->sw_if_index[VLIB_TX] == ~0)
@@ -1386,9 +1377,7 @@ snat_in2out_lb (snat_main_t *sm,
return 0;
}
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
return 0;
}
}
@@ -1398,6 +1387,7 @@ snat_in2out_lb (snat_main_t *sm,
{
b->error = node->errors[SNAT_IN2OUT_ERROR_MAX_SESSIONS_EXCEEDED];
nat_ipfix_logging_max_sessions(sm->max_translations);
+ nat_log_notice ("maximum sessions exceeded");
return 0;
}
@@ -1412,18 +1402,19 @@ snat_in2out_lb (snat_main_t *sm,
thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return 0;
}
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return 0;
}
s->ext_host_addr.as_u32 = ip->dst_address.as_u32;
+ s->ext_host_port = udp->dst_port;
s->flags |= SNAT_SESSION_FLAG_STATIC_MAPPING;
if (lb)
s->flags |= SNAT_SESSION_FLAG_LOAD_BALANCING;
@@ -1437,7 +1428,7 @@ snat_in2out_lb (snat_main_t *sm,
/* Add to lookup tables */
s_kv.value = s - tsm->sessions;
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1))
- clib_warning ("in2out-ed key add failed");
+ nat_log_notice ("in2out-ed key add failed");
key.l_addr = e_key.addr;
key.fib_index = e_key.fib_index;
@@ -1445,7 +1436,7 @@ snat_in2out_lb (snat_main_t *sm,
s_kv.key[0] = key.as_u64[0];
s_kv.key[1] = key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
- clib_warning ("out2in-ed key add failed");
+ nat_log_notice ("out2in-ed key add failed");
}
new_addr = ip->src_address.as_u32 = s->out2in.addr.as_u32;
@@ -1496,13 +1487,10 @@ snat_in2out_lb (snat_main_t *sm,
}
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
+ nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b));
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
+
return s;
}
@@ -1747,15 +1735,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
}
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace00:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -1939,15 +1922,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
}
/* Accounting */
- s1->last_heard = now;
- s1->total_pkts++;
- s1->total_bytes += vlib_buffer_length_in_chain (vm, b1);
+ nat44_session_update_counters (s1, now,
+ vlib_buffer_length_in_chain (vm, b1));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_list_head_index,
- s1->per_user_index);
+ nat44_session_update_lru (sm, s1, thread_index);
trace01:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -2168,15 +2146,10 @@ snat_in2out_node_fn_inline (vlib_main_t * vm,
}
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace0:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -2614,6 +2587,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
{
next0 = SNAT_IN2OUT_NEXT_DROP;
b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_REASS];
+ nat_log_notice ("maximum reassemblies exceeded");
goto trace0;
}
@@ -2654,6 +2628,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
if (nat_ip4_reass_add_fragment (reass0, bi0))
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
+ nat_log_notice ("maximum fragments per reassembly exceeded");
next0 = SNAT_IN2OUT_NEXT_DROP;
goto trace0;
}
@@ -2705,15 +2680,10 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
s0->ext_host_port, proto0);
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace0:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -2907,8 +2877,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
dm0 = snat_det_map_by_user(sm, &ip0->src_address);
if (PREDICT_FALSE(!dm0))
{
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
+ nat_log_info ("no match for internal host %U",
+ format_ip4_address, &ip0->src_address);
next0 = SNAT_IN2OUT_NEXT_DROP;
b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
goto trace0;
@@ -3057,8 +3027,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
dm1 = snat_det_map_by_user(sm, &ip1->src_address);
if (PREDICT_FALSE(!dm1))
{
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
+ nat_log_info ("no match for internal host %U",
+ format_ip4_address, &ip0->src_address);
next1 = SNAT_IN2OUT_NEXT_DROP;
b1->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
goto trace1;
@@ -3243,8 +3213,8 @@ snat_det_in2out_node_fn (vlib_main_t * vm,
dm0 = snat_det_map_by_user(sm, &ip0->src_address);
if (PREDICT_FALSE(!dm0))
{
- clib_warning("no match for internal host %U",
- format_ip4_address, &ip0->src_address);
+ nat_log_info ("no match for internal host %U",
+ format_ip4_address, &ip0->src_address);
next0 = SNAT_IN2OUT_NEXT_DROP;
b0->error = node->errors[SNAT_IN2OUT_ERROR_NO_TRANSLATION];
goto trace00;
@@ -3476,8 +3446,8 @@ u32 icmp_match_in2out_det(snat_main_t *sm, vlib_node_runtime_t *node,
dm0 = snat_det_map_by_user(sm, &in_addr);
if (PREDICT_FALSE(!dm0))
{
- clib_warning("no match for internal host %U",
- format_ip4_address, &in_addr);
+ nat_log_info ("no match for internal host %U",
+ format_ip4_address, &in_addr);
if (PREDICT_FALSE(snat_not_translate_fast(sm, node, sw_if_index0, ip0,
IP_PROTOCOL_ICMP, rx_fib_index0)))
{
@@ -3568,11 +3538,12 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
{
snat_main_t *sm = &snat_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
- u32 n_left_from, *from, *to_next = 0;
+ u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0;
static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index;
static __thread vlib_frame_queue_t **congested_handoff_queue_by_worker_index
= 0;
vlib_frame_queue_elt_t *hf = 0;
+ vlib_frame_queue_t *fq;
vlib_frame_t *f = 0;
int i;
u32 n_left_to_next_worker = 0, *to_next_worker = 0;
@@ -3581,6 +3552,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
u32 thread_index = vlib_get_thread_index ();
u32 fq_index;
u32 to_node_index;
+ vlib_frame_t *d = 0;
ASSERT (vec_len (sm->workers));
@@ -3600,7 +3572,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1);
vec_validate_init_empty (congested_handoff_queue_by_worker_index,
- sm->first_worker_index + sm->num_workers - 1,
+ tm->n_vlib_mains - 1,
(vlib_frame_queue_t *) (~0));
}
@@ -3635,6 +3607,26 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
if (next_worker_index != current_worker_index)
{
+ fq = is_vlib_frame_queue_congested (
+ fq_index, next_worker_index, NAT_FQ_NELTS - 2,
+ congested_handoff_queue_by_worker_index);
+
+ if (fq)
+ {
+ /* if this is 1st frame */
+ if (!d)
+ {
+ d = vlib_get_frame_to_node (vm, sm->error_node_index);
+ to_next_drop = vlib_frame_vector_args (d);
+ }
+
+ to_next_drop[0] = bi0;
+ to_next_drop += 1;
+ d->n_vectors++;
+ b0->error = node->errors[SNAT_IN2OUT_ERROR_FQ_CONGESTED];
+ goto trace0;
+ }
+
if (hf)
hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
@@ -3676,6 +3668,7 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
f->n_vectors++;
}
+trace0:
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
{
@@ -3689,6 +3682,9 @@ snat_in2out_worker_handoff_fn_inline (vlib_main_t * vm,
if (f)
vlib_put_frame_to_node (vm, to_node_index, f);
+ if (d)
+ vlib_put_frame_to_node (vm, sm->error_node_index, d);
+
if (hf)
hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
@@ -3733,6 +3729,9 @@ VLIB_REGISTER_NODE (snat_in2out_worker_handoff_node) = {
.format_trace = format_snat_in2out_worker_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(snat_in2out_error_strings),
+ .error_strings = snat_in2out_error_strings,
+
.n_next_nodes = 1,
.next_nodes = {
diff --git a/src/plugins/nat/nat.c b/src/plugins/nat/nat.c
index 8ebec585d8a..1d493a6d346 100755
--- a/src/plugins/nat/nat.c
+++ b/src/plugins/nat/nat.c
@@ -27,6 +27,7 @@
#include <nat/nat66.h>
#include <nat/dslite.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/fib_table.h>
#include <vnet/fib/ip4_fib.h>
@@ -164,7 +165,7 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index)
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &ed_kv, 0))
- clib_warning ("in2out_ed key del failed");
+ nat_log_warn ("in2out_ed key del failed");
return;
}
@@ -189,7 +190,7 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index)
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &ed_kv, 0))
- clib_warning ("out2in_ed key del failed");
+ nat_log_warn ("out2in_ed key del failed");
ed_key.l_addr = s->in2out.addr;
ed_key.fib_index = s->in2out.fib_index;
@@ -203,7 +204,7 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index)
ed_kv.key[0] = ed_key.as_u64[0];
ed_kv.key[1] = ed_key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &ed_kv, 0))
- clib_warning ("in2out_ed key del failed");
+ nat_log_warn ("in2out_ed key del failed");
}
if (snat_is_unk_proto_session (s))
@@ -240,10 +241,10 @@ nat_free_session_data (snat_main_t * sm, snat_session_t * s, u32 thread_index)
/* Session lookup tables */
kv.key = s->in2out.as_u64;
if (clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0))
- clib_warning ("in2out key del failed");
+ nat_log_warn ("in2out key del failed");
kv.key = s->out2in.as_u64;
if (clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0))
- clib_warning ("out2in key del failed");
+ nat_log_warn ("out2in key del failed");
if (snat_is_session_static (s))
return;
@@ -287,7 +288,7 @@ nat_user_get_or_create (snat_main_t *sm, ip4_address_t *addr, u32 fib_index,
/* add user */
if (clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 1))
- clib_warning ("user_hash keay add failed");
+ nat_log_warn ("user_hash keay add failed");
}
else
{
@@ -367,6 +368,24 @@ nat_session_alloc_or_recycle (snat_main_t *sm, snat_user_t *u, u32 thread_index)
return s;
}
+typedef struct {
+ u8 next_in2out;
+} nat44_classify_trace_t;
+
+static u8 * format_nat44_classify_trace (u8 * s, va_list * args)
+{
+ CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
+ CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
+ nat44_classify_trace_t *t = va_arg (*args, nat44_classify_trace_t *);
+ char *next;
+
+ next = t->next_in2out ? "nat44-in2out" : "nat44-out2in";
+
+ s = format (s, "nat44-classify: next %s", next);
+
+ return s;
+}
+
static inline uword
nat44_classify_node_fn_inline (vlib_main_t * vm,
vlib_node_runtime_t * node,
@@ -445,6 +464,14 @@ nat44_classify_node_fn_inline (vlib_main_t * vm,
}
enqueue0:
+ if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
+ && (b0->flags & VLIB_BUFFER_IS_TRACED)))
+ {
+ nat44_classify_trace_t *t =
+ vlib_add_trace (vm, node, b0, sizeof (*t));
+ t->next_in2out = next0 == NAT44_CLASSIFY_NEXT_IN2OUT ? 1 : 0;
+ }
+
/* verify speculative enqueue, maybe switch current next frame */
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next,
@@ -469,6 +496,7 @@ VLIB_REGISTER_NODE (nat44_classify_node) = {
.function = nat44_classify_node_fn,
.name = "nat44-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
@@ -492,6 +520,7 @@ VLIB_REGISTER_NODE (nat44_det_classify_node) = {
.function = nat44_det_classify_node_fn,
.name = "nat44-det-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
@@ -515,6 +544,7 @@ VLIB_REGISTER_NODE (nat44_handoff_classify_node) = {
.function = nat44_handoff_classify_node_fn,
.name = "nat44-handoff-classify",
.vector_size = sizeof (u32),
+ .format_trace = format_nat44_classify_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
.n_next_nodes = NAT44_CLASSIFY_N_NEXT,
.next_nodes = {
@@ -859,7 +889,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
@@ -931,7 +961,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 1))
- clib_warning ("in2out key add failed");
+ nat_log_warn ("in2out key add failed");
}
m_key.addr = m->external_addr;
@@ -946,7 +976,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
- clib_warning ("out2in key add failed");
+ nat_log_warn ("out2in key add failed");
}
/* Delete dynamic sessions matching local address (+ local port) */
@@ -979,10 +1009,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
continue;
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
if (!addr_only)
break;
@@ -1023,7 +1050,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
@@ -1049,7 +1076,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
- clib_warning ("in2out key del failed");
+ nat_log_warn ("in2out key del failed");
}
m_key.addr = m->external_addr;
@@ -1063,7 +1090,7 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
kv.key = m_key.as_u64;
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
- clib_warning ("out2in key del failed");
+ nat_log_warn ("out2in key del failed");
}
/* Delete session(s) for static mapping if exist */
@@ -1104,15 +1131,12 @@ int snat_add_static_mapping(ip4_address_t l_addr, ip4_address_t e_addr,
continue;
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nstaticsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
if (!addr_only)
break;
}
- if (addr_only && (u->nstaticsessions == 0))
+ if (addr_only && (u->nstaticsessions == 0) && (u->nsessions == 0))
{
pool_put (tsm->users, u);
clib_bihash_add_del_8_8 (&tsm->user_hash, &kv, 0);
@@ -1246,7 +1270,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
@@ -1277,7 +1301,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.value = m - sm->static_mappings;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 1))
{
- clib_warning ("static_mapping_by_external key add failed");
+ nat_log_err ("static_mapping_by_external key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1297,7 +1321,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 1))
{
- clib_warning ("out2in key add failed");
+ nat_log_err ("out2in key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1321,7 +1345,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.value = ~0ULL;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 1))
{
- clib_warning ("in2out key add failed");
+ nat_log_err ("in2out key add failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
@@ -1355,7 +1379,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return VNET_API_ERROR_INVALID_VALUE_2;
}
break;
@@ -1371,7 +1395,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_external, &kv, 0))
{
- clib_warning ("static_mapping_by_external key del failed");
+ nat_log_err ("static_mapping_by_external key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1379,7 +1403,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&tsm->out2in, &kv, 0))
{
- clib_warning ("outi2in key del failed");
+ nat_log_err ("outi2in key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
@@ -1393,7 +1417,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&sm->static_mapping_by_local, &kv, 0))
{
- clib_warning ("static_mapping_by_local key del failed");
+ nat_log_err ("static_mapping_by_local key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
@@ -1404,7 +1428,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
kv.key = m_key.as_u64;
if (clib_bihash_add_del_8_8(&tsm->in2out, &kv, 0))
{
- clib_warning ("in2out key del failed");
+ nat_log_err ("in2out key del failed");
return VNET_API_ERROR_UNSPECIFIED;
}
}
@@ -1436,10 +1460,7 @@ int nat44_add_del_lb_static_mapping (ip4_address_t e_addr, u16 e_port,
continue;
nat_free_session_data (sm, s, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
- u->nstaticsessions--;
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
}
}
}
@@ -1460,9 +1481,6 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm,
snat_address_t *a = 0;
snat_session_t *ses;
u32 *ses_to_be_removed = 0, *ses_index;
- clib_bihash_kv_8_8_t kv, value;
- snat_user_key_t user_key;
- snat_user_t *u;
snat_main_per_thread_data_t *tsm;
snat_static_mapping_t *m;
snat_interface_t *interface;
@@ -1498,7 +1516,7 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm,
/* Check if address is used in some static mapping */
if (is_snat_address_used_in_static_mapping(sm, addr))
{
- clib_warning ("address used in static mapping");
+ nat_log_notice ("address used in static mapping");
return VNET_API_ERROR_UNSPECIFIED;
}
}
@@ -1517,25 +1535,15 @@ snat_del_address (snat_main_t *sm, ip4_address_t addr, u8 delete_sm,
{
ses->outside_address_index = ~0;
nat_free_session_data (sm, ses, tsm - sm->per_thread_data);
- clib_dlist_remove (tsm->list_pool, ses->per_user_index);
- pool_put_index (tsm->list_pool, ses->per_user_index);
vec_add1 (ses_to_be_removed, ses - tsm->sessions);
- user_key.addr = ses->in2out.addr;
- user_key.fib_index = ses->in2out.fib_index;
- kv.key = user_key.as_u64;
- if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
- {
- u = pool_elt_at_index (tsm->users, value.value);
- if (snat_is_session_static (ses))
- u->nstaticsessions--;
- else
- u->nsessions--;
- }
}
}));
vec_foreach (ses_index, ses_to_be_removed)
- pool_put_index (tsm->sessions, ses_index[0]);
+ {
+ ses = pool_elt_at_index (tsm->sessions, ses_index[0]);
+ nat44_delete_session (sm, ses, tsm - sm->per_thread_data);
+ }
vec_free (ses_to_be_removed);
}
@@ -1601,10 +1609,12 @@ int snat_interface_add_del (u32 sw_if_index, u8 is_inside, int is_del)
}
if (sm->fq_in2out_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index, 0);
+ sm->fq_in2out_index = vlib_frame_queue_main_init (sm->in2out_node_index,
+ NAT_FQ_NELTS);
if (sm->fq_out2in_index == ~0 && !sm->deterministic && sm->num_workers > 1)
- sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index, 0);
+ sm->fq_out2in_index = vlib_frame_queue_main_init (sm->out2in_node_index,
+ NAT_FQ_NELTS);
pool_foreach (i, sm->interfaces,
({
@@ -1895,6 +1905,7 @@ static clib_error_t * snat_init (vlib_main_t * vm)
uword *bitmap = 0;
u32 i;
ip4_add_del_interface_address_callback_t cb4;
+ vlib_node_t * error_drop_node;
sm->vlib_main = vm;
sm->vnet_main = vnet_get_main();
@@ -1915,6 +1926,9 @@ static clib_error_t * snat_init (vlib_main_t * vm)
sm->icmp_timeout = SNAT_ICMP_TIMEOUT;
sm->alloc_addr_and_port = nat_alloc_addr_and_port_default;
sm->forwarding_enabled = 0;
+ sm->log_class = vlib_log_register_class ("nat", 0);
+ error_drop_node = vlib_get_node_by_name (vm, (u8 *) "error-drop");
+ sm->error_node_index = error_drop_node->index;
p = hash_get_mem (tm->thread_registrations_by_name, "workers");
if (p)
@@ -2003,7 +2017,7 @@ void snat_free_outside_address_and_port (snat_address_t * addresses,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown_protocol");
+ nat_log_info ("unknown protocol");
return;
}
}
@@ -2179,7 +2193,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
@@ -2211,7 +2225,7 @@ nat_alloc_addr_and_port_default (snat_address_t * addresses,
foreach_snat_protocol
#undef _
default:
- clib_warning ("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
}
@@ -2264,7 +2278,7 @@ nat_alloc_addr_and_port_mape (snat_address_t * addresses,
foreach_snat_protocol
#undef _
default:
- clib_warning("unknown protocol");
+ nat_log_info ("unknown protocol");
return 1;
}
@@ -2330,6 +2344,65 @@ format_snat_protocol (u8 * s, va_list * args)
return s;
}
+u8 * format_snat_key (u8 * s, va_list * args);
+
+u8 *
+format_session_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_session_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U session-index %llu", format_snat_key, &k, v->value);
+
+ return s;
+}
+
+u8 *
+format_static_mapping_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_session_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U static-mapping-index %llu", format_snat_key, &k, v->value);
+
+ return s;
+}
+
+u8 *
+format_user_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_8_8_t *v = va_arg (*args, clib_bihash_kv_8_8_t *);
+ snat_user_key_t k;
+
+ k.as_u64 = v->key;
+
+ s = format (s, "%U fib %d user-index %llu", format_ip4_address, &k.addr,
+ k.fib_index, v->value);
+
+ return s;
+}
+
+u8 *
+format_ed_session_kvp (u8 * s, va_list * args)
+{
+ clib_bihash_kv_16_8_t *v = va_arg (*args, clib_bihash_kv_16_8_t *);
+ nat_ed_ses_key_t k;
+
+ k.as_u64[0] = v->key[0];
+ k.as_u64[1] = v->key[1];
+
+ s = format (s, "local %U:%d remote %U:%d proto %U fib %d session-index %llu",
+ format_ip4_address, &k.l_addr, clib_net_to_host_u16 (k.l_port),
+ format_ip4_address, &k.r_addr, clib_net_to_host_u16 (k.r_port),
+ format_ip_protocol, k.proto, k.fib_index, v->value);
+
+ return s;
+}
+
static u32
snat_get_worker_in2out_cb (ip4_header_t * ip0, u32 rx_fib_index0)
{
@@ -2615,19 +2688,29 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
{
clib_bihash_init_8_8 (&tsm->in2out, "in2out", translation_buckets,
translation_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->in2out,
+ format_session_kvp);
clib_bihash_init_8_8 (&tsm->out2in, "out2in", translation_buckets,
translation_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->out2in,
+ format_session_kvp);
clib_bihash_init_8_8 (&tsm->user_hash, "users", user_buckets,
user_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&tsm->user_hash,
+ format_user_kvp);
}
clib_bihash_init_16_8 (&sm->in2out_ed, "in2out-ed",
translation_buckets, translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->in2out_ed,
+ format_ed_session_kvp);
clib_bihash_init_16_8 (&sm->out2in_ed, "out2in-ed",
translation_buckets, translation_memory_size);
+ clib_bihash_set_kvp_format_fn_16_8 (&sm->out2in_ed,
+ format_ed_session_kvp);
}
else
{
@@ -2637,10 +2720,14 @@ snat_config (vlib_main_t * vm, unformat_input_t * input)
clib_bihash_init_8_8 (&sm->static_mapping_by_local,
"static_mapping_by_local", static_mapping_buckets,
static_mapping_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_local,
+ format_static_mapping_kvp);
clib_bihash_init_8_8 (&sm->static_mapping_by_external,
"static_mapping_by_external", static_mapping_buckets,
static_mapping_memory_size);
+ clib_bihash_set_kvp_format_fn_8_8 (&sm->static_mapping_by_external,
+ format_static_mapping_kvp);
}
return 0;
@@ -2678,7 +2765,7 @@ u8 * format_snat_key (u8 * s, va_list * args)
u8 * format_snat_session (u8 * s, va_list * args)
{
- snat_main_t * sm __attribute__((unused)) = va_arg (*args, snat_main_t *);
+ snat_main_per_thread_data_t * sm = va_arg (*args, snat_main_per_thread_data_t *);
snat_session_t * sess = va_arg (*args, snat_session_t *);
if (snat_is_unk_proto_session (sess))
@@ -2715,6 +2802,7 @@ u8 * format_snat_session (u8 * s, va_list * args)
clib_net_to_host_u16 (sess->ext_host_port));
}
}
+ s = format (s, " index %llu\n", sess - sm->sessions);
s = format (s, " last heard %.2f\n", sess->last_heard);
s = format (s, " total pkts %d, total bytes %lld\n",
sess->total_pkts, sess->total_bytes);
@@ -2724,7 +2812,7 @@ u8 * format_snat_session (u8 * s, va_list * args)
s = format (s, " dynamic translation\n");
if (is_fwd_bypass_session (sess))
s = format (s, " forwarding-bypass\n");
- if (sess->flags & SNAT_SESSION_FLAG_LOAD_BALANCING)
+ if (is_lb_session (sess))
s = format (s, " load-balancing\n");
if (is_twice_nat_session (sess))
s = format (s, " twice-nat\n");
@@ -2931,7 +3019,7 @@ match:
!is_delete,
0, 0, rp->tag);
if (rv)
- clib_warning ("snat_add_static_mapping returned %d", rv);
+ nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
static void
@@ -3002,8 +3090,7 @@ match:
rp->is_add,
0, 0, rp->tag);
if (rv)
- clib_warning ("snat_add_static_mapping returned %d",
- rv);
+ nat_log_notice ("snat_add_static_mapping returned %d", rv);
}
}
return;
@@ -3093,8 +3180,6 @@ nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port,
snat_session_key_t key;
snat_session_t *s;
clib_bihash_8_8_t *t;
- snat_user_key_t u_key;
- snat_user_t *u;
ip.dst_address.as_u32 = ip.src_address.as_u32 = addr->as_u32;
if (sm->num_workers > 1)
@@ -3116,24 +3201,8 @@ nat44_del_session (snat_main_t *sm, ip4_address_t *addr, u16 port,
return VNET_API_ERROR_UNSPECIFIED;
s = pool_elt_at_index (tsm->sessions, value.value);
- kv.key = s->in2out.as_u64;
- clib_bihash_add_del_8_8 (&tsm->in2out, &kv, 0);
- kv.key = s->out2in.as_u64;
- clib_bihash_add_del_8_8 (&tsm->out2in, &kv, 0);
- u_key.addr = s->in2out.addr;
- u_key.fib_index = s->in2out.fib_index;
- kv.key = u_key.as_u64;
- if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
- {
- u = pool_elt_at_index (tsm->users, value.value);
- if (snat_is_session_static (s))
- u->nstaticsessions--;
- else
- u->nsessions--;
- }
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- pool_put_index (tsm->list_pool, s->per_user_index);
- pool_put (tsm->sessions, s);
+ nat_free_session_data (sm, s, tsm - sm->per_thread_data);
+ nat44_delete_session (sm, s, tsm - sm->per_thread_data);
return 0;
}
diff --git a/src/plugins/nat/nat.h b/src/plugins/nat/nat.h
index f889976dd52..9de65d97e03 100644
--- a/src/plugins/nat/nat.h
+++ b/src/plugins/nat/nat.h
@@ -28,6 +28,7 @@
#include <vppinfra/dlist.h>
#include <vppinfra/error.h>
#include <vlibapi/api.h>
+#include <vlib/log.h>
#define SNAT_UDP_TIMEOUT 300
@@ -37,6 +38,8 @@
#define SNAT_TCP_INCOMING_SYN 6
#define SNAT_ICMP_TIMEOUT 60
+#define NAT_FQ_NELTS 64
+
#define SNAT_FLAG_HAIRPINNING (1 << 0)
/* Key */
@@ -131,7 +134,7 @@ typedef enum {
#define NAT44_SES_I2O_FIN_ACK 4
#define NAT44_SES_O2I_FIN_ACK 8
-#define nat44_is_ses_closed(s) (s->state == 0xf)
+#define nat44_is_ses_closed(s) s->state == 0xf
#define SNAT_SESSION_FLAG_STATIC_MAPPING 1
#define SNAT_SESSION_FLAG_UNKNOWN_PROTO 2
@@ -370,6 +373,7 @@ typedef struct snat_main_s {
u32 in2out_node_index;
u32 in2out_output_node_index;
u32 out2in_node_index;
+ u32 error_node_index;
/* Deterministic NAT */
snat_det_map_t * det_maps;
@@ -402,6 +406,9 @@ typedef struct snat_main_s {
/* API message ID base */
u16 msg_id_base;
+ /* log class */
+ vlib_log_class_t log_class;
+
/* convenience */
vlib_main_t * vlib_main;
vnet_main_t * vnet_main;
@@ -453,6 +460,7 @@ void snat_add_del_addr_to_fib (ip4_address_t * addr,
format_function_t format_snat_user;
format_function_t format_snat_static_mapping;
format_function_t format_snat_static_map_to_resolve;
+format_function_t format_snat_session;
format_function_t format_det_map_ses;
typedef struct {
@@ -499,6 +507,17 @@ typedef struct {
#define nat_interface_is_inside(i) i->flags & NAT_INTERFACE_FLAG_IS_INSIDE
#define nat_interface_is_outside(i) i->flags & NAT_INTERFACE_FLAG_IS_OUTSIDE
+#define nat_log_err(...) \
+ vlib_log(VLIB_LOG_LEVEL_ERR, snat_main.log_class, __VA_ARGS__)
+#define nat_log_warn(...) \
+ vlib_log(VLIB_LOG_LEVEL_WARNING, snat_main.log_class, __VA_ARGS__)
+#define nat_log_notice(...) \
+ vlib_log(VLIB_LOG_LEVEL_NOTICE, snat_main.log_class, __VA_ARGS__)
+#define nat_log_info(...) \
+ vlib_log(VLIB_LOG_LEVEL_INFO, snat_main.log_class, __VA_ARGS__)
+#define nat_log_debug(...)\
+ vlib_log(VLIB_LOG_LEVEL_DEBUG, snat_main.log_class, __VA_ARGS__)
+
/*
* Why is this here? Because we don't need to touch this layer to
* simply reply to an icmp. We need to change id to a unique
@@ -510,31 +529,6 @@ typedef struct {
u16 sequence;
} icmp_echo_header_t;
-always_inline u32
-ip_proto_to_snat_proto (u8 ip_proto)
-{
- u32 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;
- snat_proto = (ip_proto == IP_PROTOCOL_ICMP6) ? 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;
-}
-
typedef struct {
u16 src_port, dst_port;
} tcp_udp_header_t;
@@ -609,165 +603,4 @@ void nat_set_alloc_addr_and_port_mape (u16 psid, u16 psid_offset,
u16 psid_length);
void nat_set_alloc_addr_and_port_default (void);
-static_always_inline u8
-icmp_is_error_message (icmp46_header_t * icmp)
-{
- switch(icmp->type)
- {
- case ICMP4_destination_unreachable:
- case ICMP4_time_exceeded:
- case ICMP4_parameter_problem:
- case ICMP4_source_quench:
- case ICMP4_redirect:
- case ICMP4_alternate_host_address:
- return 1;
- }
- return 0;
-}
-
-static_always_inline u8
-is_interface_addr(snat_main_t *sm, vlib_node_runtime_t *node, u32 sw_if_index0,
- u32 ip4_addr)
-{
- snat_runtime_t *rt = (snat_runtime_t *) node->runtime_data;
- ip4_address_t * first_int_addr;
-
- if (PREDICT_FALSE(rt->cached_sw_if_index != sw_if_index0))
- {
- first_int_addr =
- ip4_interface_first_address (sm->ip4_main, sw_if_index0,
- 0 /* just want the address */);
- rt->cached_sw_if_index = sw_if_index0;
- if (first_int_addr)
- rt->cached_ip4_address = first_int_addr->as_u32;
- else
- rt->cached_ip4_address = 0;
- }
-
- if (PREDICT_FALSE(ip4_addr == rt->cached_ip4_address))
- return 1;
- else
- return 0;
-}
-
-always_inline u8
-maximum_sessions_exceeded (snat_main_t *sm, u32 thread_index)
-{
- if (pool_elts (sm->per_thread_data[thread_index].sessions) >= sm->max_translations)
- return 1;
-
- return 0;
-}
-
-static_always_inline void
-nat_send_all_to_node(vlib_main_t *vm, u32 *bi_vector,
- vlib_node_runtime_t *node, vlib_error_t *error, u32 next)
-{
- u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
-
- from = bi_vector;
- n_left_from = vec_len(bi_vector);
- next_index = node->cached_next_index;
- while (n_left_from > 0) {
- vlib_get_next_frame(vm, node, next_index, to_next, n_left_to_next);
- while (n_left_from > 0 && n_left_to_next > 0) {
- u32 bi0 = to_next[0] = from[0];
- from += 1;
- n_left_from -= 1;
- to_next += 1;
- n_left_to_next -= 1;
- vlib_buffer_t *p0 = vlib_get_buffer(vm, bi0);
- p0->error = *error;
- vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next,
- n_left_to_next, bi0, next);
- }
- vlib_put_next_frame(vm, node, next_index, n_left_to_next);
- }
-}
-
-always_inline void
-user_session_increment(snat_main_t *sm, snat_user_t *u, u8 is_static)
-{
- if (u->nsessions + u->nstaticsessions < sm->max_translations_per_user)
- {
- if (is_static)
- u->nstaticsessions++;
- else
- u->nsessions++;
- }
-}
-
-always_inline void
-nat44_delete_session(snat_main_t * sm, snat_session_t * ses, u32 thread_index)
-{
- snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
- thread_index);
- clib_bihash_kv_8_8_t kv, value;
- snat_user_key_t u_key;
- snat_user_t *u;
- u_key.addr = ses->in2out.addr;
- u_key.fib_index = ses->in2out.fib_index;
- kv.key = u_key.as_u64;
- if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
- {
- u = pool_elt_at_index (tsm->users, value.value);
- if (snat_is_session_static(ses))
- u->nstaticsessions--;
- else
- u->nsessions--;
- }
- clib_dlist_remove (tsm->list_pool, ses->per_user_index);
- pool_put_index (tsm->list_pool, ses->per_user_index);
- pool_put (tsm->sessions, ses);
-}
-
-/** \brief Set TCP session state.
- @return 1 if session was closed, otherwise 0
-*/
-always_inline int
-nat44_set_tcp_session_state_i2o(snat_main_t * sm, snat_session_t * ses,
- tcp_header_t * tcp, u32 thread_index)
-{
- if (tcp->flags & TCP_FLAG_FIN)
- {
- ses->i2o_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
- ses->state |= NAT44_SES_I2O_FIN;
- }
- if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN))
- {
- if (clib_net_to_host_u32 (tcp->ack_number) > ses->o2i_fin_seq)
- ses->state |= NAT44_SES_O2I_FIN_ACK;
- }
- if (nat44_is_ses_closed (ses))
- {
- nat_free_session_data (sm, ses, thread_index);
- nat44_delete_session (sm, ses, thread_index);
- return 1;
- }
- return 0;
-}
-
-always_inline int
-nat44_set_tcp_session_state_o2i(snat_main_t * sm, snat_session_t * ses,
- tcp_header_t * tcp, u32 thread_index)
-{
- if (tcp->flags & TCP_FLAG_FIN)
- {
- ses->o2i_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
- ses->state |= NAT44_SES_O2I_FIN;
- }
- if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN))
- {
- if (clib_net_to_host_u32 (tcp->ack_number) > ses->i2o_fin_seq)
- ses->state |= NAT44_SES_I2O_FIN_ACK;
- }
- if (nat44_is_ses_closed (ses))
- {
- nat_free_session_data (sm, ses, thread_index);
- nat44_delete_session (sm, ses, thread_index);
- return 1;
- }
- return 0;
-}
-
#endif /* __included_snat_h__ */
diff --git a/src/plugins/nat/nat44_cli.c b/src/plugins/nat/nat44_cli.c
index efde4be284c..7a8be98c6fe 100644
--- a/src/plugins/nat/nat44_cli.c
+++ b/src/plugins/nat/nat44_cli.c
@@ -20,6 +20,7 @@
#include <nat/nat.h>
#include <nat/nat_ipfix_logging.h>
#include <nat/nat_det.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/fib_table.h>
#define UNSUPPORTED_IN_DET_MODE_STR \
@@ -181,6 +182,8 @@ nat44_show_hash_commnad_fn (vlib_main_t * vm, unformat_input_t * input,
vec_foreach_index (i, sm->per_thread_data)
{
tsm = vec_elt_at_index (sm->per_thread_data, i);
+ vlib_cli_output (vm, "-------- thread %d %s --------\n",
+ i, vlib_worker_threads[i].name);
vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->in2out, verbose);
vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->out2in, verbose);
vlib_cli_output (vm, "%U", format_bihash_8_8, &tsm->user_hash, verbose);
@@ -292,7 +295,7 @@ add_address_command_fn (vlib_main_t * vm,
count = (end_host_order - start_host_order) + 1;
if (count > 1024)
- clib_warning ("%U - %U, %d addresses...",
+ nat_log_info ("%U - %U, %d addresses...",
format_ip4_address, &start_addr,
format_ip4_address, &end_addr, count);
@@ -942,6 +945,8 @@ nat44_show_sessions_command_fn (vlib_main_t * vm, unformat_input_t * input,
{
tsm = vec_elt_at_index (sm->per_thread_data, i);
+ vlib_cli_output (vm, "-------- thread %d %s --------\n",
+ i, vlib_worker_threads[i].name);
pool_foreach (u, tsm->users,
({
vlib_cli_output (vm, " %U", format_snat_user, tsm, u, verbose);
diff --git a/src/plugins/nat/nat64.c b/src/plugins/nat/nat64.c
index 0b7536f21a7..53c2caba2fa 100644
--- a/src/plugins/nat/nat64.c
+++ b/src/plugins/nat/nat64.c
@@ -20,6 +20,7 @@
#include <nat/nat64.h>
#include <nat/nat64_db.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/ip4_fib.h>
#include <vppinfra/crc32.h>
diff --git a/src/plugins/nat/nat64_cli.c b/src/plugins/nat/nat64_cli.c
index 5b46feddb49..c2639f4fb16 100644
--- a/src/plugins/nat/nat64_cli.c
+++ b/src/plugins/nat/nat64_cli.c
@@ -19,6 +19,7 @@
#include <nat/nat64.h>
#include <nat/nat.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/fib_table.h>
static clib_error_t *
diff --git a/src/plugins/nat/nat64_db.c b/src/plugins/nat/nat64_db.c
index 3edc1a43006..9ff68c80282 100644
--- a/src/plugins/nat/nat64_db.c
+++ b/src/plugins/nat/nat64_db.c
@@ -18,6 +18,7 @@
*/
#include <nat/nat64_db.h>
#include <nat/nat_ipfix_logging.h>
+#include <nat/nat_inlines.h>
#include <vnet/fib/fib_table.h>
int
diff --git a/src/plugins/nat/nat64_in2out.c b/src/plugins/nat/nat64_in2out.c
index ef322d5b60d..603b30ee11a 100644
--- a/src/plugins/nat/nat64_in2out.c
+++ b/src/plugins/nat/nat64_in2out.c
@@ -19,6 +19,7 @@
#include <nat/nat64.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vnet/ip/ip6_to_ip4.h>
#include <vnet/fib/fib_table.h>
diff --git a/src/plugins/nat/nat64_out2in.c b/src/plugins/nat/nat64_out2in.c
index 17513c5efb8..f43d3e081b4 100644
--- a/src/plugins/nat/nat64_out2in.c
+++ b/src/plugins/nat/nat64_out2in.c
@@ -19,6 +19,7 @@
#include <nat/nat64.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vnet/ip/ip4_to_ip6.h>
#include <vnet/fib/ip4_fib.h>
#include <vnet/udp/udp.h>
diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c
index 11a6f0fee04..f5f41619b33 100644
--- a/src/plugins/nat/nat_api.c
+++ b/src/plugins/nat/nat_api.c
@@ -24,6 +24,7 @@
#include <nat/nat66.h>
#include <nat/dslite.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vlibapi/api.h>
#include <vlibmemory/api.h>
@@ -444,7 +445,7 @@ static void
vrf_id = clib_host_to_net_u32 (mp->vrf_id);
if (count > 1024)
- clib_warning ("%U - %U, %d addresses...",
+ nat_log_info ("%U - %U, %d addresses...",
format_ip4_address, mp->first_ip_address,
format_ip4_address, mp->last_ip_address, count);
diff --git a/src/plugins/nat/nat_inlines.h b/src/plugins/nat/nat_inlines.h
new file mode 100644
index 00000000000..db5b295f938
--- /dev/null
+++ b/src/plugins/nat/nat_inlines.h
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2018 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @brief The NAT inline functions
+ */
+
+#ifndef __included_nat_inlines_h__
+#define __included_nat_inlines_h__
+
+#include <nat/nat.h>
+
+always_inline u32
+ip_proto_to_snat_proto (u8 ip_proto)
+{
+ u32 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;
+ snat_proto =
+ (ip_proto == IP_PROTOCOL_ICMP6) ? 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;
+}
+
+static_always_inline u8
+icmp_is_error_message (icmp46_header_t * icmp)
+{
+ switch (icmp->type)
+ {
+ case ICMP4_destination_unreachable:
+ case ICMP4_time_exceeded:
+ case ICMP4_parameter_problem:
+ case ICMP4_source_quench:
+ case ICMP4_redirect:
+ case ICMP4_alternate_host_address:
+ return 1;
+ }
+ return 0;
+}
+
+always_inline u8
+is_interface_addr (snat_main_t * sm, vlib_node_runtime_t * node,
+ u32 sw_if_index0, u32 ip4_addr)
+{
+ snat_runtime_t *rt = (snat_runtime_t *) node->runtime_data;
+ ip4_address_t *first_int_addr;
+
+ if (PREDICT_FALSE (rt->cached_sw_if_index != sw_if_index0))
+ {
+ first_int_addr =
+ ip4_interface_first_address (sm->ip4_main, sw_if_index0,
+ 0 /* just want the address */ );
+ rt->cached_sw_if_index = sw_if_index0;
+ if (first_int_addr)
+ rt->cached_ip4_address = first_int_addr->as_u32;
+ else
+ rt->cached_ip4_address = 0;
+ }
+
+ if (PREDICT_FALSE (ip4_addr == rt->cached_ip4_address))
+ return 1;
+ else
+ return 0;
+}
+
+always_inline u8
+maximum_sessions_exceeded (snat_main_t * sm, u32 thread_index)
+{
+ if (pool_elts (sm->per_thread_data[thread_index].sessions) >=
+ sm->max_translations)
+ return 1;
+
+ return 0;
+}
+
+always_inline void
+nat_send_all_to_node (vlib_main_t * vm, u32 * bi_vector,
+ vlib_node_runtime_t * node, vlib_error_t * error,
+ u32 next)
+{
+ u32 n_left_from, *from, next_index, *to_next, n_left_to_next;
+
+ from = bi_vector;
+ n_left_from = vec_len (bi_vector);
+ next_index = node->cached_next_index;
+ while (n_left_from > 0)
+ {
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
+ while (n_left_from > 0 && n_left_to_next > 0)
+ {
+ u32 bi0 = to_next[0] = from[0];
+ from += 1;
+ n_left_from -= 1;
+ to_next += 1;
+ n_left_to_next -= 1;
+ vlib_buffer_t *p0 = vlib_get_buffer (vm, bi0);
+ p0->error = *error;
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
+ n_left_to_next, bi0, next);
+ }
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
+ }
+}
+
+always_inline void
+user_session_increment (snat_main_t * sm, snat_user_t * u, u8 is_static)
+{
+ if (u->nsessions + u->nstaticsessions < sm->max_translations_per_user)
+ {
+ if (is_static)
+ u->nstaticsessions++;
+ else
+ u->nsessions++;
+ }
+}
+
+always_inline void
+nat44_delete_session (snat_main_t * sm, snat_session_t * ses,
+ u32 thread_index)
+{
+ snat_main_per_thread_data_t *tsm = vec_elt_at_index (sm->per_thread_data,
+ thread_index);
+ clib_bihash_kv_8_8_t kv, value;
+ snat_user_key_t u_key;
+ snat_user_t *u;
+
+ nat_log_debug ("session deleted %U", format_snat_session, tsm, ses);
+ u_key.addr = ses->in2out.addr;
+ u_key.fib_index = ses->in2out.fib_index;
+ kv.key = u_key.as_u64;
+ if (!clib_bihash_search_8_8 (&tsm->user_hash, &kv, &value))
+ {
+ u = pool_elt_at_index (tsm->users, value.value);
+ if (snat_is_session_static (ses))
+ u->nstaticsessions--;
+ else
+ u->nsessions--;
+ }
+ clib_dlist_remove (tsm->list_pool, ses->per_user_index);
+ pool_put_index (tsm->list_pool, ses->per_user_index);
+ pool_put (tsm->sessions, ses);
+}
+
+/** \brief Set TCP session state.
+ @return 1 if session was closed, otherwise 0
+*/
+always_inline int
+nat44_set_tcp_session_state_i2o (snat_main_t * sm, snat_session_t * ses,
+ tcp_header_t * tcp, u32 thread_index)
+{
+ if (tcp->flags & TCP_FLAG_FIN)
+ {
+ ses->i2o_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
+ ses->state |= NAT44_SES_I2O_FIN;
+ }
+ if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_O2I_FIN))
+ {
+ if (clib_net_to_host_u32 (tcp->ack_number) > ses->o2i_fin_seq)
+ ses->state |= NAT44_SES_O2I_FIN_ACK;
+ }
+ if (nat44_is_ses_closed (ses))
+ {
+ nat_log_debug ("TCP close connection %U", format_snat_session,
+ &sm->per_thread_data[thread_index], ses);
+ nat_free_session_data (sm, ses, thread_index);
+ nat44_delete_session (sm, ses, thread_index);
+ return 1;
+ }
+ return 0;
+}
+
+always_inline int
+nat44_set_tcp_session_state_o2i (snat_main_t * sm, snat_session_t * ses,
+ tcp_header_t * tcp, u32 thread_index)
+{
+ if (tcp->flags & TCP_FLAG_FIN)
+ {
+ ses->o2i_fin_seq = clib_net_to_host_u32 (tcp->seq_number);
+ ses->state |= NAT44_SES_O2I_FIN;
+ }
+ if ((tcp->flags & TCP_FLAG_ACK) && (ses->state & NAT44_SES_I2O_FIN))
+ {
+ if (clib_net_to_host_u32 (tcp->ack_number) > ses->i2o_fin_seq)
+ ses->state |= NAT44_SES_I2O_FIN_ACK;
+ }
+ if (nat44_is_ses_closed (ses))
+ {
+ nat_log_debug ("TCP close connection %U", format_snat_session,
+ &sm->per_thread_data[thread_index], ses);
+ nat_free_session_data (sm, ses, thread_index);
+ nat44_delete_session (sm, ses, thread_index);
+ return 1;
+ }
+ return 0;
+}
+
+always_inline void
+nat44_session_update_counters (snat_session_t * s, f64 now, uword bytes)
+{
+ s->last_heard = now;
+ s->total_pkts++;
+ s->total_bytes += bytes;
+}
+
+/** \brief Per-user LRU list maintenance */
+always_inline void
+nat44_session_update_lru (snat_main_t * sm, snat_session_t * s,
+ u32 thread_index)
+{
+ clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
+ s->per_user_index);
+ clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
+ s->per_user_list_head_index, s->per_user_index);
+}
+
+#endif /* __included_nat_inlines_h__ */
+
+/*
+ * fd.io coding-style-patch-verification: ON
+ *
+ * Local Variables:
+ * eval: (c-set-style "gnu")
+ * End:
+ */
diff --git a/src/plugins/nat/nat_ipfix_logging.c b/src/plugins/nat/nat_ipfix_logging.c
index 0f291337b0c..4a61fb03f55 100644
--- a/src/plugins/nat/nat_ipfix_logging.c
+++ b/src/plugins/nat/nat_ipfix_logging.c
@@ -17,6 +17,7 @@
#include <vnet/ipfix-export/flow_report.h>
#include <vlibmemory/api.h>
+#include <nat/nat_inlines.h>
#include <nat/nat_ipfix_logging.h>
snat_ipfix_logging_main_t snat_ipfix_logging_main;
diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c
index c7eece8897c..83e1426a413 100755
--- a/src/plugins/nat/out2in.c
+++ b/src/plugins/nat/out2in.c
@@ -26,6 +26,7 @@
#include <nat/nat_ipfix_logging.h>
#include <nat/nat_det.h>
#include <nat/nat_reass.h>
+#include <nat/nat_inlines.h>
#include <vppinfra/hash.h>
#include <vppinfra/error.h>
@@ -113,7 +114,8 @@ _(NO_TRANSLATION, "No translation") \
_(MAX_SESSIONS_EXCEEDED, "Maximum sessions exceeded") \
_(DROP_FRAGMENT, "Drop fragment") \
_(MAX_REASS, "Maximum reassemblies exceeded") \
-_(MAX_FRAG, "Maximum fragments per reassembly exceeded")
+_(MAX_FRAG, "Maximum fragments per reassembly exceeded")\
+_(FQ_CONGESTED, "Handoff frame queue congested")
typedef enum {
#define _(sym,str) SNAT_OUT2IN_ERROR_##sym,
@@ -168,6 +170,7 @@ create_session_for_static_mapping (snat_main_t *sm,
if (PREDICT_FALSE (maximum_sessions_exceeded(sm, thread_index)))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
+ nat_log_notice ("maximum sessions exceeded");
return 0;
}
@@ -177,14 +180,14 @@ create_session_for_static_mapping (snat_main_t *sm,
u = nat_user_get_or_create (sm, &in2out.addr, in2out.fib_index, thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return 0;
}
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return 0;
}
@@ -202,13 +205,13 @@ create_session_for_static_mapping (snat_main_t *sm,
kv0.value = s - sm->per_thread_data[thread_index].sessions;
if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].in2out, &kv0,
1 /* is_add */))
- clib_warning ("in2out key add failed");
+ nat_log_notice ("in2out key add failed");
kv0.key = s->out2in.as_u64;
if (clib_bihash_add_del_8_8 (&sm->per_thread_data[thread_index].out2in, &kv0,
1 /* is_add */))
- clib_warning ("out2in key add failed");
+ nat_log_notice ("out2in key add failed");
/* log NAT event */
snat_ipfix_logging_nat44_ses_create(s->in2out.addr.as_u32,
@@ -381,14 +384,14 @@ create_bypass_for_fwd(snat_main_t * sm, ip4_header_t * ip, u32 rx_fib_index,
u = nat_user_get_or_create (sm, &ip->dst_address, sm->inside_fib_index, thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return;
}
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return;
}
@@ -405,7 +408,7 @@ create_bypass_for_fwd(snat_main_t * sm, ip4_header_t * ip, u32 rx_fib_index,
kv.value = s - tsm->sessions;
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &kv, 1))
- clib_warning ("in2out_ed key add failed");
+ nat_log_notice ("in2out_ed key add failed");
}
if (ip->protocol == IP_PROTOCOL_TCP)
@@ -415,12 +418,9 @@ create_bypass_for_fwd(snat_main_t * sm, ip4_header_t * ip, u32 rx_fib_index,
return;
}
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
+ nat44_session_update_counters (s, now, 0);
}
/**
@@ -789,15 +789,10 @@ static inline u32 icmp_out2in_slow_path (snat_main_t *sm,
if (PREDICT_TRUE(next0 != SNAT_OUT2IN_NEXT_DROP && s0))
{
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (sm->vlib_main, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (sm->vlib_main, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
}
return next0;
}
@@ -844,6 +839,7 @@ snat_out2in_unknown_proto (snat_main_t *sm,
if (PREDICT_FALSE (maximum_sessions_exceeded(sm, thread_index)))
{
b->error = node->errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
+ nat_log_notice ("maximum sessions exceeded");
return 0;
}
@@ -866,7 +862,7 @@ snat_out2in_unknown_proto (snat_main_t *sm,
thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return 0;
}
@@ -874,7 +870,7 @@ snat_out2in_unknown_proto (snat_main_t *sm,
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return 0;
}
@@ -893,14 +889,14 @@ snat_out2in_unknown_proto (snat_main_t *sm,
/* Add to lookup tables */
s_kv.value = s - tsm->sessions;
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
- clib_warning ("out2in key add failed");
+ nat_log_notice ("out2in key add failed");
key.l_addr = ip->dst_address;
key.fib_index = m->fib_index;
s_kv.key[0] = key.as_u64[0];
s_kv.key[1] = key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1))
- clib_warning ("in2out key add failed");
+ nat_log_notice ("in2out key add failed");
}
/* Update IP checksum */
@@ -911,13 +907,10 @@ snat_out2in_unknown_proto (snat_main_t *sm,
vnet_buffer(b)->sw_if_index[VLIB_TX] = s->in2out.fib_index;
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
+ nat44_session_update_counters (s, now,
+ vlib_buffer_length_in_chain (vm, b));
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
return s;
}
@@ -969,6 +962,7 @@ snat_out2in_lb (snat_main_t *sm,
if (PREDICT_FALSE (maximum_sessions_exceeded(sm, thread_index)))
{
b->error = node->errors[SNAT_OUT2IN_ERROR_MAX_SESSIONS_EXCEEDED];
+ nat_log_notice ("maximum sessions exceeded");
return 0;
}
@@ -983,14 +977,14 @@ snat_out2in_lb (snat_main_t *sm,
thread_index);
if (!u)
{
- clib_warning ("create NAT user failed");
+ nat_log_warn ("create NAT user failed");
return 0;
}
s = nat_session_alloc_or_recycle (sm, u, thread_index);
if (!s)
{
- clib_warning ("create NAT session failed");
+ nat_log_warn ("create NAT session failed");
return 0;
}
@@ -1008,7 +1002,7 @@ snat_out2in_lb (snat_main_t *sm,
/* Add to lookup tables */
s_kv.value = s - tsm->sessions;
if (clib_bihash_add_del_16_8 (&sm->out2in_ed, &s_kv, 1))
- clib_warning ("out2in-ed key add failed");
+ nat_log_notice ("out2in-ed key add failed");
if (twice_nat == TWICE_NAT ||
(twice_nat == TWICE_NAT_SELF &&
@@ -1034,7 +1028,7 @@ snat_out2in_lb (snat_main_t *sm,
s_kv.key[0] = key.as_u64[0];
s_kv.key[1] = key.as_u64[1];
if (clib_bihash_add_del_16_8 (&sm->in2out_ed, &s_kv, 1))
- clib_warning ("in2out-ed key add failed");
+ nat_log_notice ("in2out-ed key add failed");
}
new_addr = ip->dst_address.as_u32 = s->in2out.addr.as_u32;
@@ -1085,13 +1079,9 @@ snat_out2in_lb (snat_main_t *sm,
}
/* Accounting */
- s->last_heard = now;
- s->total_pkts++;
- s->total_bytes += vlib_buffer_length_in_chain (vm, b);
+ nat44_session_update_counters (s, now, vlib_buffer_length_in_chain (vm, b));
/* Per-user LRU list maintenance */
- clib_dlist_remove (tsm->list_pool, s->per_user_index);
- clib_dlist_addtail (tsm->list_pool, s->per_user_list_head_index,
- s->per_user_index);
+ nat44_session_update_lru (sm, s, thread_index);
return s;
}
@@ -1321,15 +1311,10 @@ snat_out2in_node_fn (vlib_main_t * vm,
}
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace0:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -1499,15 +1484,10 @@ snat_out2in_node_fn (vlib_main_t * vm,
}
/* Accounting */
- s1->last_heard = now;
- s1->total_pkts++;
- s1->total_bytes += vlib_buffer_length_in_chain (vm, b1);
+ nat44_session_update_counters (s1, now,
+ vlib_buffer_length_in_chain (vm, b1));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s1->per_user_list_head_index,
- s1->per_user_index);
+ nat44_session_update_lru (sm, s1, thread_index);
trace1:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -1713,15 +1693,10 @@ snat_out2in_node_fn (vlib_main_t * vm,
}
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace00:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -1858,6 +1833,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
{
next0 = SNAT_OUT2IN_NEXT_DROP;
b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_REASS];
+ nat_log_notice ("maximum reassemblies exceeded");
goto trace0;
}
@@ -1934,6 +1910,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
if (nat_ip4_reass_add_fragment (reass0, bi0))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_FRAG];
+ nat_log_notice ("maximum fragments per reassembly exceeded");
next0 = SNAT_OUT2IN_NEXT_DROP;
goto trace0;
}
@@ -1982,15 +1959,10 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
}
/* Accounting */
- s0->last_heard = now;
- s0->total_pkts++;
- s0->total_bytes += vlib_buffer_length_in_chain (vm, b0);
+ nat44_session_update_counters (s0, now,
+ vlib_buffer_length_in_chain (vm, b0));
/* Per-user LRU list maintenance */
- clib_dlist_remove (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_index);
- clib_dlist_addtail (sm->per_thread_data[thread_index].list_pool,
- s0->per_user_list_head_index,
- s0->per_user_index);
+ nat44_session_update_lru (sm, s0, thread_index);
trace0:
if (PREDICT_FALSE((node->flags & VLIB_NODE_FLAG_TRACE)
@@ -2185,8 +2157,8 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
dm0 = snat_det_map_by_out(sm, &ip0->dst_address);
if (PREDICT_FALSE(!dm0))
{
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
+ nat_log_info ("unknown dst address: %U",
+ format_ip4_address, &ip0->dst_address);
next0 = SNAT_OUT2IN_NEXT_DROP;
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace0;
@@ -2198,12 +2170,12 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
ses0 = snat_det_get_ses_by_out (dm0, &new_addr0, key0.as_u64);
if (PREDICT_FALSE(!ses0))
{
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip0->src_address,
- clib_net_to_host_u16 (tcp0->src),
- format_ip4_address, &ip0->dst_address,
- clib_net_to_host_u16 (tcp0->dst),
- format_ip4_address, &new_addr0);
+ nat_log_info ("no match src %U:%d dst %U:%d for user %U",
+ format_ip4_address, &ip0->src_address,
+ clib_net_to_host_u16 (tcp0->src),
+ format_ip4_address, &ip0->dst_address,
+ clib_net_to_host_u16 (tcp0->dst),
+ format_ip4_address, &new_addr0);
next0 = SNAT_OUT2IN_NEXT_DROP;
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace0;
@@ -2301,8 +2273,8 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
dm1 = snat_det_map_by_out(sm, &ip1->dst_address);
if (PREDICT_FALSE(!dm1))
{
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip1->dst_address);
+ nat_log_info ("unknown dst address: %U",
+ format_ip4_address, &ip1->dst_address);
next1 = SNAT_OUT2IN_NEXT_DROP;
b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace1;
@@ -2314,12 +2286,12 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
ses1 = snat_det_get_ses_by_out (dm1, &new_addr1, key1.as_u64);
if (PREDICT_FALSE(!ses1))
{
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip1->src_address,
- clib_net_to_host_u16 (tcp1->src),
- format_ip4_address, &ip1->dst_address,
- clib_net_to_host_u16 (tcp1->dst),
- format_ip4_address, &new_addr1);
+ nat_log_info ("no match src %U:%d dst %U:%d for user %U",
+ format_ip4_address, &ip1->src_address,
+ clib_net_to_host_u16 (tcp1->src),
+ format_ip4_address, &ip1->dst_address,
+ clib_net_to_host_u16 (tcp1->dst),
+ format_ip4_address, &new_addr1);
next1 = SNAT_OUT2IN_NEXT_DROP;
b1->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace1;
@@ -2450,8 +2422,8 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
dm0 = snat_det_map_by_out(sm, &ip0->dst_address);
if (PREDICT_FALSE(!dm0))
{
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
+ nat_log_info ("unknown dst address: %U",
+ format_ip4_address, &ip0->dst_address);
next0 = SNAT_OUT2IN_NEXT_DROP;
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace00;
@@ -2463,12 +2435,12 @@ snat_det_out2in_node_fn (vlib_main_t * vm,
ses0 = snat_det_get_ses_by_out (dm0, &new_addr0, key0.as_u64);
if (PREDICT_FALSE(!ses0))
{
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &ip0->src_address,
- clib_net_to_host_u16 (tcp0->src),
- format_ip4_address, &ip0->dst_address,
- clib_net_to_host_u16 (tcp0->dst),
- format_ip4_address, &new_addr0);
+ nat_log_info ("no match src %U:%d dst %U:%d for user %U",
+ format_ip4_address, &ip0->src_address,
+ clib_net_to_host_u16 (tcp0->src),
+ format_ip4_address, &ip0->dst_address,
+ clib_net_to_host_u16 (tcp0->dst),
+ format_ip4_address, &new_addr0);
next0 = SNAT_OUT2IN_NEXT_DROP;
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
goto trace00;
@@ -2652,8 +2624,8 @@ u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node,
dont_translate = 1;
goto out;
}
- clib_warning("unknown dst address: %U",
- format_ip4_address, &ip0->dst_address);
+ nat_log_info ("unknown dst address: %U",
+ format_ip4_address, &ip0->dst_address);
goto out;
}
@@ -2670,12 +2642,12 @@ u32 icmp_match_out2in_det(snat_main_t *sm, vlib_node_runtime_t *node,
dont_translate = 1;
goto out;
}
- clib_warning("no match src %U:%d dst %U:%d for user %U",
- format_ip4_address, &key0.ext_host_addr,
- clib_net_to_host_u16 (key0.ext_host_port),
- format_ip4_address, &out_addr,
- clib_net_to_host_u16 (key0.out_port),
- format_ip4_address, &new_addr0);
+ nat_log_info ("no match src %U:%d dst %U:%d for user %U",
+ format_ip4_address, &key0.ext_host_addr,
+ clib_net_to_host_u16 (key0.ext_host_port),
+ format_ip4_address, &out_addr,
+ clib_net_to_host_u16 (key0.out_port),
+ format_ip4_address, &new_addr0);
b0->error = node->errors[SNAT_OUT2IN_ERROR_NO_TRANSLATION];
next0 = SNAT_OUT2IN_NEXT_DROP;
goto out;
@@ -2717,17 +2689,19 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
{
snat_main_t *sm = &snat_main;
vlib_thread_main_t *tm = vlib_get_thread_main ();
- u32 n_left_from, *from, *to_next = 0;
+ u32 n_left_from, *from, *to_next = 0, *to_next_drop = 0;
static __thread vlib_frame_queue_elt_t **handoff_queue_elt_by_worker_index;
static __thread vlib_frame_queue_t **congested_handoff_queue_by_worker_index
= 0;
vlib_frame_queue_elt_t *hf = 0;
+ vlib_frame_queue_t *fq;
vlib_frame_t *f = 0;
int i;
u32 n_left_to_next_worker = 0, *to_next_worker = 0;
u32 next_worker_index = 0;
u32 current_worker_index = ~0;
u32 thread_index = vlib_get_thread_index ();
+ vlib_frame_t *d = 0;
ASSERT (vec_len (sm->workers));
@@ -2736,7 +2710,7 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
vec_validate (handoff_queue_elt_by_worker_index, tm->n_vlib_mains - 1);
vec_validate_init_empty (congested_handoff_queue_by_worker_index,
- sm->first_worker_index + sm->num_workers - 1,
+ tm->n_vlib_mains - 1,
(vlib_frame_queue_t *) (~0));
}
@@ -2771,6 +2745,26 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
if (next_worker_index != current_worker_index)
{
+ fq = is_vlib_frame_queue_congested (
+ sm->fq_out2in_index, next_worker_index, NAT_FQ_NELTS - 2,
+ congested_handoff_queue_by_worker_index);
+
+ if (fq)
+ {
+ /* if this is 1st frame */
+ if (!d)
+ {
+ d = vlib_get_frame_to_node (vm, sm->error_node_index);
+ to_next_drop = vlib_frame_vector_args (d);
+ }
+
+ to_next_drop[0] = bi0;
+ to_next_drop += 1;
+ d->n_vectors++;
+ b0->error = node->errors[SNAT_OUT2IN_ERROR_FQ_CONGESTED];
+ goto trace0;
+ }
+
if (hf)
hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
@@ -2812,6 +2806,7 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
f->n_vectors++;
}
+trace0:
if (PREDICT_FALSE ((node->flags & VLIB_NODE_FLAG_TRACE)
&& (b0->flags & VLIB_BUFFER_IS_TRACED)))
{
@@ -2825,6 +2820,9 @@ snat_out2in_worker_handoff_fn (vlib_main_t * vm,
if (f)
vlib_put_frame_to_node (vm, sm->out2in_node_index, f);
+ if (d)
+ vlib_put_frame_to_node (vm, sm->error_node_index, d);
+
if (hf)
hf->n_vectors = VLIB_FRAME_SIZE - n_left_to_next_worker;
@@ -2861,6 +2859,9 @@ VLIB_REGISTER_NODE (snat_out2in_worker_handoff_node) = {
.format_trace = format_snat_out2in_worker_handoff_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
+ .n_errors = ARRAY_LEN(snat_out2in_error_strings),
+ .error_strings = snat_out2in_error_strings,
+
.n_next_nodes = 1,
.next_nodes = {
diff --git a/test/test_nat.py b/test/test_nat.py
index e2f34657d25..ad2b9649b7d 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -826,6 +826,7 @@ class TestNAT44(MethodHolder):
@classmethod
def setUpClass(cls):
super(TestNAT44, cls).setUpClass()
+ cls.vapi.cli("set log class nat level debug")
try:
cls.tcp_port_in = 6303
@@ -2582,7 +2583,8 @@ class TestNAT44(MethodHolder):
self.pg0.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(9)
ipfix = IPFIXDecoder()
@@ -2639,7 +2641,8 @@ class TestNAT44(MethodHolder):
self.pg0.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(9)
ipfix = IPFIXDecoder()
@@ -2698,7 +2701,7 @@ class TestNAT44(MethodHolder):
self.pg2.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
# remove addresses and verify
self.nat44_add_address(self.nat_addr, is_add=0)
@@ -2711,7 +2714,7 @@ class TestNAT44(MethodHolder):
self.pg1.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
p = (Ether(src=self.pg1.remote_mac, dst='ff:ff:ff:ff:ff:ff') /
ARP(op=ARP.who_has, pdst=static_addr,
@@ -2719,7 +2722,7 @@ class TestNAT44(MethodHolder):
self.pg1.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
def test_vrf_mode(self):
""" NAT44 tenant VRF aware address pool mode """
@@ -3117,7 +3120,7 @@ class TestNAT44(MethodHolder):
self.pg0.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg0.get_capture(1)
+ self.pg0.get_capture(1)
p = (Ether(dst=self.pg0.local_mac, src=host.mac) /
IP(src=host.ip4, dst=server_nat_ip) /
@@ -3608,7 +3611,7 @@ class TestNAT44(MethodHolder):
self.pg0.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- capture = self.pg1.get_capture(len(pkts))
+ self.pg1.get_capture(len(pkts))
sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n, 0)
nsessions = len(sessions)
@@ -4018,7 +4021,8 @@ class TestNAT44(MethodHolder):
self.pg0.add_stream(pkts[-1])
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- frags = self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(9)
ipfix = IPFIXDecoder()
@@ -4042,7 +4046,14 @@ class TestNAT44(MethodHolder):
def test_tcp_session_close_in(self):
""" Close TCP session from inside network """
+ self.tcp_port_out = 10505
self.nat44_add_address(self.nat_addr)
+ self.nat44_add_static_mapping(self.pg0.remote_ip4,
+ self.nat_addr,
+ self.tcp_port_in,
+ self.tcp_port_out,
+ proto=IP_PROTOS.tcp,
+ twice_nat=1)
self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
is_inside=0)
@@ -4052,60 +4063,61 @@ class TestNAT44(MethodHolder):
self.initiate_tcp_session(self.pg0, self.pg1)
- # close the session from inside
- try:
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=100, ack=300))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
+ # FIN packet in -> out
+ p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
+ flags="FA", seq=100, ack=300))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg1.get_capture(1)
- pkts = []
+ pkts = []
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=300, ack=101))
- pkts.append(p)
+ # ACK packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="A", seq=300, ack=101))
+ pkts.append(p)
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=300, ack=101))
- pkts.append(p)
+ # FIN packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="FA", seq=300, ack=101))
+ pkts.append(p)
- self.pg1.add_stream(pkts)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(2)
+ self.pg1.add_stream(pkts)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(2)
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A", seq=101, ack=301))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
+ # ACK packet in -> out
+ p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
+ flags="A", seq=101, ack=301))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg1.get_capture(1)
- self.initiate_tcp_session(self.pg0, self.pg1)
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 1)
- except:
- self.logger.error("TCP session termination failed")
- raise
+ sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
+ 0)
+ self.assertEqual(len(sessions) - start_sessnum, 0)
def test_tcp_session_close_out(self):
""" Close TCP session from outside network """
+ self.tcp_port_out = 10505
self.nat44_add_address(self.nat_addr)
+ self.nat44_add_static_mapping(self.pg0.remote_ip4,
+ self.nat_addr,
+ self.tcp_port_in,
+ self.tcp_port_out,
+ proto=IP_PROTOS.tcp,
+ twice_nat=1)
self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
is_inside=0)
@@ -4115,50 +4127,51 @@ class TestNAT44(MethodHolder):
self.initiate_tcp_session(self.pg0, self.pg1)
- # close the session from outside
- try:
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=100, ack=300))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
+ # FIN packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="FA", seq=100, ack=300))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(1)
- # FIN+ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=300, ack=101))
+ # FIN+ACK packet in -> out
+ p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
+ flags="FA", seq=300, ack=101))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg1.get_capture(1)
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=101, ack=301))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
+ # ACK packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="A", seq=101, ack=301))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(1)
- self.initiate_tcp_session(self.pg0, self.pg1)
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 1)
- except:
- self.logger.error("TCP session termination failed")
- raise
+ sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
+ 0)
+ self.assertEqual(len(sessions) - start_sessnum, 0)
def test_tcp_session_close_simultaneous(self):
""" Close TCP session from inside network """
+ self.tcp_port_out = 10505
self.nat44_add_address(self.nat_addr)
+ self.nat44_add_static_mapping(self.pg0.remote_ip4,
+ self.nat_addr,
+ self.tcp_port_in,
+ self.tcp_port_out,
+ proto=IP_PROTOS.tcp,
+ twice_nat=1)
self.vapi.nat44_interface_add_del_feature(self.pg0.sw_if_index)
self.vapi.nat44_interface_add_del_feature(self.pg1.sw_if_index,
is_inside=0)
@@ -4168,55 +4181,49 @@ class TestNAT44(MethodHolder):
self.initiate_tcp_session(self.pg0, self.pg1)
- # close the session from inside
- try:
- # FIN packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="FA", seq=100, ack=300))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
+ # FIN packet in -> out
+ p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
+ flags="FA", seq=100, ack=300))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg1.get_capture(1)
- # FIN packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="FA", seq=300, ack=100))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
+ # FIN packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="FA", seq=300, ack=100))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(1)
- # ACK packet in -> out
- p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
- IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
- TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
- flags="A", seq=101, ack=301))
- self.pg0.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg1.get_capture(1)
+ # ACK packet in -> out
+ p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
+ IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
+ TCP(sport=self.tcp_port_in, dport=self.tcp_external_port,
+ flags="A", seq=101, ack=301))
+ self.pg0.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg1.get_capture(1)
- # ACK packet out -> in
- p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
- IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
- TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
- flags="A", seq=301, ack=101))
- self.pg1.add_stream(p)
- self.pg_enable_capture(self.pg_interfaces)
- self.pg_start()
- self.pg0.get_capture(1)
+ # ACK packet out -> in
+ p = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
+ IP(src=self.pg1.remote_ip4, dst=self.nat_addr) /
+ TCP(sport=self.tcp_external_port, dport=self.tcp_port_out,
+ flags="A", seq=301, ack=101))
+ self.pg1.add_stream(p)
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pg_start()
+ self.pg0.get_capture(1)
- self.initiate_tcp_session(self.pg0, self.pg1)
- sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
- 0)
- self.assertEqual(len(sessions) - start_sessnum, 1)
- except:
- self.logger.error("TCP session termination failed")
- raise
+ sessions = self.vapi.nat44_user_session_dump(self.pg0.remote_ip4n,
+ 0)
+ self.assertEqual(len(sessions) - start_sessnum, 0)
def tearDown(self):
super(TestNAT44, self).tearDown()
@@ -4227,8 +4234,10 @@ class TestNAT44(MethodHolder):
self.logger.info(self.vapi.cli("show nat44 interface address"))
self.logger.info(self.vapi.cli("show nat44 sessions detail"))
self.logger.info(self.vapi.cli("show nat virtual-reassembly"))
+ self.logger.info(self.vapi.cli("show nat44 hash tables detail"))
self.vapi.cli("nat addr-port-assignment-alg default")
self.clear_nat44()
+ self.vapi.cli("clear logging")
class TestNAT44Out2InDPO(MethodHolder):
@@ -4242,6 +4251,7 @@ class TestNAT44Out2InDPO(MethodHolder):
@classmethod
def setUpClass(cls):
super(TestNAT44Out2InDPO, cls).setUpClass()
+ cls.vapi.cli("set log class nat level debug")
try:
cls.tcp_port_in = 6303
@@ -4359,6 +4369,7 @@ class TestDeterministicNAT(MethodHolder):
@classmethod
def setUpClass(cls):
super(TestDeterministicNAT, cls).setUpClass()
+ cls.vapi.cli("set log class nat level debug")
try:
cls.tcp_port_in = 6303
@@ -5950,7 +5961,8 @@ class TestNAT64(MethodHolder):
self.pg0.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(9)
ipfix = IPFIXDecoder()
@@ -5977,7 +5989,8 @@ class TestNAT64(MethodHolder):
self.pg0.add_stream(p)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(1)
# verify events in data set
@@ -6013,7 +6026,8 @@ class TestNAT64(MethodHolder):
self.pg0.add_stream(pkts[-1])
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
- self.pg1.get_capture(0)
+ self.pg1.assert_nothing_captured()
+ sleep(1)
self.vapi.cli("ipfix flush") # FIXME this should be an API call
capture = self.pg3.get_capture(9)
ipfix = IPFIXDecoder()