From e31d956d90882186070c174f987abc642b73d54e Mon Sep 17 00:00:00 2001 From: Ole Troan Date: Wed, 8 Nov 2017 11:10:54 +0100 Subject: [PATCH] MAP: Add RFC6052 mapping to MAP-T Change-Id: I2e311f8b7f50133678b9172e8d071826af491609 Signed-off-by: Ole Troan Signed-off-by: Juraj Sloboda --- src/vnet/map/ip6_map_t.c | 26 +++++++++++++++++++------- src/vnet/map/map.api | 4 +++- src/vnet/map/map.c | 25 +++++++++++++++++++++++-- src/vnet/map/map.h | 28 ++++++++++++++++++++-------- src/vnet/map/map_api.c | 9 ++++++++- 5 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/vnet/map/ip6_map_t.c b/src/vnet/map/ip6_map_t.c index 03cbfc1c16a..a6314c66ee6 100644 --- a/src/vnet/map/ip6_map_t.c +++ b/src/vnet/map/ip6_map_t.c @@ -59,7 +59,8 @@ ip6_map_fragment_cache (ip6_header_t * ip6, ip6_frag_hdr_t * frag, { u32 *ignore = NULL; map_ip4_reass_lock (); - map_ip4_reass_t *r = map_ip4_reass_get (map_get_ip4 (&ip6->src_address), + map_ip4_reass_t *r = map_ip4_reass_get (map_get_ip4 (&ip6->src_address, + d->flags), ip6_map_t_embedded_address (d, &ip6-> dst_address), @@ -82,7 +83,8 @@ ip6_map_fragment_get (ip6_header_t * ip6, ip6_frag_hdr_t * frag, { u32 *ignore = NULL; map_ip4_reass_lock (); - map_ip4_reass_t *r = map_ip4_reass_get (map_get_ip4 (&ip6->src_address), + map_ip4_reass_t *r = map_ip4_reass_get (map_get_ip4 (&ip6->src_address, + d->flags), ip6_map_t_embedded_address (d, &ip6-> dst_address), @@ -110,7 +112,7 @@ ip6_to_ip4_set_icmp_cb (ip6_header_t * ip6, ip4_header_t * ip4, void *arg) //Security check //Note that this prevents an intermediate IPv6 router from answering the request - ip4_sadr = map_get_ip4 (&ip6->src_address); + ip4_sadr = map_get_ip4 (&ip6->src_address, ctx->d->flags); if (ip6->src_address.as_u64[0] != map_get_pfx_net (ctx->d, ip4_sadr, ctx->sender_port) || ip6->src_address.as_u64[1] != map_get_sfx_net (ctx->d, ip4_sadr, @@ -132,7 +134,7 @@ ip6_to_ip4_set_inner_icmp_cb (ip6_header_t * ip6, ip4_header_t * ip4, u32 inner_ip4_dadr; //Security check of inner packet - inner_ip4_dadr = map_get_ip4 (&ip6->dst_address); + inner_ip4_dadr = map_get_ip4 (&ip6->dst_address, ctx->d->flags); if (ip6->dst_address.as_u64[0] != map_get_pfx_net (ctx->d, inner_ip4_dadr, ctx->sender_port) || ip6->dst_address.as_u64[1] != map_get_sfx_net (ctx->d, @@ -612,8 +614,10 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) ip60 = vlib_buffer_get_current (p0); ip61 = vlib_buffer_get_current (p1); - saddr0 = map_get_ip4 (&ip60->src_address); - saddr1 = map_get_ip4 (&ip61->src_address); + saddr0 = 0; /* TODO */ + saddr1 = 0; /* TODO */ + /* NOTE: ip6_map_get_domain currently doesn't utilize second argument */ + d0 = ip6_map_get_domain (vnet_buffer (p0)->ip.adj_index[VLIB_TX], (ip4_address_t *) & saddr0, &vnet_buffer (p0)->map_t.map_domain_index, @@ -624,6 +628,9 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) &vnet_buffer (p1)->map_t.map_domain_index, &error1); + saddr0 = map_get_ip4 (&ip60->src_address, d0->flags); + saddr1 = map_get_ip4 (&ip61->src_address, d1->flags); + vnet_buffer (p0)->map_t.v6.saddr = saddr0; vnet_buffer (p1)->map_t.v6.saddr = saddr1; vnet_buffer (p0)->map_t.v6.daddr = @@ -790,13 +797,18 @@ ip6_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame) p0 = vlib_get_buffer (vm, pi0); ip60 = vlib_buffer_get_current (p0); + //Save saddr in a different variable to not overwrite ip.adj_index - saddr = map_get_ip4 (&ip60->src_address); + saddr = 0; /* TODO */ + /* NOTE: ip6_map_get_domain currently doesn't utilize second argument */ + d0 = ip6_map_get_domain (vnet_buffer (p0)->ip.adj_index[VLIB_TX], (ip4_address_t *) & saddr, &vnet_buffer (p0)->map_t.map_domain_index, &error0); + saddr = map_get_ip4 (&ip60->src_address, d0->flags); + //FIXME: What if d0 is null vnet_buffer (p0)->map_t.v6.saddr = saddr; vnet_buffer (p0)->map_t.v6.daddr = diff --git a/src/vnet/map/map.api b/src/vnet/map/map.api index 14f10e73342..a63703aac01 100644 --- a/src/vnet/map/map.api +++ b/src/vnet/map/map.api @@ -13,7 +13,7 @@ * limitations under the License. */ -vl_api_version 1.0.0 +vl_api_version 1.1.0 /** \brief Add MAP domains @param client_index - opaque cookie to identify the sender @@ -27,6 +27,7 @@ vl_api_version 1.0.0 @param psid_offset - Port Set Identifider (PSID) offset @param psid_length - PSID length @param is_translation - MAP-E / MAP-T + @param is_rfc6052 - rfc6052 translation @param mtu - MTU */ define map_add_domain @@ -43,6 +44,7 @@ define map_add_domain u8 psid_offset; u8 psid_length; u8 is_translation; + u8 is_rfc6052; u16 mtu; }; diff --git a/src/vnet/map/map.c b/src/vnet/map/map.c index e3886d7e7e6..b2eefee9bb2 100644 --- a/src/vnet/map/map.c +++ b/src/vnet/map/map.c @@ -85,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 { @@ -586,6 +592,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'", @@ -919,6 +927,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) { @@ -933,13 +953,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) { diff --git a/src/vnet/map/map.h b/src/vnet/map/map.h index b9b3353dd2e..8bae222a24b 100644 --- a/src/vnet/map/map.h +++ b/src/vnet/map/map.h @@ -35,10 +35,12 @@ int map_add_del_psid (u32 map_domain_index, u16 psid, ip6_address_t * tep, u8 is_add); u8 *format_map_trace (u8 * s, va_list * args); -typedef enum __attribute__ ((__packed__)) +typedef enum { - MAP_DOMAIN_PREFIX = 1 << 0, MAP_DOMAIN_TRANSLATION = 1 << 1, // The domain uses MAP-T -} map_domain_flags_e; + MAP_DOMAIN_PREFIX = 1 << 0, + MAP_DOMAIN_TRANSLATION = 1 << 1, // The domain uses MAP-T + MAP_DOMAIN_RFC6052 = 1 << 2, +} __attribute__ ((__packed__)) map_domain_flags_e; /** * IP4 reassembly logic: @@ -382,6 +384,9 @@ map_get_sfx (map_domain_t *d, u32 addr, u16 port) if (d->ip6_prefix_len == 128) return clib_net_to_host_u64(d->ip6_prefix.as_u64[1]); + if (d->flags & MAP_DOMAIN_RFC6052) + return (clib_net_to_host_u64(d->ip6_prefix.as_u64[1]) | addr); + /* IPv4 prefix */ if (d->flags & MAP_DOMAIN_PREFIX) return (u64) (addr & (0xFFFFFFFF << d->suffix_shift)) << 16; @@ -398,9 +403,12 @@ map_get_sfx_net (map_domain_t *d, u32 addr, u16 port) } static_always_inline u32 -map_get_ip4 (ip6_address_t *addr) +map_get_ip4 (ip6_address_t *addr, map_domain_flags_e flags) { - return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1]) >> 16); + if (flags & MAP_DOMAIN_RFC6052) + return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1])); + else + return clib_host_to_net_u32(clib_net_to_host_u64(addr->as_u64[1]) >> 16); } /* @@ -427,16 +435,19 @@ ip6_map_get_domain (u32 mdi, { map_main_t *mm = &map_main; +#ifdef TODO /* * Disable direct MAP domain lookup on decap, until the security check is updated to verify IPv4 SA. * (That's done implicitly when MAP domain is looked up in the IPv4 FIB) */ -#ifdef MAP_NONSHARED_DOMAIN_ENABLED -#error "How can you be sure this domain is not shared?" + //#ifdef MAP_NONSHARED_DOMAIN_ENABLED + //#error "How can you be sure this domain is not shared?" +#endif + *map_domain_index = mdi; return pool_elt_at_index(mm->domains, mdi); -#endif +#ifdef TODO u32 lbi = ip4_fib_forwarding_lookup(0, addr); const dpo_id_t *dpo = load_balance_get_bucket(lbi, 0); if (PREDICT_TRUE(dpo->dpoi_type == map_dpo_type || @@ -447,6 +458,7 @@ ip6_map_get_domain (u32 mdi, } *error = MAP_ERROR_NO_DOMAIN; return NULL; +#endif } map_ip4_reass_t * diff --git a/src/vnet/map/map_api.c b/src/vnet/map/map_api.c index 994a64de480..35b82d42b16 100644 --- a/src/vnet/map/map_api.c +++ b/src/vnet/map/map_api.c @@ -56,7 +56,14 @@ vl_api_map_add_domain_t_handler (vl_api_map_add_domain_t * mp) vl_api_map_add_domain_reply_t *rmp; int rv = 0; u32 index; - u8 flags = mp->is_translation ? MAP_DOMAIN_TRANSLATION : 0; + u8 flags = 0; + + if (mp->is_translation) + flags |= MAP_DOMAIN_TRANSLATION; + + if (mp->is_rfc6052) + flags |= MAP_DOMAIN_RFC6052; + rv = map_create_domain ((ip4_address_t *) & mp->ip4_prefix, mp->ip4_prefix_len, (ip6_address_t *) & mp->ip6_prefix, mp->ip6_prefix_len, -- 2.16.6