map: honor pre-resolve param in map-t
[vpp.git] / src / plugins / map / ip4_map_t.c
index a02b554..e9882e7 100644 (file)
@@ -22,6 +22,7 @@ typedef enum
   IP4_MAPT_NEXT_MAPT_TCP_UDP,
   IP4_MAPT_NEXT_MAPT_ICMP,
   IP4_MAPT_NEXT_MAPT_FRAGMENTED,
+  IP4_MAPT_NEXT_ICMP_ERROR,
   IP4_MAPT_NEXT_DROP,
   IP4_MAPT_N_NEXT
 } ip4_mapt_next_t;
@@ -29,6 +30,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 +39,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 +48,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
@@ -172,6 +176,11 @@ ip4_map_t_icmp (vlib_main_t * vm,
              vnet_buffer (p0)->ip_frag.next_index = IP_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))
            {
@@ -291,6 +300,11 @@ ip4_map_t_fragmented (vlib_main_t * vm,
                    IP_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,
@@ -457,6 +471,11 @@ ip4_map_t_tcp_udp (vlib_main_t * vm,
                    IP_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,
@@ -575,9 +594,41 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
              goto exit;
            }
 
+         dst_port0 = -1;
+
+         if (PREDICT_FALSE (ip40->ttl == 1))
+           {
+             icmp4_error_set_vnet_buffer (p0, ICMP4_time_exceeded,
+                                          ICMP4_time_exceeded_ttl_exceeded_in_transit,
+                                          0);
+             p0->error = error_node->errors[MAP_ERROR_TIME_EXCEEDED];
+             next0 = IP4_MAPT_NEXT_ICMP_ERROR;
+             goto trace;
+           }
+
+         bool df0 =
+           ip40->flags_and_fragment_offset &
+           clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
+
          vnet_buffer (p0)->map_t.mtu = d0->mtu ? d0->mtu : ~0;
 
-         dst_port0 = -1;
+         if (PREDICT_FALSE
+             (df0 && !map_main.frag_ignore_df
+              &&
+              ((ip4_len0 +
+                (sizeof (ip6_header_t) - sizeof (ip4_header_t))) >
+               vnet_buffer (p0)->map_t.mtu)))
+           {
+             icmp4_error_set_vnet_buffer (p0, ICMP4_destination_unreachable,
+                                          ICMP4_destination_unreachable_fragmentation_needed_and_dont_fragment_set,
+                                          vnet_buffer (p0)->map_t.mtu -
+                                          (sizeof (ip6_header_t) -
+                                           sizeof (ip4_header_t)));
+             p0->error = error_node->errors[MAP_ERROR_DF_SET];
+             next0 = IP4_MAPT_NEXT_ICMP_ERROR;
+             goto trace;
+           }
+
          ip4_map_t_classify (p0, d0, ip40, ip4_len0, &dst_port0, &error0,
                              &next0, l4_dst_port);
 
@@ -601,17 +652,6 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
          pheader0->daddr.as_u64[1] =
            map_get_sfx_net (d0, ip40->dst_address.as_u32, (u16) dst_port0);
 
-         bool df0 =
-           ip40->flags_and_fragment_offset &
-           clib_host_to_net_u16 (IP4_HEADER_FLAG_DONT_FRAGMENT);
-
-         if (PREDICT_TRUE (ip4_is_first_fragment (ip40) && df0))
-           {
-             p0->error = error_node->errors[MAP_ERROR_FRAGMENT_DROPPED];
-             next0 = IP4_MAPT_NEXT_MAPT_FRAGMENTED;
-             goto exit;
-           }
-
          if (PREDICT_TRUE
              (error0 == MAP_ERROR_NONE && next0 != IP4_MAPT_NEXT_MAPT_ICMP))
            {
@@ -625,7 +665,7 @@ ip4_map_t (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
 
          next0 = (error0 != MAP_ERROR_NONE) ? IP4_MAPT_NEXT_DROP : next0;
          p0->error = error_node->errors[error0];
-
+       trace:
          if (PREDICT_FALSE (p0->flags & VLIB_BUFFER_IS_TRACED))
            {
              map_add_trace (vm, node, p0, d0 - map_main.domains, dst_port0);
@@ -667,6 +707,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",
   },
@@ -687,6 +728,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",
   },
@@ -707,6 +749,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",
   },
@@ -729,6 +772,7 @@ VLIB_REGISTER_NODE(ip4_map_t_node) = {
       [IP4_MAPT_NEXT_MAPT_TCP_UDP] = "ip4-map-t-tcp-udp",
       [IP4_MAPT_NEXT_MAPT_ICMP] = "ip4-map-t-icmp",
       [IP4_MAPT_NEXT_MAPT_FRAGMENTED] = "ip4-map-t-fragmented",
+      [IP4_MAPT_NEXT_ICMP_ERROR] = "ip4-icmp-error",
       [IP4_MAPT_NEXT_DROP] = "error-drop",
   },
 };