vnet: ip4/6_local-> don't drop TCP/UCP marked for cksum calc fix
[vpp.git] / src / vnet / ip / ip4_forward.c
index 58cfd18..60a7fab 100755 (executable)
  * This file contains the source code for IPv4 forwarding.
  */
 
-void
-ip4_forward_next_trace (vlib_main_t * vm,
-                       vlib_node_runtime_t * node,
-                       vlib_frame_t * frame,
-                       vlib_rx_or_tx_t which_adj_index);
-
 always_inline uword
 ip4_lookup_inline (vlib_main_t * vm,
                   vlib_node_runtime_t * node,
@@ -1258,7 +1252,7 @@ format_ip4_forward_next_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
-  uword indent = format_get_indent (s);
+  u32 indent = format_get_indent (s);
   s = format (s, "%U%U",
              format_white_space, indent,
              format_ip4_header, t->packet_data, sizeof (t->packet_data));
@@ -1271,7 +1265,7 @@ format_ip4_lookup_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
-  uword indent = format_get_indent (s);
+  u32 indent = format_get_indent (s);
 
   s = format (s, "fib %d dpo-idx %d flow hash: 0x%08x",
              t->fib_index, t->dpo_index, t->flow_hash);
@@ -1287,7 +1281,7 @@ format_ip4_rewrite_trace (u8 * s, va_list * args)
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
   CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *);
   ip4_forward_next_trace_t *t = va_arg (*args, ip4_forward_next_trace_t *);
-  uword indent = format_get_indent (s);
+  u32 indent = format_get_indent (s);
 
   s = format (s, "tx_sw_if_index %d dpo-idx %d : %U flow hash: 0x%08x",
              t->fib_index, t->dpo_index, format_ip_adjacency,
@@ -1387,68 +1381,6 @@ ip4_forward_next_trace (vlib_main_t * vm,
     }
 }
 
-static uword
-ip4_drop_or_punt (vlib_main_t * vm,
-                 vlib_node_runtime_t * node,
-                 vlib_frame_t * frame, ip4_error_t error_code)
-{
-  u32 *buffers = vlib_frame_vector_args (frame);
-  uword n_packets = frame->n_vectors;
-
-  vlib_error_drop_buffers (vm, node, buffers,
-                          /* stride */ 1,
-                          n_packets,
-                          /* next */ 0,
-                          ip4_input_node.index, error_code);
-
-  if (node->flags & VLIB_NODE_FLAG_TRACE)
-    ip4_forward_next_trace (vm, node, frame, VLIB_TX);
-
-  return n_packets;
-}
-
-static uword
-ip4_drop (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
-  return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_DROP);
-}
-
-static uword
-ip4_punt (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * frame)
-{
-  return ip4_drop_or_punt (vm, node, frame, IP4_ERROR_ADJACENCY_PUNT);
-}
-
-/* *INDENT-OFF* */
-VLIB_REGISTER_NODE (ip4_drop_node, static) =
-{
-  .function = ip4_drop,
-  .name = "ip4-drop",
-  .vector_size = sizeof (u32),
-  .format_trace = format_ip4_forward_next_trace,
-  .n_next_nodes = 1,
-  .next_nodes = {
-    [0] = "error-drop",
-  },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (ip4_drop_node, ip4_drop);
-
-VLIB_REGISTER_NODE (ip4_punt_node, static) =
-{
-  .function = ip4_punt,
-  .name = "ip4-punt",
-  .vector_size = sizeof (u32),
-  .format_trace = format_ip4_forward_next_trace,
-  .n_next_nodes = 1,
-  .next_nodes = {
-    [0] = "error-punt",
-  },
-};
-
-VLIB_NODE_FUNCTION_MULTIARCH (ip4_punt_node, ip4_punt);
-/* *INDENT-ON */
-
 /* Compute TCP/UDP/ICMP4 checksum in software. */
 u16
 ip4_tcp_udp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
@@ -1483,11 +1415,12 @@ ip4_tcp_udp_compute_checksum (vlib_main_t * vm, vlib_buffer_t * p0,
 
   n_bytes_left = n_this_buffer = payload_length_host_byte_order;
   data_this_buffer = (void *) ip0 + ip_header_length;
-  n_ip_bytes_this_buffer = p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
+  n_ip_bytes_this_buffer =
+    p0->current_length - (((u8 *) ip0 - p0->data) - p0->current_data);
   if (n_this_buffer + ip_header_length > n_ip_bytes_this_buffer)
     {
       n_this_buffer = n_ip_bytes_this_buffer > ip_header_length ?
-         n_ip_bytes_this_buffer - ip_header_length : 0;
+       n_ip_bytes_this_buffer - ip_header_length : 0;
     }
   while (1)
     {
@@ -1565,7 +1498,9 @@ ip4_local_validate_l4 (vlib_main_t * vm, vlib_buffer_t * p, ip4_header_t * ip,
 }
 
 #define ip4_local_do_l4_check(is_tcp_udp, flags)                       \
-    (is_tcp_udp && !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED))
+    (is_tcp_udp && !(flags & VNET_BUFFER_F_L4_CHECKSUM_COMPUTED \
+    || flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM \
+    || flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM))
 
 static inline uword
 ip4_local_inline (vlib_main_t * vm,
@@ -1641,9 +1576,13 @@ ip4_local_inline (vlib_main_t * vm,
          is_tcp_udp1 = is_udp1 || proto1 == IP_PROTOCOL_TCP;
 
          good_tcp_udp0 =
-           (p0->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
-         good_tcp_udp1 =
-           (p1->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
+           (p0->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT
+            || (p0->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM
+                || p0->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)) != 0;
+         good_tcp_udp1 = (p1->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT
+                          || (p1->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM
+                              || p1->flags &
+                              VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)) != 0;
 
          if (PREDICT_FALSE (ip4_local_do_l4_check (is_tcp_udp0, p0->flags)
                             || ip4_local_do_l4_check (is_tcp_udp1,
@@ -1673,6 +1612,10 @@ ip4_local_inline (vlib_main_t * vm,
            (vnet_buffer (p1)->sw_if_index[VLIB_TX] ==
             (u32) ~ 0) ? fib_index1 : vnet_buffer (p1)->sw_if_index[VLIB_TX];
 
+         /* TODO maybe move to lookup? */
+         vnet_buffer (p0)->ip.fib_index = fib_index0;
+         vnet_buffer (p1)->ip.fib_index = fib_index1;
+
          mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
          mtrie1 = &ip4_fib_get (fib_index1)->mtrie;
 
@@ -1710,6 +1653,9 @@ ip4_local_inline (vlib_main_t * vm,
           *  - uRPF check for any route to source - accept if passes.
           *  - allow packets destined to the broadcast address from unknown sources
           */
+         if (p0->flags & VNET_BUFFER_F_IS_NATED)
+           goto skip_check0;
+
          error0 = ((error0 == IP4_ERROR_UNKNOWN_PROTOCOL &&
                     dpo0->dpoi_type == DPO_RECEIVE) ?
                    IP4_ERROR_SPOOFED_LOCAL_PACKETS : error0);
@@ -1717,6 +1663,11 @@ ip4_local_inline (vlib_main_t * vm,
                     !fib_urpf_check_size (lb0->lb_urpf) &&
                     ip0->dst_address.as_u32 != 0xFFFFFFFF)
                    ? IP4_ERROR_SRC_LOOKUP_MISS : error0);
+
+       skip_check0:
+         if (p1->flags & VNET_BUFFER_F_IS_NATED)
+           goto skip_checks;
+
          error1 = ((error1 == IP4_ERROR_UNKNOWN_PROTOCOL &&
                     dpo1->dpoi_type == DPO_RECEIVE) ?
                    IP4_ERROR_SPOOFED_LOCAL_PACKETS : error1);
@@ -1781,13 +1732,16 @@ ip4_local_inline (vlib_main_t * vm,
             until support of IP frag reassembly is implemented */
          proto0 = ip4_is_fragment (ip0) ? 0xfe : ip0->protocol;
 
-         if (head_of_feature_arc == 0)
+         if (head_of_feature_arc == 0 || p0->flags & VNET_BUFFER_F_IS_NATED)
            goto skip_check;
 
          is_udp0 = proto0 == IP_PROTOCOL_UDP;
          is_tcp_udp0 = is_udp0 || proto0 == IP_PROTOCOL_TCP;
+
          good_tcp_udp0 =
-           (p0->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT) != 0;
+           (p0->flags & VNET_BUFFER_F_L4_CHECKSUM_CORRECT
+            || (p0->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM
+                || p0->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM)) != 0;
 
          if (PREDICT_FALSE (ip4_local_do_l4_check (is_tcp_udp0, p0->flags)))
            {
@@ -1803,6 +1757,7 @@ ip4_local_inline (vlib_main_t * vm,
          fib_index0 =
            (vnet_buffer (p0)->sw_if_index[VLIB_TX] ==
             (u32) ~ 0) ? fib_index0 : vnet_buffer (p0)->sw_if_index[VLIB_TX];
+         vnet_buffer (p0)->ip.fib_index = fib_index0;
          mtrie0 = &ip4_fib_get (fib_index0)->mtrie;
          leaf0 = ip4_fib_mtrie_lookup_step_one (mtrie0, &ip0->src_address);
          leaf0 = ip4_fib_mtrie_lookup_step (mtrie0, leaf0, &ip0->src_address,
@@ -1862,8 +1817,8 @@ VLIB_REGISTER_NODE (ip4_local_node) =
   .n_next_nodes = IP_LOCAL_N_NEXT,
   .next_nodes =
   {
-    [IP_LOCAL_NEXT_DROP] = "error-drop",
-    [IP_LOCAL_NEXT_PUNT] = "error-punt",
+    [IP_LOCAL_NEXT_DROP] = "ip4-drop",
+    [IP_LOCAL_NEXT_PUNT] = "ip4-punt",
     [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
     [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",
   },
@@ -2093,6 +2048,10 @@ ip4_arp_inline (vlib_main_t * vm,
                                                 &im->ip4_arp_request_packet_template,
                                                 &bi0);
 
+             /* Seems we're out of buffers */
+             if (PREDICT_FALSE (!h0))
+               continue;
+
              /* Add rewrite/encap string for ARP packet. */
              vnet_rewrite_one_header (adj0[0], h0,
                                       sizeof (ethernet_header_t));