From a7f8b228ff505acc052a77101b12e714ead26536 Mon Sep 17 00:00:00 2001 From: Matus Fabian Date: Wed, 5 Sep 2018 06:01:55 -0700 Subject: 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 --- src/plugins/nat/in2out.c | 2 +- src/plugins/nat/nat64_in2out.c | 3 ++- src/plugins/nat/nat64_out2in.c | 3 ++- src/plugins/nat/nat_reass.c | 24 ++++++++++++++++++++++-- src/plugins/nat/nat_reass.h | 12 ++++++++++-- src/plugins/nat/out2in.c | 2 +- 6 files changed, 38 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/plugins/nat/in2out.c b/src/plugins/nat/in2out.c index 0fe36338397..22a346855c6 100755 --- a/src/plugins/nat/in2out.c +++ b/src/plugins/nat/in2out.c @@ -2218,7 +2218,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 718c69d7bdf..ddbf5850c7c 100644 --- a/src/plugins/nat/nat64_in2out.c +++ b/src/plugins/nat/nat64_in2out.c @@ -1424,7 +1424,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 d4b0c3987f9..54a7e82c7c1 100644 --- a/src/plugins/nat/nat64_out2in.c +++ b/src/plugins/nat/nat64_out2in.c @@ -785,7 +785,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 5029300dcdb..3d4e9228e67 100755 --- a/src/plugins/nat/out2in.c +++ b/src/plugins/nat/out2in.c @@ -1430,7 +1430,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"); -- cgit 1.2.3-korg