map: use ip6-full-reassembly instead of own code

Remove map's implementation of reassembly and use common
ip6-full-reassembly functionality. This makes it easier to maintain by
removing duplicate code/functionality.

Type: refactor

Change-Id: I430e888b704e28c100a9ce075d1460cb529e4676
Signed-off-by: Klement Sekera <ksekera@cisco.com>
This commit is contained in:
Klement Sekera
2019-10-01 13:00:22 +00:00
committed by Ole Trøan
parent d5262831a3
commit 7b2e9fb1a8
10 changed files with 100 additions and 978 deletions

File diff suppressed because it is too large Load Diff

View File

@ -241,28 +241,6 @@ autoreply define map_param_add_del_pre_resolve
vl_api_ip6_address_t ip6_nh_address;
};
/** \brief Set MAP reassembly parameters
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param is_ip6 - 1 = params apply to IPv6, 0 = params apply to IPv4
@param lifetime_ms - reassembly valid lifetime, or ~0
@param pool_size - max number of reassemblies, or ~0
@param buffers - max number of reassembly buffers, or ~0
@param ht_ratio - hash-table size factor, or ~0
*/
autoreply define map_param_set_reassembly
{
u32 client_index;
u32 context;
bool is_ip6;
u16 lifetime_ms;
u16 pool_size;
u32 buffers;
f64 ht_ratio;
};
/** \brief Set MAP security-check parameters
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@ -326,10 +304,6 @@ define map_param_get
@param icmp6_enable_unreachable - 1 = send ICMP unreachable err msgs
@param ip4_nh_address - direct IP4 next-hop address
@param ip6_nh_address - direct IP6 next-hop address
@param ip6_lifetime_ms - max number of reassemblies, or ~0
@param ip6_pool_size - max number of reassemblies, or ~0
@param ip6_buffers - max number of reassembly buffers, or ~0
@param ip6_ht_ratio - hash-table size factor, or ~0
@param sec_check_enable - 1=enable security check on first inbound packet
@param sec_check_fragments - 1=enable check on (subsequent) fragments too
@param tc_copy - 1 = copy packet class/TOS field, 0 = use class instead
@ -349,10 +323,6 @@ define map_param_get_reply
u16 ip4_pool_size;
u32 ip4_buffers;
f64 ip4_ht_ratio;
u16 ip6_lifetime_ms;
u16 ip6_pool_size;
u32 ip6_buffers;
f64 ip6_ht_ratio;
bool sec_check_enable;
bool sec_check_fragments;
bool tc_copy;

File diff suppressed because it is too large Load Diff

View File

@ -50,9 +50,6 @@ int map_param_set_fragmentation (bool inner, bool ignore_df);
int map_param_set_icmp (ip4_address_t * ip4_err_relay_src);
int map_param_set_icmp6 (u8 enable_unreachable);
void map_pre_resolve (ip4_address_t * ip4, ip6_address_t * ip6, bool is_del);
int map_param_set_reassembly (bool is_ipv6, u16 lifetime_ms, u16 pool_size,
u32 buffers, f64 ht_ratio, u32 * reass,
u32 * packets);
int map_param_set_security_check (bool enable, bool fragments);
int map_param_set_traffic_class (bool copy, u8 tc);
int map_param_set_tcp (u16 tcp_mss);
@ -65,15 +62,6 @@ typedef enum
MAP_DOMAIN_RFC6052 = 1 << 2,
} __attribute__ ((__packed__)) map_domain_flags_e;
#define MAP_IP6_REASS_LIFETIME_DEFAULT (100) /* ms */
#define MAP_IP6_REASS_HT_RATIO_DEFAULT (1.0)
#define MAP_IP6_REASS_POOL_SIZE_DEFAULT 1024 // Number of reassembly structures
#define MAP_IP6_REASS_BUFFERS_DEFAULT 2048
#define MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY 5
#define MAP_IP6_REASS_COUNT_BYTES
//#define IP6_MAP_T_OVERRIDE_TOS 0
/*
@ -136,46 +124,6 @@ typedef enum
MAP_N_DOMAIN_COUNTER
} map_domain_counter_t;
/*
* main_main_t
*/
/* *INDENT-OFF* */
typedef union {
CLIB_PACKED (struct {
ip6_address_t src;
ip6_address_t dst;
u32 fragment_id;
u8 protocol;
});
u64 as_u64[5];
u32 as_u32[10];
} map_ip6_reass_key_t;
/* *INDENT-ON* */
typedef struct
{
u32 pi; //Cached packet or ~0
u16 next_data_offset; //The data offset of the additional 20 bytes or ~0
u8 next_data_len; //Number of bytes ready to be copied (20 if not last fragment)
u8 next_data[20]; //The 20 additional bytes
} map_ip6_fragment_t;
typedef struct
{
map_ip6_reass_key_t key;
f64 ts;
#ifdef MAP_IP6_REASS_COUNT_BYTES
u16 expected_total;
u16 forwarded;
#endif
u16 bucket; //What hash bucket this element is linked in
u16 bucket_next;
u16 fifo_prev;
u16 fifo_next;
ip4_header_t ip4_header;
map_ip6_fragment_t fragments[MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY];
} map_ip6_reass_t;
#ifdef MAP_SKIP_IP6_LOOKUP
/**
* A pre-resolved next-hop
@ -245,26 +193,6 @@ typedef struct
bool frag_inner; /* Inner or outer fragmentation */
bool frag_ignore_df; /* Fragment (outer) packet even if DF is set */
/*
* IPv6 decap reassembly
*/
/* Configuration */
f32 ip6_reass_conf_ht_ratio; //Size of ht is 2^ceil(log2(ratio*pool_size))
u16 ip6_reass_conf_pool_size; //Max number of allocated reass structures
u16 ip6_reass_conf_lifetime_ms; //Time a reassembly struct is considered valid in ms
u32 ip6_reass_conf_buffers; //Maximum number of buffers used by ip6 reassembly
/* Runtime */
map_ip6_reass_t *ip6_reass_pool;
u8 ip6_reass_ht_log2len; //Hash table size is 2^log2len
u16 ip6_reass_allocated;
u16 *ip6_reass_hash_table;
u16 ip6_reass_fifo_last;
clib_spinlock_t ip6_reass_lock;
/* Counters */
u32 ip6_reass_buffered_counter;
/* Graph node state */
uword *bm_trans_enabled_by_sw_if;
uword *bm_encap_enabled_by_sw_if;
@ -445,35 +373,8 @@ ip6_map_get_domain (ip6_address_t * addr, u32 * map_domain_index, u8 * error)
clib_error_t *map_plugin_api_hookup (vlib_main_t * vm);
map_ip6_reass_t *map_ip6_reass_get (ip6_address_t * src, ip6_address_t * dst,
u32 fragment_id, u8 protocol,
u32 ** pi_to_drop);
void map_ip6_reass_free (map_ip6_reass_t * r, u32 ** pi_to_drop);
#define map_ip6_reass_lock() clib_spinlock_lock (&map_main.ip6_reass_lock)
#define map_ip6_reass_unlock() clib_spinlock_unlock (&map_main.ip6_reass_lock)
int
map_ip6_reass_add_fragment (map_ip6_reass_t * r, u32 pi,
u16 data_offset, u16 next_data_offset,
u8 * data_start, u16 data_len);
void map_ip4_drop_pi (u32 pi);
void map_ip6_drop_pi (u32 pi);
int map_ip6_reass_conf_ht_ratio (f32 ht_ratio, u32 * trashed_reass,
u32 * dropped_packets);
#define MAP_IP6_REASS_CONF_HT_RATIO_MAX 100
int map_ip6_reass_conf_pool_size (u16 pool_size, u32 * trashed_reass,
u32 * dropped_packets);
#define MAP_IP6_REASS_CONF_POOL_SIZE_MAX (0xfeff)
int map_ip6_reass_conf_lifetime (u16 lifetime_ms);
#define MAP_IP6_REASS_CONF_LIFETIME_MAX 0xffff
int map_ip6_reass_conf_buffers (u32 buffers);
#define MAP_IP6_REASS_CONF_BUFFERS_MAX (0xffffffff)
/*
* Supports prefix of 96 or 64 (with u-octet)
*/

View File

@ -24,6 +24,7 @@
#include <vnet/ip/ip.h>
#include <vnet/ip/reass/ip4_sv_reass.h>
#include <vnet/ip/reass/ip6_sv_reass.h>
#include <vnet/ip/reass/ip6_full_reass.h>
#include <vnet/fib/fib_table.h>
#include <vlibmemory/api.h>
@ -330,102 +331,6 @@ static void
REPLY_MACRO (VL_API_MAP_PARAM_ADD_DEL_PRE_RESOLVE_REPLY);
}
int
map_param_set_reassembly (bool is_ipv6,
u16 lifetime_ms,
u16 pool_size,
u32 buffers,
f64 ht_ratio, u32 * reass, u32 * packets)
{
u32 ps_reass = 0, ps_packets = 0;
u32 ht_reass = 0, ht_packets = 0;
if (is_ipv6)
{
if (pool_size != (u16) ~ 0)
{
if (pool_size > MAP_IP6_REASS_CONF_POOL_SIZE_MAX)
return MAP_ERR_BAD_POOL_SIZE;
if (map_ip6_reass_conf_pool_size
(pool_size, &ps_reass, &ps_packets))
return MAP_ERR_BAD_POOL_SIZE;
}
if (ht_ratio != (MAP_IP6_REASS_CONF_HT_RATIO_MAX + 1))
{
if (ht_ratio > MAP_IP6_REASS_CONF_HT_RATIO_MAX)
return MAP_ERR_BAD_HT_RATIO;
if (map_ip6_reass_conf_ht_ratio (ht_ratio, &ht_reass, &ht_packets))
return MAP_ERR_BAD_HT_RATIO;
}
if (lifetime_ms != (u16) ~ 0)
{
if (lifetime_ms > MAP_IP6_REASS_CONF_LIFETIME_MAX)
return MAP_ERR_BAD_LIFETIME;
if (map_ip6_reass_conf_lifetime (lifetime_ms))
return MAP_ERR_BAD_LIFETIME;
}
if (buffers != ~0)
{
if (buffers > MAP_IP6_REASS_CONF_BUFFERS_MAX)
return MAP_ERR_BAD_BUFFERS;
if (map_ip6_reass_conf_buffers (buffers))
return MAP_ERR_BAD_BUFFERS;
}
if (map_main.ip6_reass_conf_buffers >
map_main.ip6_reass_conf_pool_size *
MAP_IP6_REASS_MAX_FRAGMENTS_PER_REASSEMBLY)
{
return MAP_ERR_BAD_BUFFERS_TOO_LARGE;
}
}
else
{
return MAP_ERR_UNSUPPORTED;
}
if (reass)
*reass = ps_reass + ht_reass;
if (packets)
*packets = ps_packets + ht_packets;
return 0;
}
static void
vl_api_map_param_set_reassembly_t_handler
(vl_api_map_param_set_reassembly_t * mp)
{
map_main_t *mm = &map_main;
vl_api_map_param_set_reassembly_reply_t *rmp;
u32 reass = 0, packets = 0;
int rv;
f64 ht_ratio;
ht_ratio = (f64) clib_net_to_host_f64 (mp->ht_ratio);
if (ht_ratio == ~0)
ht_ratio = MAP_IP6_REASS_CONF_HT_RATIO_MAX + 1;
rv = map_param_set_reassembly (mp->is_ip6,
clib_net_to_host_u16 (mp->lifetime_ms),
clib_net_to_host_u16 (mp->pool_size),
clib_net_to_host_u32 (mp->buffers),
ht_ratio, &reass, &packets);
/*
* FIXME: Should the lost reass and packet counts be returned in the API?
*/
REPLY_MACRO (VL_API_MAP_PARAM_SET_REASSEMBLY_REPLY);
}
int
map_param_set_security_check (bool enable, bool fragments)
{
@ -530,12 +435,6 @@ vl_api_map_param_get_t_handler (vl_api_map_param_get_t * mp)
clib_memset (&rmp->ip4_nh_address, 0, sizeof (rmp->ip4_nh_address));
clib_memset (&rmp->ip6_nh_address, 0, sizeof (rmp->ip6_nh_address));
rmp->ip6_lifetime_ms =
clib_net_to_host_u16 (mm->ip6_reass_conf_lifetime_ms);
rmp->ip6_pool_size = clib_net_to_host_u16 (mm->ip6_reass_conf_pool_size);
rmp->ip6_buffers = clib_net_to_host_u32 (mm->ip6_reass_conf_buffers);
rmp->ip6_ht_ratio = clib_net_to_host_f64 (mm->ip6_reass_conf_ht_ratio);
rmp->sec_check_enable = mm->sec_check;
rmp->sec_check_fragments = mm->sec_check_frag;
@ -573,6 +472,7 @@ map_if_enable_disable (bool is_enable, u32 sw_if_index, bool is_translation)
if (is_translation == false)
{
ip4_sv_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
ip6_full_reass_enable_disable_with_refcnt (sw_if_index, is_enable);
vnet_feature_enable_disable ("ip4-unicast", "ip4-map", sw_if_index,
is_enable ? 1 : 0, 0, 0);
vnet_feature_enable_disable ("ip6-unicast", "ip6-map", sw_if_index,

View File

@ -7,7 +7,7 @@ from ipaddress import IPv6Network, IPv4Network
from framework import VppTestCase, VppTestRunner
from vpp_ip import DpoProto
from vpp_ip_route import VppIpRoute, VppRoutePath
from util import fragment_rfc791
from util import fragment_rfc791, fragment_rfc8200
import scapy.compat
from scapy.layers.l2 import Ether, Raw
@ -227,6 +227,29 @@ class TestMAP(VppTestCase):
rx = self.pg0.get_capture(len(frags))
for r in rx:
self.assertFalse(r.haslayer(IPv6))
self.assertEqual(r[IP].src, p[IP].src)
self.assertEqual(r[IP].dst, p[IP].dst)
# Verify that fragments pass even if ipv6 layer is fragmented
stream = (IPv6(dst='3000::1', src=map_translated_addr) / x
for x in frags)
v6_stream = [
Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / x
for i in range(len(frags))
for x in fragment_rfc8200(
IPv6(dst='3000::1', src=map_translated_addr) / frags[i],
i, 200)]
self.pg1.add_stream(v6_stream)
self.pg_enable_capture(self.pg_interfaces)
self.pg_start()
rx = self.pg0.get_capture(len(frags))
for r in rx:
self.assertFalse(r.haslayer(IPv6))
self.assertEqual(r[IP].src, p[IP].src)

View File

@ -185,6 +185,8 @@ typedef struct
u32 fq_index;
u32 fq_feature_index;
// reference count for enabling/disabling feature - per interface
u32 *feature_use_refcount_per_intf;
} ip4_full_reass_main_t;
extern ip4_full_reass_main_t ip4_full_reass_main;
@ -1448,6 +1450,7 @@ ip4_full_reass_init_function (vlib_main_t * vm)
rm->fq_feature_index =
vlib_frame_queue_main_init (ip4_full_reass_node_feature.index, 0);
rm->feature_use_refcount_per_intf = NULL;
return error;
}
@ -1793,6 +1796,35 @@ VLIB_REGISTER_NODE (ip4_full_reass_feature_handoff_node) = {
};
/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
int
ip4_full_reass_enable_disable_with_refcnt (u32 sw_if_index, int is_enable)
{
ip4_full_reass_main_t *rm = &ip4_full_reass_main;
vec_validate (rm->feature_use_refcount_per_intf, sw_if_index);
if (is_enable)
{
if (!rm->feature_use_refcount_per_intf[sw_if_index])
{
++rm->feature_use_refcount_per_intf[sw_if_index];
return vnet_feature_enable_disable ("ip4-unicast",
"ip4-full-reassembly-feature",
sw_if_index, 1, 0, 0);
}
++rm->feature_use_refcount_per_intf[sw_if_index];
}
else
{
--rm->feature_use_refcount_per_intf[sw_if_index];
if (!rm->feature_use_refcount_per_intf[sw_if_index])
return vnet_feature_enable_disable ("ip4-unicast",
"ip4-full-reassembly-feature",
sw_if_index, 0, 0, 0);
}
return -1;
}
#endif
/*
* fd.io coding-style-patch-verification: ON
*

View File

@ -43,6 +43,9 @@ vnet_api_error_t ip4_full_reass_get (u32 * timeout_ms, u32 * max_reassemblies,
vnet_api_error_t ip4_full_reass_enable_disable (u32 sw_if_index,
u8 enable_disable);
int ip4_full_reass_enable_disable_with_refcnt (u32 sw_if_index,
int is_enable);
#endif /* __included_ip4_full_reass_h__ */
/*

View File

@ -164,6 +164,8 @@ typedef struct
u32 fq_index;
u32 fq_feature_index;
// reference count for enabling/disabling feature - per interface
u32 *feature_use_refcount_per_intf;
} ip6_full_reass_main_t;
extern ip6_full_reass_main_t ip6_full_reass_main;
@ -1427,6 +1429,7 @@ ip6_full_reass_init_function (vlib_main_t * vm)
rm->fq_feature_index =
vlib_frame_queue_main_init (ip6_full_reass_node_feature.index, 0);
rm->feature_use_refcount_per_intf = NULL;
return error;
}
@ -1790,6 +1793,35 @@ VLIB_REGISTER_NODE (ip6_full_reassembly_feature_handoff_node) = {
};
/* *INDENT-ON* */
#ifndef CLIB_MARCH_VARIANT
int
ip6_full_reass_enable_disable_with_refcnt (u32 sw_if_index, int is_enable)
{
ip6_full_reass_main_t *rm = &ip6_full_reass_main;
vec_validate (rm->feature_use_refcount_per_intf, sw_if_index);
if (is_enable)
{
if (!rm->feature_use_refcount_per_intf[sw_if_index])
{
++rm->feature_use_refcount_per_intf[sw_if_index];
return vnet_feature_enable_disable ("ip6-unicast",
"ip6-full-reassembly-feature",
sw_if_index, 1, 0, 0);
}
++rm->feature_use_refcount_per_intf[sw_if_index];
}
else
{
--rm->feature_use_refcount_per_intf[sw_if_index];
if (!rm->feature_use_refcount_per_intf[sw_if_index])
return vnet_feature_enable_disable ("ip6-unicast",
"ip6-full-reassembly-feature",
sw_if_index, 0, 0, 0);
}
return -1;
}
#endif
/*
* fd.io coding-style-patch-verification: ON
*

View File

@ -43,6 +43,9 @@ vnet_api_error_t ip6_full_reass_get (u32 * timeout_ms, u32 * max_reassemblies,
vnet_api_error_t ip6_full_reass_enable_disable (u32 sw_if_index,
u8 enable_disable);
int ip6_full_reass_enable_disable_with_refcnt (u32 sw_if_index,
int is_enable);
#endif /* __included_ip6_full_reass_h */
/*