map: honor pre-resolve param in map-t

With this commit, forward the translated packet directly to the
specified next-hop if pre-resolve param is enabled in MAP-T.

Type: fix

Change-Id: Ie26080c7820318c7982599577a4af6e4d01a0574
Signed-off-by: Alexander Chernavin <achernavin@netgate.com>
(cherry picked from commit f145c15631ba62e798395499f83a2f8a91ae83c7)
Signed-off-by: Dave Wallace <dwallacelf@gmail.com>
This commit is contained in:
Alexander Chernavin 2020-02-11 09:57:09 -05:00 committed by Dave Wallace
parent 18d2d6bd4a
commit caa082a106
6 changed files with 153 additions and 30 deletions

View File

@ -123,20 +123,6 @@ ip4_map_vtcfl (ip4_header_t * ip4, vlib_buffer_t * p)
return (clib_host_to_net_u32 (vtcfl));
}
static_always_inline bool
ip4_map_ip6_lookup_bypass (vlib_buffer_t * p0, ip4_header_t * ip)
{
#ifdef MAP_SKIP_IP6_LOOKUP
if (FIB_NODE_INDEX_INVALID != pre_resolved[FIB_PROTOCOL_IP6].fei)
{
vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
pre_resolved[FIB_PROTOCOL_IP6].dpo.dpoi_index;
return (true);
}
#endif
return (false);
}
/*
* ip4_map_ttl
*/

View File

@ -29,6 +29,7 @@ typedef enum
typedef enum
{
IP4_MAPT_ICMP_NEXT_IP6_LOOKUP,
IP4_MAPT_ICMP_NEXT_IP6_REWRITE,
IP4_MAPT_ICMP_NEXT_IP6_FRAG,
IP4_MAPT_ICMP_NEXT_DROP,
IP4_MAPT_ICMP_N_NEXT
@ -37,6 +38,7 @@ typedef enum
typedef enum
{
IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP,
IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE,
IP4_MAPT_TCP_UDP_NEXT_IP6_FRAG,
IP4_MAPT_TCP_UDP_NEXT_DROP,
IP4_MAPT_TCP_UDP_N_NEXT
@ -45,6 +47,7 @@ typedef enum
typedef enum
{
IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP,
IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE,
IP4_MAPT_FRAGMENTED_NEXT_IP6_FRAG,
IP4_MAPT_FRAGMENTED_NEXT_DROP,
IP4_MAPT_FRAGMENTED_N_NEXT
@ -206,6 +209,11 @@ ip4_map_t_icmp (vlib_main_t * vm,
vnet_buffer (p0)->ip_frag.next_index = IP6_FRAG_NEXT_IP6_LOOKUP;
next0 = IP4_MAPT_ICMP_NEXT_IP6_FRAG;
}
else
{
next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
IP4_MAPT_ICMP_NEXT_IP6_REWRITE : next0;
}
err0:
if (PREDICT_TRUE (error0 == MAP_ERROR_NONE))
{
@ -325,6 +333,11 @@ ip4_map_t_fragmented (vlib_main_t * vm,
IP6_FRAG_NEXT_IP6_LOOKUP;
next0 = IP4_MAPT_FRAGMENTED_NEXT_IP6_FRAG;
}
else
{
next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE : next0;
}
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@ -491,6 +504,11 @@ ip4_map_t_tcp_udp (vlib_main_t * vm,
IP6_FRAG_NEXT_IP6_LOOKUP;
next0 = IP4_MAPT_TCP_UDP_NEXT_IP6_FRAG;
}
else
{
next0 = ip4_map_ip6_lookup_bypass (p0, NULL) ?
IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE : next0;
}
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
to_next, n_left_to_next, pi0,
@ -692,6 +710,7 @@ VLIB_REGISTER_NODE(ip4_map_t_fragmented_node) = {
.n_next_nodes = IP4_MAPT_FRAGMENTED_N_NEXT,
.next_nodes = {
[IP4_MAPT_FRAGMENTED_NEXT_IP6_LOOKUP] = "ip6-lookup",
[IP4_MAPT_FRAGMENTED_NEXT_IP6_REWRITE] = "ip6-load-balance",
[IP4_MAPT_FRAGMENTED_NEXT_IP6_FRAG] = IP6_FRAG_NODE_NAME,
[IP4_MAPT_FRAGMENTED_NEXT_DROP] = "error-drop",
},
@ -712,6 +731,7 @@ VLIB_REGISTER_NODE(ip4_map_t_icmp_node) = {
.n_next_nodes = IP4_MAPT_ICMP_N_NEXT,
.next_nodes = {
[IP4_MAPT_ICMP_NEXT_IP6_LOOKUP] = "ip6-lookup",
[IP4_MAPT_ICMP_NEXT_IP6_REWRITE] = "ip6-load-balance",
[IP4_MAPT_ICMP_NEXT_IP6_FRAG] = IP6_FRAG_NODE_NAME,
[IP4_MAPT_ICMP_NEXT_DROP] = "error-drop",
},
@ -732,6 +752,7 @@ VLIB_REGISTER_NODE(ip4_map_t_tcp_udp_node) = {
.n_next_nodes = IP4_MAPT_TCP_UDP_N_NEXT,
.next_nodes = {
[IP4_MAPT_TCP_UDP_NEXT_IP6_LOOKUP] = "ip6-lookup",
[IP4_MAPT_TCP_UDP_NEXT_IP6_REWRITE] = "ip6-load-balance",
[IP4_MAPT_TCP_UDP_NEXT_IP6_FRAG] = IP6_FRAG_NODE_NAME,
[IP4_MAPT_TCP_UDP_NEXT_DROP] = "error-drop",
},

View File

@ -149,20 +149,6 @@ ip6_map_security_check (map_domain_t * d, ip4_header_t * ip4,
}
}
static_always_inline bool
ip6_map_ip4_lookup_bypass (vlib_buffer_t * p0, ip4_header_t * ip)
{
#ifdef MAP_SKIP_IP6_LOOKUP
if (FIB_NODE_INDEX_INVALID != pre_resolved[FIB_PROTOCOL_IP4].fei)
{
vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
pre_resolved[FIB_PROTOCOL_IP4].dpo.dpoi_index;
return (true);
}
#endif
return (false);
}
/*
* ip6_map
*/

View File

@ -30,6 +30,7 @@ typedef enum
typedef enum
{
IP6_MAPT_ICMP_NEXT_IP4_LOOKUP,
IP6_MAPT_ICMP_NEXT_IP4_REWRITE,
IP6_MAPT_ICMP_NEXT_IP4_FRAG,
IP6_MAPT_ICMP_NEXT_DROP,
IP6_MAPT_ICMP_N_NEXT
@ -38,6 +39,7 @@ typedef enum
typedef enum
{
IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP,
IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE,
IP6_MAPT_TCP_UDP_NEXT_IP4_FRAG,
IP6_MAPT_TCP_UDP_NEXT_DROP,
IP6_MAPT_TCP_UDP_N_NEXT
@ -46,6 +48,7 @@ typedef enum
typedef enum
{
IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP,
IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE,
IP6_MAPT_FRAGMENTED_NEXT_IP4_FRAG,
IP6_MAPT_FRAGMENTED_NEXT_DROP,
IP6_MAPT_FRAGMENTED_N_NEXT
@ -211,6 +214,11 @@ ip6_map_t_icmp (vlib_main_t * vm,
vnet_buffer (p0)->ip_frag.next_index = IP4_FRAG_NEXT_IP4_LOOKUP;
next0 = IP6_MAPT_ICMP_NEXT_IP4_FRAG;
}
else
{
next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
IP6_MAPT_ICMP_NEXT_IP4_REWRITE : next0;
}
err0:
if (PREDICT_TRUE (error0 == MAP_ERROR_NONE))
{
@ -311,8 +319,7 @@ ip6_map_t_fragmented (vlib_main_t * vm,
n_left_from -= 1;
to_next += 1;
n_left_to_next -= 1;
next0 = IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP;
next0 = IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP;
p0 = vlib_get_buffer (vm, pi0);
if (map_ip6_to_ip4_fragmented (p0))
@ -330,6 +337,11 @@ ip6_map_t_fragmented (vlib_main_t * vm,
IP4_FRAG_NEXT_IP4_LOOKUP;
next0 = IP6_MAPT_FRAGMENTED_NEXT_IP4_FRAG;
}
else
{
next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE : next0;
}
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@ -495,6 +507,11 @@ ip6_map_t_tcp_udp (vlib_main_t * vm,
IP4_FRAG_NEXT_IP4_LOOKUP;
next0 = IP6_MAPT_TCP_UDP_NEXT_IP4_FRAG;
}
else
{
next0 = ip6_map_ip4_lookup_bypass (p0, NULL) ?
IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE : next0;
}
}
vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
@ -729,6 +746,7 @@ VLIB_REGISTER_NODE(ip6_map_t_fragmented_node) = {
.next_nodes =
{
[IP6_MAPT_FRAGMENTED_NEXT_IP4_LOOKUP] = "ip4-lookup",
[IP6_MAPT_FRAGMENTED_NEXT_IP4_REWRITE] = "ip4-load-balance",
[IP6_MAPT_FRAGMENTED_NEXT_IP4_FRAG] = IP4_FRAG_NODE_NAME,
[IP6_MAPT_FRAGMENTED_NEXT_DROP] = "error-drop",
},
@ -750,6 +768,7 @@ VLIB_REGISTER_NODE(ip6_map_t_icmp_node) = {
.next_nodes =
{
[IP6_MAPT_ICMP_NEXT_IP4_LOOKUP] = "ip4-lookup",
[IP6_MAPT_ICMP_NEXT_IP4_REWRITE] = "ip4-load-balance",
[IP6_MAPT_ICMP_NEXT_IP4_FRAG] = IP4_FRAG_NODE_NAME,
[IP6_MAPT_ICMP_NEXT_DROP] = "error-drop",
},
@ -771,6 +790,7 @@ VLIB_REGISTER_NODE(ip6_map_t_tcp_udp_node) = {
.next_nodes =
{
[IP6_MAPT_TCP_UDP_NEXT_IP4_LOOKUP] = "ip4-lookup",
[IP6_MAPT_TCP_UDP_NEXT_IP4_REWRITE] = "ip4-load-balance",
[IP6_MAPT_TCP_UDP_NEXT_IP4_FRAG] = IP4_FRAG_NODE_NAME,
[IP6_MAPT_TCP_UDP_NEXT_DROP] = "error-drop",
},

View File

@ -673,6 +673,34 @@ map_mss_clamping (tcp_header_t * tcp, ip_csum_t * sum, u16 mss_clamping)
}
}
static_always_inline bool
ip4_map_ip6_lookup_bypass (vlib_buffer_t * p0, ip4_header_t * ip)
{
#ifdef MAP_SKIP_IP6_LOOKUP
if (FIB_NODE_INDEX_INVALID != pre_resolved[FIB_PROTOCOL_IP6].fei)
{
vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
pre_resolved[FIB_PROTOCOL_IP6].dpo.dpoi_index;
return (true);
}
#endif
return (false);
}
static_always_inline bool
ip6_map_ip4_lookup_bypass (vlib_buffer_t * p0, ip4_header_t * ip)
{
#ifdef MAP_SKIP_IP6_LOOKUP
if (FIB_NODE_INDEX_INVALID != pre_resolved[FIB_PROTOCOL_IP4].fei)
{
vnet_buffer (p0)->ip.adj_index[VLIB_TX] =
pre_resolved[FIB_PROTOCOL_IP4].dpo.dpoi_index;
return (true);
}
#endif
return (false);
}
/*
* fd.io coding-style-patch-verification: ON
*

View File

@ -35,6 +35,8 @@ class TestMAP(VppTestCase):
self.pg0.admin_up()
self.pg0.config_ip4()
self.pg0.resolve_arp()
self.pg0.generate_remote_hosts(2)
self.pg0.configure_ipv4_neighbors()
# pg1 is 'outside' IPv6
self.pg1.admin_up()
@ -432,6 +434,86 @@ class TestMAP(VppTestCase):
for p in rx:
self.validate(p[1], p4_translated)
def test_map_t_pre_resolve(self):
""" MAP-T pre-resolve"""
# Add a domain that maps from pg0 to pg1
map_dst = '2001:db8::/32'
map_src = '1234:5678:90ab:cdef::/64'
ip4_pfx = '192.168.0.0/24'
tag = 'MAP-T Test Domain.'
self.vapi.map_add_domain(ip6_prefix=map_dst,
ip4_prefix=ip4_pfx,
ip6_src=map_src,
ea_bits_len=16,
psid_offset=6,
psid_length=4,
mtu=1500,
tag=tag)
# Enable MAP-T on interfaces.
self.vapi.map_if_enable_disable(is_enable=1,
sw_if_index=self.pg0.sw_if_index,
is_translation=1)
self.vapi.map_if_enable_disable(is_enable=1,
sw_if_index=self.pg1.sw_if_index,
is_translation=1)
# Enable pre-resolve option
self.vapi.map_param_add_del_pre_resolve(ip4_nh_address="10.1.2.3",
ip6_nh_address="4001::1",
is_add=1)
# Add a route to 4001::1 and expect the translated traffic to be
# sent via that route next-hop.
pre_res_route6 = VppIpRoute(self, "4001::1", 128,
[VppRoutePath(self.pg1.remote_hosts[2].ip6,
self.pg1.sw_if_index)])
pre_res_route6.add_vpp_config()
# Add a route to 10.1.2.3 and expect the "untranslated" traffic to be
# sent via that route next-hop.
pre_res_route4 = VppIpRoute(self, "10.1.2.3", 32,
[VppRoutePath(self.pg0.remote_hosts[1].ip4,
self.pg0.sw_if_index)])
pre_res_route4.add_vpp_config()
# Send an IPv4 packet that will be translated
p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac)
p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1')
payload = TCP(sport=0xabcd, dport=0xabcd)
p4 = (p_ether / p_ip4 / payload)
p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0",
dst="2001:db8:1f0::c0a8:1:f") / payload)
p6_translated.hlim -= 1
rx = self.send_and_expect(self.pg0, p4*1, self.pg1)
for p in rx:
self.assertEqual(p[Ether].dst, self.pg1.remote_hosts[2].mac)
self.validate(p[1], p6_translated)
# Send back an IPv6 packet that will be "untranslated"
p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac)
p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f',
dst='1234:5678:90ab:cdef:ac:1001:200:0')
p6 = (p_ether6 / p_ip6 / payload)
p4_translated = (IP(src='192.168.0.1',
dst=self.pg0.remote_ip4) / payload)
p4_translated.id = 0
p4_translated.ttl -= 1
rx = self.send_and_expect(self.pg1, p6*1, self.pg0)
for p in rx:
self.assertEqual(p[Ether].dst, self.pg0.remote_hosts[1].mac)
self.validate(p[1], p4_translated)
# Cleanup pre-resolve option
self.vapi.map_param_add_del_pre_resolve(ip4_nh_address="10.1.2.3",
ip6_nh_address="4001::1",
is_add=0)
if __name__ == '__main__':
unittest.main(testRunner=VppTestRunner)