diff options
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/map/ip4_map.c | 14 | ||||
-rw-r--r-- | src/plugins/map/ip4_map_t.c | 21 | ||||
-rw-r--r-- | src/plugins/map/ip6_map.c | 14 | ||||
-rw-r--r-- | src/plugins/map/ip6_map_t.c | 24 | ||||
-rw-r--r-- | src/plugins/map/map.h | 28 | ||||
-rw-r--r-- | src/plugins/map/test/test_map.py | 82 |
6 files changed, 153 insertions, 30 deletions
diff --git a/src/plugins/map/ip4_map.c b/src/plugins/map/ip4_map.c index 64da602e838..f92438e9161 100644 --- a/src/plugins/map/ip4_map.c +++ b/src/plugins/map/ip4_map.c @@ -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 */ diff --git a/src/plugins/map/ip4_map_t.c b/src/plugins/map/ip4_map_t.c index 21d17d77910..127a97e85e9 100644 --- a/src/plugins/map/ip4_map_t.c +++ b/src/plugins/map/ip4_map_t.c @@ -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", }, diff --git a/src/plugins/map/ip6_map.c b/src/plugins/map/ip6_map.c index d9db602bad8..303ccf00ead 100644 --- a/src/plugins/map/ip6_map.c +++ b/src/plugins/map/ip6_map.c @@ -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 */ diff --git a/src/plugins/map/ip6_map_t.c b/src/plugins/map/ip6_map_t.c index 5e2b63def8d..6757163bb1e 100644 --- a/src/plugins/map/ip6_map_t.c +++ b/src/plugins/map/ip6_map_t.c @@ -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", }, diff --git a/src/plugins/map/map.h b/src/plugins/map/map.h index a65a16a06d5..91732390cd2 100644 --- a/src/plugins/map/map.h +++ b/src/plugins/map/map.h @@ -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 * diff --git a/src/plugins/map/test/test_map.py b/src/plugins/map/test/test_map.py index f1388b39c65..31575fa58ca 100644 --- a/src/plugins/map/test/test_map.py +++ b/src/plugins/map/test/test_map.py @@ -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) |