aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2018-09-05 06:01:55 -0700
committerMatus Fabian <matfabia@cisco.com>2018-09-06 11:43:16 +0000
commitd783d1d6bf869169df7f3cfc44f110f7869806f3 (patch)
tree659080900701341c73f24931b6e8d34c5fa4e222
parentf74b4d2b559b1d5697fd625d9c8e0f76ba5a4463 (diff)
NAT: fix maximum out of order fragments (VPP-1399)
All fragments should be dropped when max_frag is 1 and 2 non-initial fragments are received before first fragment. Change-Id: Id0c968f45629698e347e8226c5926f27b48b82d6 Signed-off-by: Matus Fabian <matfabia@cisco.com> (cherry picked from commit a7f8b228ff505acc052a77101b12e714ead26536)
-rwxr-xr-xsrc/plugins/nat/in2out.c2
-rw-r--r--src/plugins/nat/nat64_in2out.c3
-rw-r--r--src/plugins/nat/nat64_out2in.c3
-rwxr-xr-xsrc/plugins/nat/nat_reass.c24
-rw-r--r--src/plugins/nat/nat_reass.h12
-rwxr-xr-xsrc/plugins/nat/out2in.c2
-rw-r--r--test/test_nat.py14
7 files changed, 46 insertions, 14 deletions
diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c
index c3ef6ce1996..9f749cb7b3f 100755
--- a/src/plugins/nat/in2out.c
+++ b/src/plugins/nat/in2out.c
@@ -2174,7 +2174,7 @@ nat44_in2out_reass_node_fn (vlib_main_t * vm,
{
if (PREDICT_FALSE (reass0->sess_index == (u32) ~0))
{
- if (nat_ip4_reass_add_fragment (reass0, bi0))
+ if (nat_ip4_reass_add_fragment (reass0, bi0, &fragments_to_drop))
{
b0->error = node->errors[SNAT_IN2OUT_ERROR_MAX_FRAG];
nat_log_notice ("maximum fragments per reassembly exceeded");
diff --git a/src/plugins/nat/nat64_in2out.c b/src/plugins/nat/nat64_in2out.c
index cdfe9b8d80c..319b84b9679 100644
--- a/src/plugins/nat/nat64_in2out.c
+++ b/src/plugins/nat/nat64_in2out.c
@@ -1416,7 +1416,8 @@ nat64_in2out_reass_node_fn (vlib_main_t * vm,
ctx0.first_frag = 0;
if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
{
- if (nat_ip6_reass_add_fragment (reass0, bi0))
+ if (nat_ip6_reass_add_fragment
+ (reass0, bi0, &fragments_to_drop))
{
b0->error = node->errors[NAT64_IN2OUT_ERROR_MAX_FRAG];
next0 = NAT64_IN2OUT_NEXT_DROP;
diff --git a/src/plugins/nat/nat64_out2in.c b/src/plugins/nat/nat64_out2in.c
index f7d4dd417f5..33d6dda17ca 100644
--- a/src/plugins/nat/nat64_out2in.c
+++ b/src/plugins/nat/nat64_out2in.c
@@ -780,7 +780,8 @@ nat64_out2in_reass_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node,
if (PREDICT_FALSE (reass0->sess_index == (u32) ~ 0))
{
- if (nat_ip4_reass_add_fragment (reass0, bi0))
+ if (nat_ip4_reass_add_fragment
+ (reass0, bi0, &fragments_to_drop))
{
b0->error = node->errors[NAT64_OUT2IN_ERROR_MAX_FRAG];
next0 = NAT64_OUT2IN_NEXT_DROP;
diff --git a/src/plugins/nat/nat_reass.c b/src/plugins/nat/nat_reass.c
index eb1b4925521..8fd370de2fc 100755
--- a/src/plugins/nat/nat_reass.c
+++ b/src/plugins/nat/nat_reass.c
@@ -249,6 +249,13 @@ nat_ip4_reass_find_or_create (ip4_address_t src, ip4_address_t dst,
srm->ip4_reass_head_index,
reass->lru_list_index);
}
+
+ if (reass->flags && NAT_REASS_FLAG_MAX_FRAG_DROP)
+ {
+ reass = 0;
+ goto unlock;
+ }
+
goto unlock;
}
@@ -326,7 +333,8 @@ unlock:
}
int
-nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi)
+nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi,
+ u32 ** bi_to_drop)
{
nat_reass_main_t *srm = &nat_reass_main;
dlist_elt_t *elt;
@@ -336,6 +344,8 @@ nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi)
{
nat_ipfix_logging_max_fragments_ip4 (srm->ip4_max_frag,
&reass->key.src);
+ reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
+ nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
return -1;
}
@@ -446,6 +456,13 @@ nat_ip6_reass_find_or_create (ip6_address_t src, ip6_address_t dst,
srm->ip6_reass_head_index,
reass->lru_list_index);
}
+
+ if (reass->flags && NAT_REASS_FLAG_MAX_FRAG_DROP)
+ {
+ reass = 0;
+ goto unlock;
+ }
+
goto unlock;
}
@@ -522,7 +539,8 @@ unlock:
}
int
-nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi)
+nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi,
+ u32 ** bi_to_drop)
{
nat_reass_main_t *srm = &nat_reass_main;
dlist_elt_t *elt;
@@ -532,6 +550,8 @@ nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi)
{
nat_ipfix_logging_max_fragments_ip6 (srm->ip6_max_frag,
&reass->key.src);
+ reass->flags |= NAT_REASS_FLAG_MAX_FRAG_DROP;
+ nat_ip6_reass_get_frags_inline (reass, bi_to_drop);
return -1;
}
diff --git a/src/plugins/nat/nat_reass.h b/src/plugins/nat/nat_reass.h
index 4a9137e3255..5b18d1bd7b9 100644
--- a/src/plugins/nat/nat_reass.h
+++ b/src/plugins/nat/nat_reass.h
@@ -30,6 +30,8 @@
#define NAT_MAX_FRAG_DEFAULT 5
#define NAT_REASS_HT_LOAD_FACTOR (0.75)
+#define NAT_REASS_FLAG_MAX_FRAG_DROP 1
+
typedef struct
{
union
@@ -57,6 +59,7 @@ typedef CLIB_PACKED(struct
f64 last_heard;
u32 frags_per_reass_list_head_index;
u8 frag_n;
+ u8 flags;
}) nat_reass_ip4_t;
/* *INDENT-ON* */
@@ -86,6 +89,7 @@ typedef CLIB_PACKED(struct
f64 last_heard;
u32 frags_per_reass_list_head_index;
u8 frag_n;
+ u8 flags;
}) nat_reass_ip6_t;
/* *INDENT-ON* */
@@ -222,10 +226,12 @@ nat_reass_ip4_t *nat_ip4_reass_find_or_create (ip4_address_t src,
*
* @param reass Reassembly data.
* @param bi Buffer index.
+ * @param bi_to_drop Fragments to drop.
*
* @returns 0 on success, non-zero value otherwise.
*/
-int nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi);
+int nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi,
+ u32 ** bi_to_drop);
/**
* @brief Get cached fragments.
@@ -271,10 +277,12 @@ nat_reass_ip6_t *nat_ip6_reass_find_or_create (ip6_address_t src,
*
* @param reass Reassembly data.
* @param bi Buffer index.
+ * @param bi_to_drop Fragments to drop.
*
* @returns 0 on success, non-zero value otherwise.
*/
-int nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi);
+int nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi,
+ u32 ** bi_to_drop);
/**
* @brief Get cached fragments.
diff --git a/src/plugins/nat/out2in.c b/src/plugins/nat/out2in.c
index 4308ed25834..b20b9f6cc02 100755
--- a/src/plugins/nat/out2in.c
+++ b/src/plugins/nat/out2in.c
@@ -1390,7 +1390,7 @@ nat44_out2in_reass_node_fn (vlib_main_t * vm,
{
if (PREDICT_FALSE (reass0->sess_index == (u32) ~0))
{
- if (nat_ip4_reass_add_fragment (reass0, bi0))
+ if (nat_ip4_reass_add_fragment (reass0, bi0, &fragments_to_drop))
{
b0->error = node->errors[SNAT_OUT2IN_ERROR_MAX_FRAG];
nat_log_notice ("maximum fragments per reassembly exceeded");
diff --git a/test/test_nat.py b/test/test_nat.py
index ceab717e3f5..6f7a0e237f7 100644
--- a/test/test_nat.py
+++ b/test/test_nat.py
@@ -3097,7 +3097,7 @@ class TestNAT44(MethodHolder):
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)
- self.vapi.nat_set_reass(max_frag=0)
+ self.vapi.nat_set_reass(max_frag=1)
self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
src_address=self.pg3.local_ip4n,
path_mtu=512,
@@ -3112,7 +3112,8 @@ class TestNAT44(MethodHolder):
self.tcp_port_in,
20,
data)
- self.pg0.add_stream(pkts[-1])
+ pkts.reverse()
+ self.pg0.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
self.pg1.assert_nothing_captured()
@@ -3135,7 +3136,7 @@ class TestNAT44(MethodHolder):
for p in capture:
if p.haslayer(Data):
data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_fragments_ip4(data, 0,
+ self.verify_ipfix_max_fragments_ip4(data, 1,
self.pg0.remote_ip4n)
def test_multiple_outside_vrf(self):
@@ -6729,7 +6730,7 @@ class TestNAT64(MethodHolder):
self.nat_addr_n)
self.vapi.nat64_add_del_interface(self.pg0.sw_if_index)
self.vapi.nat64_add_del_interface(self.pg1.sw_if_index, is_inside=0)
- self.vapi.nat_set_reass(max_frag=0, is_ip6=1)
+ self.vapi.nat_set_reass(max_frag=1, is_ip6=1)
self.vapi.set_ipfix_exporter(collector_address=self.pg3.remote_ip4n,
src_address=self.pg3.local_ip4n,
path_mtu=512,
@@ -6740,7 +6741,8 @@ class TestNAT64(MethodHolder):
data = 'a' * 200
pkts = self.create_stream_frag_ip6(self.pg0, self.pg1.remote_ip4,
self.tcp_port_in, 20, data)
- self.pg0.add_stream(pkts[-1])
+ pkts.reverse()
+ self.pg0.add_stream(pkts)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
self.pg1.assert_nothing_captured()
@@ -6763,7 +6765,7 @@ class TestNAT64(MethodHolder):
for p in capture:
if p.haslayer(Data):
data = ipfix.decode_data_set(p.getlayer(Set))
- self.verify_ipfix_max_fragments_ip6(data, 0,
+ self.verify_ipfix_max_fragments_ip6(data, 1,
self.pg0.remote_ip6n)
def test_ipfix_bib_ses(self):