X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvnet%2Fmap%2Fmap.c;h=702b5f80e5288fcaf459f298a76766b62d7af4de;hb=5fda7a3925be145f0c326d0aecc36d883cbcb2ee;hp=6a707df10c72f7ca115b59b9308bdee352d9a330;hpb=a0558307187ef2317f31e3e876a1a5e1faa2541c;p=vpp.git diff --git a/src/vnet/map/map.c b/src/vnet/map/map.c index 6a707df10c7..702b5f80e52 100644 --- a/src/vnet/map/map.c +++ b/src/vnet/map/map.c @@ -19,28 +19,11 @@ #include #include #include +#include #include "map.h" -#ifdef __SSE4_2__ -static inline u32 -crc_u32 (u32 data, u32 value) -{ - __asm__ volatile ("crc32l %[data], %[value];":[value] "+r" (value):[data] - "rm" (data)); - return value; -} -#else -#include - -static inline u32 -crc_u32 (u32 data, u32 value) -{ - u64 tmp = ((u64) data << 32) | (u64) value; - return (u32) clib_xxhash (tmp); -} -#endif - +map_main_t map_main; /* * This code supports the following MAP modes: @@ -76,91 +59,6 @@ crc_u32 (u32 data, u32 value) */ -i32 -ip4_get_port (ip4_header_t * ip, map_dir_e dir, u16 buffer_len) -{ - //TODO: use buffer length - if (ip->ip_version_and_header_length != 0x45 || - ip4_get_fragment_offset (ip)) - return -1; - - if (PREDICT_TRUE ((ip->protocol == IP_PROTOCOL_TCP) || - (ip->protocol == IP_PROTOCOL_UDP))) - { - udp_header_t *udp = (void *) (ip + 1); - return (dir == MAP_SENDER) ? udp->src_port : udp->dst_port; - } - else if (ip->protocol == IP_PROTOCOL_ICMP) - { - icmp46_header_t *icmp = (void *) (ip + 1); - if (icmp->type == ICMP4_echo_request || icmp->type == ICMP4_echo_reply) - { - return *((u16 *) (icmp + 1)); - } - else if (clib_net_to_host_u16 (ip->length) >= 64) - { - ip = (ip4_header_t *) (icmp + 2); - if (PREDICT_TRUE ((ip->protocol == IP_PROTOCOL_TCP) || - (ip->protocol == IP_PROTOCOL_UDP))) - { - udp_header_t *udp = (void *) (ip + 1); - return (dir == MAP_SENDER) ? udp->dst_port : udp->src_port; - } - else if (ip->protocol == IP_PROTOCOL_ICMP) - { - icmp46_header_t *icmp = (void *) (ip + 1); - if (icmp->type == ICMP4_echo_request || - icmp->type == ICMP4_echo_reply) - { - return *((u16 *) (icmp + 1)); - } - } - } - } - return -1; -} - -i32 -ip6_get_port (ip6_header_t * ip6, map_dir_e dir, u16 buffer_len) -{ - u8 l4_protocol; - u16 l4_offset; - u16 frag_offset; - u8 *l4; - - if (ip6_parse (ip6, buffer_len, &l4_protocol, &l4_offset, &frag_offset)) - return -1; - - //TODO: Use buffer length - - if (frag_offset && - ip6_frag_hdr_offset (((ip6_frag_hdr_t *) - u8_ptr_add (ip6, frag_offset)))) - return -1; //Can't deal with non-first fragment for now - - l4 = u8_ptr_add (ip6, l4_offset); - if (l4_protocol == IP_PROTOCOL_TCP || l4_protocol == IP_PROTOCOL_UDP) - { - return (dir == - MAP_SENDER) ? ((udp_header_t *) (l4))->src_port : ((udp_header_t - *) - (l4))->dst_port; - } - else if (l4_protocol == IP_PROTOCOL_ICMP6) - { - icmp46_header_t *icmp = (icmp46_header_t *) (l4); - if (icmp->type == ICMP6_echo_request) - { - return (dir == MAP_SENDER) ? ((u16 *) (icmp))[2] : -1; - } - else if (icmp->type == ICMP6_echo_reply) - { - return (dir == MAP_SENDER) ? -1 : ((u16 *) (icmp))[2]; - } - } - return -1; -} - int map_create_domain (ip4_address_t * ip4_prefix, @@ -187,6 +85,12 @@ map_create_domain (ip4_address_t * ip4_prefix, clib_warning ("MAP-T only supports ip6_src_len = 96 for now."); return -1; } + if ((flags & MAP_DOMAIN_RFC6052) && ip6_prefix_len != 96) + { + clib_warning ("RFC6052 translation only supports ip6_prefix_len = " + "96 for now"); + return -1; + } } else { @@ -202,7 +106,8 @@ map_create_domain (ip4_address_t * ip4_prefix, /* How many, and which bits to grab from the IPv4 DA */ if (ip4_prefix_len + ea_bits_len < 32) { - flags |= MAP_DOMAIN_PREFIX; + if (!(flags & MAP_DOMAIN_TRANSLATION)) + flags |= MAP_DOMAIN_PREFIX; suffix_shift = 32 - ip4_prefix_len - ea_bits_len; suffix_len = ea_bits_len; } @@ -222,6 +127,12 @@ map_create_domain (ip4_address_t * ip4_prefix, return -1; } + if (mm->is_ce && !(flags & MAP_DOMAIN_TRANSLATION)) + { + clib_warning ("MAP-E CE is not supported yet"); + return -1; + } + /* Get domain index */ pool_get_aligned (mm->domains, d, CLIB_CACHE_LINE_BYTES); memset (d, 0, sizeof (*d)); @@ -253,11 +164,23 @@ map_create_domain (ip4_address_t * ip4_prefix, map_dpo_create (DPO_PROTO_IP4, *map_domain_index, &dpo_v4); /* Create ip4 route */ + u8 ip4_pfx_len; + ip4_address_t ip4_pfx; + if (mm->is_ce) + { + ip4_pfx_len = 0; + ip4_pfx.as_u32 = 0; + } + else + { + ip4_pfx_len = d->ip4_prefix_len; + ip4_pfx = d->ip4_prefix; + } fib_prefix_t pfx = { .fp_proto = FIB_PROTOCOL_IP4, - .fp_len = d->ip4_prefix_len, + .fp_len = ip4_pfx_len, .fp_addr = { - .ip4 = d->ip4_prefix, + .ip4 = ip4_pfx, } , }; @@ -283,10 +206,22 @@ map_create_domain (ip4_address_t * ip4_prefix, * already exists and is MAP sourced, it is now MAP source n+1 times * and will need to be removed n+1 times. */ + u8 ip6_pfx_len; + ip6_address_t ip6_pfx; + if (mm->is_ce) + { + ip6_pfx_len = d->ip6_prefix_len; + ip6_pfx = d->ip6_prefix; + } + else + { + ip6_pfx_len = d->ip6_src_len; + ip6_pfx = d->ip6_src; + } fib_prefix_t pfx6 = { .fp_proto = FIB_PROTOCOL_IP6, - .fp_len = d->ip6_src_len, - .fp_addr.ip6 = d->ip6_src, + .fp_len = ip6_pfx_len, + .fp_addr.ip6 = ip6_pfx, }; fib_table_entry_special_dpo_add (0, &pfx6, @@ -421,9 +356,9 @@ map_pre_resolve_init (map_main_pre_resolved_t * pr) } static u8 * -format_map_pre_resolve (u8 * s, va_list ap) +format_map_pre_resolve (u8 * s, va_list * ap) { - map_main_pre_resolved_t *pr = va_arg (ap, map_main_pre_resolved_t *); + map_main_pre_resolved_t *pr = va_arg (*ap, map_main_pre_resolved_t *); if (FIB_NODE_INDEX_INVALID != pr->fei) { @@ -458,9 +393,7 @@ map_last_lock_gone (fib_node_t * node) static map_main_pre_resolved_t * map_from_fib_node (fib_node_t * node) { -#if (CLIB_DEBUG > 0) ASSERT (FIB_NODE_TYPE_MAP_E == node->fn_type); -#endif return ((map_main_pre_resolved_t *) (((char *) node) - STRUCT_OFFSET_OF (map_main_pre_resolved_t, node))); @@ -690,6 +623,8 @@ map_add_domain_command_fn (vlib_main_t * vm, num_m_args++; else if (unformat (line_input, "map-t")) flags |= MAP_DOMAIN_TRANSLATION; + else if (unformat (line_input, "rfc6052")) + flags |= (MAP_DOMAIN_TRANSLATION | MAP_DOMAIN_RFC6052); else { error = clib_error_return (0, "unknown input `%U'", @@ -1023,6 +958,18 @@ done: return error; } +static char * +map_flags_to_string (u32 flags) +{ + if (flags & MAP_DOMAIN_RFC6052) + return "rfc6052"; + if (flags & MAP_DOMAIN_PREFIX) + return "prefix"; + if (flags & MAP_DOMAIN_TRANSLATION) + return "map-t"; + return ""; +} + static u8 * format_map_domain (u8 * s, va_list * args) { @@ -1037,13 +984,14 @@ format_map_domain (u8 * s, va_list * args) ip6_prefix = d->ip6_prefix; s = format (s, - "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d psid-offset %d psid-len %d mtu %d %s", + "[%d] ip4-pfx %U/%d ip6-pfx %U/%d ip6-src %U/%d ea_bits_len %d " + "psid-offset %d psid-len %d mtu %d %s", d - mm->domains, format_ip4_address, &d->ip4_prefix, d->ip4_prefix_len, format_ip6_address, &ip6_prefix, d->ip6_prefix_len, format_ip6_address, &d->ip6_src, d->ip6_src_len, d->ea_bits_len, d->psid_offset, d->psid_length, d->mtu, - (d->flags & MAP_DOMAIN_TRANSLATION) ? "map-t" : ""); + map_flags_to_string (d->flags)); if (counters) { @@ -1210,7 +1158,10 @@ show_map_stats_command_fn (vlib_main_t * vm, unformat_input_t * input, map_domain_t *d; int domains = 0, rules = 0, domaincount = 0, rulecount = 0; if (pool_elts (mm->domains) == 0) - vlib_cli_output (vm, "No MAP domains are configured..."); + { + vlib_cli_output (vm, "No MAP domains are configured..."); + return 0; + } /* *INDENT-OFF* */ pool_foreach(d, mm->domains, ({ @@ -1573,10 +1524,12 @@ map_ip4_reass_get (u32 src, u32 dst, u16 fragment_id, }; u32 h = 0; - h = crc_u32 (k.as_u32[0], h); - h = crc_u32 (k.as_u32[1], h); - h = crc_u32 (k.as_u32[2], h); - h = crc_u32 (k.as_u32[3], h); +#ifdef clib_crc32c_uses_intrinsics + h = clib_crc32c ((u8 *) k.as_u32, 16); +#else + u64 tmp = k.as_u32[0] ^ k.as_u32[1] ^ k.as_u32[2] ^ k.as_u32[3]; + h = clib_xxhash (tmp); +#endif h = h >> (32 - mm->ip4_reass_ht_log2len); f64 now = vlib_time_now (mm->vlib_main); @@ -1745,8 +1698,15 @@ map_ip6_reass_get (ip6_address_t * src, ip6_address_t * dst, u32 fragment_id, u32 h = 0; int i; - for (i = 0; i < 10; i++) - h = crc_u32 (k.as_u32[i], h); + +#ifdef clib_crc32c_uses_intrinsics + h = clib_crc32c ((u8 *) k.as_u32, 40); +#else + u64 tmp = + k.as_u64[0] ^ k.as_u64[1] ^ k.as_u64[2] ^ k.as_u64[3] ^ k.as_u64[4]; + h = clib_xxhash (tmp); +#endif + h = h >> (32 - mm->ip6_reass_ht_log2len); f64 now = vlib_time_now (mm->vlib_main); @@ -2217,7 +2177,7 @@ VLIB_CLI_COMMAND(map_add_domain_command, static) = { .path = "map add domain", .short_help = "map add domain ip4-pfx ip6-pfx " "ip6-src ea-bits-len psid-offset psid-len " - "[map-t] [mtu ]", + "[map-t] [map-ce] [mtu ]", .function = map_add_domain_command_fn, }; @@ -2287,6 +2247,28 @@ VLIB_CLI_COMMAND(show_map_fragments_command, static) = { }; /* *INDENT-ON* */ +static clib_error_t * +map_config (vlib_main_t * vm, unformat_input_t * input) +{ + map_main_t *mm = &map_main; + u8 is_ce = false; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "customer edge")) + is_ce = true; + else + return clib_error_return (0, "unknown input '%U'", + format_unformat_error, input); + } + + mm->is_ce = is_ce; + + return 0; +} + +VLIB_CONFIG_FUNCTION (map_config, "map"); + /* * map_init */ @@ -2317,6 +2299,8 @@ map_init (vlib_main_t * vm) /* ICMP6 Type 1, Code 5 for security check failure */ mm->icmp6_enabled = false; + mm->is_ce = false; + /* Inner or outer fragmentation */ mm->frag_inner = false; mm->frag_ignore_df = false; @@ -2333,6 +2317,7 @@ map_init (vlib_main_t * vm) mm->ip4_reass_pool = 0; mm->ip4_reass_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES); + *mm->ip4_reass_lock = 0; mm->ip4_reass_conf_ht_ratio = MAP_IP4_REASS_HT_RATIO_DEFAULT; mm->ip4_reass_conf_lifetime_ms = MAP_IP4_REASS_LIFETIME_DEFAULT; mm->ip4_reass_conf_pool_size = MAP_IP4_REASS_POOL_SIZE_DEFAULT; @@ -2348,6 +2333,7 @@ map_init (vlib_main_t * vm) mm->ip6_reass_pool = 0; mm->ip6_reass_lock = clib_mem_alloc_aligned (CLIB_CACHE_LINE_BYTES, CLIB_CACHE_LINE_BYTES); + *mm->ip6_reass_lock = 0; mm->ip6_reass_conf_ht_ratio = MAP_IP6_REASS_HT_RATIO_DEFAULT; mm->ip6_reass_conf_lifetime_ms = MAP_IP6_REASS_LIFETIME_DEFAULT; mm->ip6_reass_conf_pool_size = MAP_IP6_REASS_POOL_SIZE_DEFAULT;