#include <vnet/vnet.h>
#include <nat/nat_reass.h>
+#include <nat/nat_ipfix_logging.h>
nat_reass_main_t nat_reass_main;
return 0;
}
+nat_reass_ip4_t *
+nat_ip4_reass_find (ip4_address_t src, ip4_address_t dst, u16 frag_id,
+ u8 proto)
+{
+ nat_reass_main_t *srm = &nat_reass_main;
+ nat_reass_ip4_t *reass = 0;
+ nat_reass_ip4_key_t k;
+ f64 now = vlib_time_now (srm->vlib_main);
+
+ k.src.as_u32 = src.as_u32;
+ k.dst.as_u32 = dst.as_u32;
+ k.frag_id = frag_id;
+ k.proto = proto;
+
+ clib_spinlock_lock_if_init (&srm->ip4_reass_lock);
+ reass = nat_ip4_reass_lookup (&k, now);
+ clib_spinlock_unlock_if_init (&srm->ip4_reass_lock);
+
+ return reass;
+}
+
+nat_reass_ip4_t *
+nat_ip4_reass_create (ip4_address_t src, ip4_address_t dst, u16 frag_id,
+ u8 proto)
+{
+ nat_reass_main_t *srm = &nat_reass_main;
+ nat_reass_ip4_t *reass = 0;
+ dlist_elt_t *elt, *per_reass_list_head_elt;
+ u32 elt_index;
+ f64 now = vlib_time_now (srm->vlib_main);
+ nat_reass_ip4_key_t k;
+ clib_bihash_kv_16_8_t kv;
+
+ clib_spinlock_lock_if_init (&srm->ip4_reass_lock);
+
+ if (srm->ip4_reass_n >= srm->ip4_max_reass)
+ {
+ nat_elog_warn ("no free resassembly slot");
+ goto unlock;
+ }
+
+ pool_get (srm->ip4_reass_pool, reass);
+ pool_get (srm->ip4_reass_lru_list_pool, elt);
+ reass->lru_list_index = elt_index = elt - srm->ip4_reass_lru_list_pool;
+ clib_dlist_init (srm->ip4_reass_lru_list_pool, elt_index);
+ elt->value = reass - srm->ip4_reass_pool;
+ clib_dlist_addtail (srm->ip4_reass_lru_list_pool,
+ srm->ip4_reass_head_index, elt_index);
+ pool_get (srm->ip4_frags_list_pool, per_reass_list_head_elt);
+ reass->frags_per_reass_list_head_index =
+ per_reass_list_head_elt - srm->ip4_frags_list_pool;
+ clib_dlist_init (srm->ip4_frags_list_pool,
+ reass->frags_per_reass_list_head_index);
+ srm->ip4_reass_n++;
+ k.src.as_u32 = src.as_u32;
+ k.dst.as_u32 = dst.as_u32;
+ k.frag_id = frag_id;
+ k.proto = proto;
+ reass->key.as_u64[0] = kv.key[0] = k.as_u64[0];
+ reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
+ kv.value = reass - srm->ip4_reass_pool;
+ reass->sess_index = (u32) ~ 0;
+ reass->thread_index = (u32) ~ 0;
+ reass->last_heard = now;
+ reass->frag_n = 0;
+ reass->flags = 0;
+ reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
+ if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
+ nat_elog_warn ("ip4_reass_hash add key failed");
+
+unlock:
+ clib_spinlock_unlock_if_init (&srm->ip4_reass_lock);
+ return reass;
+}
+
nat_reass_ip4_t *
nat_ip4_reass_find_or_create (ip4_address_t src, ip4_address_t dst,
u16 frag_id, u8 proto, u8 reset_timeout,
dlist_elt_t *oldest_elt, *elt;
dlist_elt_t *per_reass_list_head_elt;
u32 oldest_index, elt_index;
- clib_bihash_kv_16_8_t kv;
+ clib_bihash_kv_16_8_t kv, value;
k.src.as_u32 = src.as_u32;
k.dst.as_u32 = dst.as_u32;
srm->ip4_reass_head_index,
reass->lru_list_index);
}
+
+ if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
+ {
+ reass = 0;
+ goto unlock;
+ }
+
goto unlock;
}
{
clib_dlist_addhead (srm->ip4_reass_lru_list_pool,
srm->ip4_reass_head_index, oldest_index);
- clib_warning ("no free resassembly slot");
+ nat_elog_warn ("no free resassembly slot");
reass = 0;
goto unlock;
}
clib_dlist_addtail (srm->ip4_reass_lru_list_pool,
srm->ip4_reass_head_index, oldest_index);
- kv.key[0] = k.as_u64[0];
- kv.key[1] = k.as_u64[1];
- if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 0))
+ kv.key[0] = reass->key.as_u64[0];
+ kv.key[1] = reass->key.as_u64[1];
+ if (!clib_bihash_search_16_8 (&srm->ip4_reass_hash, &kv, &value))
{
- reass = 0;
- goto unlock;
+ if (value.value == (reass - srm->ip4_reass_pool))
+ {
+ if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 0))
+ {
+ reass = 0;
+ goto unlock;
+ }
+ }
}
nat_ip4_reass_get_frags_inline (reass, bi_to_drop);
reass->key.as_u64[1] = kv.key[1] = k.as_u64[1];
kv.value = reass - srm->ip4_reass_pool;
reass->sess_index = (u32) ~ 0;
+ reass->thread_index = (u32) ~ 0;
reass->last_heard = now;
+ reass->frag_n = 0;
+ reass->flags = 0;
+ reass->classify_next = NAT_REASS_IP4_CLASSIFY_NONE;
if (clib_bihash_add_del_16_8 (&srm->ip4_reass_hash, &kv, 1))
{
}
int
-nat_ip4_reass_add_fragment (nat_reass_ip4_t * reass, u32 bi)
+nat_ip4_reass_add_fragment (u32 thread_index, nat_reass_ip4_t * reass,
+ u32 bi, u32 ** bi_to_drop)
{
nat_reass_main_t *srm = &nat_reass_main;
dlist_elt_t *elt;
u32 elt_index;
if (reass->frag_n >= srm->ip4_max_frag)
- return -1;
+ {
+ nat_ipfix_logging_max_fragments_ip4 (thread_index, 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;
+ }
clib_spinlock_lock_if_init (&srm->ip4_reass_lock);
srm->ip6_reass_head_index,
reass->lru_list_index);
}
+
+ if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
+ {
+ reass = 0;
+ goto unlock;
+ }
+
goto unlock;
}
{
clib_dlist_addhead (srm->ip6_reass_lru_list_pool,
srm->ip6_reass_head_index, oldest_index);
- clib_warning ("no free resassembly slot");
+ nat_elog_warn ("no free resassembly slot");
reass = 0;
goto unlock;
}
kv.key[0] = k.as_u64[0];
kv.key[1] = k.as_u64[1];
kv.key[2] = k.as_u64[2];
- kv.key[3] = k.as_u64[4];
- kv.key[4] = k.as_u64[5];
+ kv.key[3] = k.as_u64[3];
+ kv.key[4] = k.as_u64[4];
+ kv.key[5] = k.as_u64[5];
if (clib_bihash_add_del_48_8 (&srm->ip6_reass_hash, &kv, 0))
{
reass = 0;
}
int
-nat_ip6_reass_add_fragment (nat_reass_ip6_t * reass, u32 bi)
+nat_ip6_reass_add_fragment (u32 thread_index, nat_reass_ip6_t * reass,
+ u32 bi, u32 ** bi_to_drop)
{
nat_reass_main_t *srm = &nat_reass_main;
dlist_elt_t *elt;
u32 elt_index;
if (reass->frag_n >= srm->ip6_max_frag)
- return -1;
+ {
+ nat_ipfix_logging_max_fragments_ip6 (thread_index, 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;
+ }
clib_spinlock_lock_if_init (&srm->ip6_reass_lock);
nat_ip4_reass_walk_cli (nat_reass_ip4_t * reass, void *ctx)
{
vlib_main_t *vm = ctx;
+ u8 *flags_str = 0;
+ const char *classify_next_str;
- vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u",
+ if (reass->flags & NAT_REASS_FLAG_MAX_FRAG_DROP)
+ flags_str = format (flags_str, "MAX_FRAG_DROP");
+ if (reass->flags & NAT_REASS_FLAG_CLASSIFY_ED_CONTINUE)
+ {
+ if (flags_str)
+ flags_str = format (flags_str, " | ");
+ flags_str = format (flags_str, "CLASSIFY_ED_CONTINUE");
+ }
+ if (reass->flags & NAT_REASS_FLAG_ED_DONT_TRANSLATE)
+ {
+ if (flags_str)
+ flags_str = format (flags_str, " | ");
+ flags_str = format (flags_str, "CLASSIFY_ED_DONT_TRANSLATE");
+ }
+ if (!flags_str)
+ flags_str = format (flags_str, "0");
+ flags_str = format (flags_str, "%c", 0);
+
+ switch (reass->classify_next)
+ {
+ case NAT_REASS_IP4_CLASSIFY_NONE:
+ classify_next_str = "NONE";
+ break;
+ case NAT_REASS_IP4_CLASSIFY_NEXT_IN2OUT:
+ classify_next_str = "IN2OUT";
+ break;
+ case NAT_REASS_IP4_CLASSIFY_NEXT_OUT2IN:
+ classify_next_str = "OUT2IN";
+ break;
+ default:
+ classify_next_str = "invalid value";
+ }
+
+ vlib_cli_output (vm, " src %U dst %U proto %u id 0x%04x cached %u "
+ "flags %s classify_next %s",
format_ip4_address, &reass->key.src,
format_ip4_address, &reass->key.dst,
reass->key.proto,
- clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n);
+ clib_net_to_host_u16 (reass->key.frag_id), reass->frag_n,
+ flags_str, classify_next_str);
+
+ vec_free (flags_str);
return 0;
}
{
vlib_cli_output (vm, "NAT IPv4 virtual fragmentation reassembly is %s",
nat_reass_is_drop_frag (0) ? "DISABLED" : "ENABLED");
- vlib_cli_output (vm, " max-reasssemblies %u", nat_reass_get_max_reass (0));
+ vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (0));
vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (0));
vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (0));
vlib_cli_output (vm, " reassemblies:");
vlib_cli_output (vm, "NAT IPv6 virtual fragmentation reassembly is %s",
nat_reass_is_drop_frag (1) ? "DISABLED" : "ENABLED");
- vlib_cli_output (vm, " max-reasssemblies %u", nat_reass_get_max_reass (1));
+ vlib_cli_output (vm, " max-reassemblies %u", nat_reass_get_max_reass (1));
vlib_cli_output (vm, " max-fragments %u", nat_reass_get_max_frag (1));
vlib_cli_output (vm, " timeout %usec", nat_reass_get_timeout (1));
vlib_cli_output (vm, " reassemblies:");