Remove useless prefetch in ip4-rewrite node
[vpp.git] / src / vnet / ip / ip4_forward.c
index 3cd6d3b..1911f08 100644 (file)
@@ -123,9 +123,6 @@ VLIB_NODE_FN (ip4_load_balance_node) (vlib_main_t * vm,
   n_left_from = frame->n_vectors;
   next = node->cached_next_index;
 
-  if (node->flags & VLIB_NODE_FLAG_TRACE)
-    ip4_forward_next_trace (vm, node, frame, VLIB_TX);
-
   while (n_left_from > 0)
     {
       vlib_get_next_frame (vm, node, next, to_next, n_left_to_next);
@@ -294,6 +291,9 @@ VLIB_NODE_FN (ip4_load_balance_node) (vlib_main_t * vm,
       vlib_put_next_frame (vm, node, next, n_left_to_next);
     }
 
+  if (node->flags & VLIB_NODE_FLAG_TRACE)
+    ip4_forward_next_trace (vm, node, frame, VLIB_TX);
+
   return frame->n_vectors;
 }
 
@@ -711,6 +711,7 @@ VNET_FEATURE_ARC_INIT (ip4_unicast, static) =
 {
   .arc_name = "ip4-unicast",
   .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+  .last_in_arc = "ip4-lookup",
   .arc_index_ptr = &ip4_main.lookup_main.ucast_feature_arc_index,
 };
 
@@ -753,13 +754,13 @@ VNET_FEATURE_INIT (ip4_policer_classify, static) =
 {
   .arc_name = "ip4-unicast",
   .node_name = "ip4-policer-classify",
-  .runs_before = VNET_FEATURES ("ipsec-input-ip4"),
+  .runs_before = VNET_FEATURES ("ipsec4-input"),
 };
 
 VNET_FEATURE_INIT (ip4_ipsec, static) =
 {
   .arc_name = "ip4-unicast",
-  .node_name = "ipsec-input-ip4",
+  .node_name = "ipsec4-input",
   .runs_before = VNET_FEATURES ("vpath-input-ip4"),
 };
 
@@ -796,6 +797,7 @@ VNET_FEATURE_ARC_INIT (ip4_multicast, static) =
 {
   .arc_name = "ip4-multicast",
   .start_nodes = VNET_FEATURES ("ip4-input", "ip4-input-no-checksum"),
+  .last_in_arc = "ip4-mfib-forward-lookup",
   .arc_index_ptr = &ip4_main.lookup_main.mcast_feature_arc_index,
 };
 
@@ -825,6 +827,7 @@ VNET_FEATURE_ARC_INIT (ip4_output, static) =
 {
   .arc_name = "ip4-output",
   .start_nodes = VNET_FEATURES ("ip4-rewrite", "ip4-midchain", "ip4-dvr-dpo"),
+  .last_in_arc = "interface-output",
   .arc_index_ptr = &ip4_main.lookup_main.output_feature_arc_index,
 };
 
@@ -839,13 +842,13 @@ VNET_FEATURE_INIT (ip4_outacl, static) =
 {
   .arc_name = "ip4-output",
   .node_name = "ip4-outacl",
-  .runs_before = VNET_FEATURES ("ipsec-output-ip4"),
+  .runs_before = VNET_FEATURES ("ipsec4-output"),
 };
 
 VNET_FEATURE_INIT (ip4_ipsec_output, static) =
 {
   .arc_name = "ip4-output",
-  .node_name = "ipsec-output-ip4",
+  .node_name = "ipsec4-output",
   .runs_before = VNET_FEATURES ("interface-output"),
 };
 
@@ -943,11 +946,11 @@ ip4_lookup_init (vlib_main_t * vm)
   {
     ethernet_arp_header_t h;
 
-    memset (&h, 0, sizeof (h));
+    clib_memset (&h, 0, sizeof (h));
 
     /* Set target ethernet address to all zeros. */
-    memset (h.ip4_over_ethernet[1].ethernet, 0,
-           sizeof (h.ip4_over_ethernet[1].ethernet));
+    clib_memset (h.ip4_over_ethernet[1].ethernet, 0,
+                sizeof (h.ip4_over_ethernet[1].ethernet));
 
 #define _16(f,v) h.f = clib_host_to_net_u16 (v);
 #define _8(f,v) h.f = v;
@@ -1072,9 +1075,9 @@ ip4_forward_next_trace (vlib_main_t * vm,
            vec_elt (im->fib_index_by_sw_if_index,
                     vnet_buffer (b0)->sw_if_index[VLIB_RX]);
 
-         clib_memcpy (t0->packet_data,
-                      vlib_buffer_get_current (b0),
-                      sizeof (t0->packet_data));
+         clib_memcpy_fast (t0->packet_data,
+                           vlib_buffer_get_current (b0),
+                           sizeof (t0->packet_data));
        }
       if (b1->flags & VLIB_BUFFER_IS_TRACED)
        {
@@ -1086,8 +1089,8 @@ ip4_forward_next_trace (vlib_main_t * vm,
             (u32) ~ 0) ? vnet_buffer (b1)->sw_if_index[VLIB_TX] :
            vec_elt (im->fib_index_by_sw_if_index,
                     vnet_buffer (b1)->sw_if_index[VLIB_RX]);
-         clib_memcpy (t1->packet_data, vlib_buffer_get_current (b1),
-                      sizeof (t1->packet_data));
+         clib_memcpy_fast (t1->packet_data, vlib_buffer_get_current (b1),
+                           sizeof (t1->packet_data));
        }
       from += 2;
       n_left -= 2;
@@ -1113,8 +1116,8 @@ ip4_forward_next_trace (vlib_main_t * vm,
             (u32) ~ 0) ? vnet_buffer (b0)->sw_if_index[VLIB_TX] :
            vec_elt (im->fib_index_by_sw_if_index,
                     vnet_buffer (b0)->sw_if_index[VLIB_RX]);
-         clib_memcpy (t0->packet_data, vlib_buffer_get_current (b0),
-                      sizeof (t0->packet_data));
+         clib_memcpy_fast (t0->packet_data, vlib_buffer_get_current (b0),
+                           sizeof (t0->packet_data));
        }
       from += 1;
       n_left -= 1;
@@ -1212,6 +1215,7 @@ VNET_FEATURE_ARC_INIT (ip4_local) =
 {
   .arc_name  = "ip4-local",
   .start_nodes = VNET_FEATURES ("ip4-local"),
+  .last_in_arc = "ip4-local-end-of-arc",
 };
 /* *INDENT-ON* */
 
@@ -1485,6 +1489,7 @@ enum ip_local_packet_type_e
 {
   IP_LOCAL_PACKET_TYPE_L4,
   IP_LOCAL_PACKET_TYPE_NAT,
+  IP_LOCAL_PACKET_TYPE_FRAG,
 };
 
 /**
@@ -1498,6 +1503,11 @@ ip4_local_classify (vlib_buffer_t * b, ip4_header_t * ip, u16 * next)
 {
   ip_lookup_main_t *lm = &ip4_main.lookup_main;
 
+  if (PREDICT_FALSE (ip4_is_fragment (ip)))
+    {
+      *next = IP_LOCAL_NEXT_REASSEMBLY;
+      return IP_LOCAL_PACKET_TYPE_FRAG;
+    }
   if (PREDICT_FALSE (b->flags & VNET_BUFFER_F_IS_NATED))
     {
       *next = lm->local_next_by_ip_protocol[ip->protocol];
@@ -1644,6 +1654,7 @@ VLIB_REGISTER_NODE (ip4_local_node) =
     [IP_LOCAL_NEXT_PUNT] = "ip4-punt",
     [IP_LOCAL_NEXT_UDP_LOOKUP] = "ip4-udp-lookup",
     [IP_LOCAL_NEXT_ICMP] = "ip4-icmp-input",
+    [IP_LOCAL_NEXT_REASSEMBLY] = "ip4-reassembly",
   },
 };
 /* *INDENT-ON* */
@@ -1743,7 +1754,7 @@ ip4_arp_inline (vlib_main_t * vm,
   u32 *from, *to_next_drop;
   uword n_left_from, n_left_to_next_drop, next_index;
   u32 thread_index = vm->thread_index;
-  u32 seed;
+  u64 seed;
 
   if (node->flags & VLIB_NODE_FLAG_TRACE)
     ip4_forward_next_trace (vm, node, frame, VLIB_TX);
@@ -1763,56 +1774,58 @@ ip4_arp_inline (vlib_main_t * vm,
 
       while (n_left_from > 0 && n_left_to_next_drop > 0)
        {
-         u32 pi0, adj_index0, r0, sw_if_index0, drop0;
+         u32 pi0, bi0, adj_index0, sw_if_index0;
          ip_adjacency_t *adj0;
-         vlib_buffer_t *p0;
-         ip4_header_t *ip0;
+         vlib_buffer_t *p0, *b0;
+         ip4_address_t resolve0;
+         ethernet_arp_header_t *h0;
+         vnet_hw_interface_t *hw_if0;
+         u64 r0;
 
          pi0 = from[0];
-
          p0 = vlib_get_buffer (vm, pi0);
 
+         from += 1;
+         n_left_from -= 1;
+         to_next_drop[0] = pi0;
+         to_next_drop += 1;
+         n_left_to_next_drop -= 1;
+
          adj_index0 = vnet_buffer (p0)->ip.adj_index[VLIB_TX];
          adj0 = adj_get (adj_index0);
-         ip0 = vlib_buffer_get_current (p0);
 
-         sw_if_index0 = adj0->rewrite_header.sw_if_index;
-         vnet_buffer (p0)->sw_if_index[VLIB_TX] = sw_if_index0;
-
-         if (PREDICT_TRUE (is_glean))
+         if (is_glean)
            {
-             /*
-              * this is the Glean case, so we are ARPing for the
-              * packet's destination
-              */
-             r0 = ip0->dst_address.data_u32;
+             /* resolve the packet's destination */
+             ip4_header_t *ip0 = vlib_buffer_get_current (p0);
+             resolve0 = ip0->dst_address;
            }
          else
            {
-             r0 = adj0->sub_type.nbr.next_hop.ip4.data_u32;
+             /* resolve the incomplete adj */
+             resolve0 = adj0->sub_type.nbr.next_hop.ip4;
            }
 
-         drop0 = throttle_check (&im->arp_throttle, thread_index, r0, seed);
-
-         from += 1;
-         n_left_from -= 1;
-         to_next_drop[0] = pi0;
-         to_next_drop += 1;
-         n_left_to_next_drop -= 1;
+         /* combine the address and interface for the hash key */
+         sw_if_index0 = adj0->rewrite_header.sw_if_index;
+         r0 = (u64) resolve0.data_u32 << 32;
+         r0 |= sw_if_index0;
 
-         p0->error =
-           node->errors[drop0 ? IP4_ARP_ERROR_DROP :
-                        IP4_ARP_ERROR_REQUEST_SENT];
+         if (throttle_check (&im->arp_throttle, thread_index, r0, seed))
+           {
+             p0->error = node->errors[IP4_ARP_ERROR_THROTTLED];
+             continue;
+           }
 
          /*
           * the adj has been updated to a rewrite but the node the DPO that got
           * us here hasn't - yet. no big deal. we'll drop while we wait.
           */
          if (IP_LOOKUP_NEXT_REWRITE == adj0->lookup_next_index)
-           continue;
-
-         if (drop0)
-           continue;
+           {
+             p0->error = node->errors[IP4_ARP_ERROR_RESOLVED];
+             continue;
+           }
 
          /*
           * Can happen if the control-plane is programming tables
@@ -1822,77 +1835,61 @@ ip4_arp_inline (vlib_main_t * vm,
              || (!is_glean && adj0->lookup_next_index != IP_LOOKUP_NEXT_ARP))
            {
              p0->error = node->errors[IP4_ARP_ERROR_NON_ARP_ADJ];
+             continue;
            }
-         else
-           /* Send ARP request. */
+         /* Send ARP request. */
+         h0 =
+           vlib_packet_template_get_packet (vm,
+                                            &im->ip4_arp_request_packet_template,
+                                            &bi0);
+
+         /* Seems we're out of buffers */
+         if (PREDICT_FALSE (!h0))
            {
-             u32 bi0 = 0;
-             vlib_buffer_t *b0;
-             ethernet_arp_header_t *h0;
-             vnet_hw_interface_t *hw_if0;
-
-             h0 =
-               vlib_packet_template_get_packet (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));
+             p0->error = node->errors[IP4_ARP_ERROR_NO_BUFFERS];
+             continue;
+           }
 
-             hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+         /* Add rewrite/encap string for ARP packet. */
+         vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t));
 
-             /* Src ethernet address in ARP header. */
-             clib_memcpy (h0->ip4_over_ethernet[0].ethernet,
-                          hw_if0->hw_address,
-                          sizeof (h0->ip4_over_ethernet[0].ethernet));
+         hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
 
-             if (is_glean)
-               {
-                 /* The interface's source address is stashed in the Glean Adj */
-                 h0->ip4_over_ethernet[0].ip4 =
-                   adj0->sub_type.glean.receive_addr.ip4;
-
-                 /* Copy in destination address we are requesting. This is the
-                  * glean case, so it's the packet's destination.*/
-                 h0->ip4_over_ethernet[1].ip4.data_u32 =
-                   ip0->dst_address.data_u32;
-               }
-             else
+         /* Src ethernet address in ARP header. */
+         clib_memcpy_fast (h0->ip4_over_ethernet[0].ethernet,
+                           hw_if0->hw_address,
+                           sizeof (h0->ip4_over_ethernet[0].ethernet));
+         if (is_glean)
+           {
+             /* The interface's source address is stashed in the Glean Adj */
+             h0->ip4_over_ethernet[0].ip4 =
+               adj0->sub_type.glean.receive_addr.ip4;
+           }
+         else
+           {
+             /* Src IP address in ARP header. */
+             if (ip4_src_address_for_packet (lm, sw_if_index0,
+                                             &h0->ip4_over_ethernet[0].ip4))
                {
-                 /* Src IP address in ARP header. */
-                 if (ip4_src_address_for_packet (lm, sw_if_index0,
-                                                 &h0->
-                                                 ip4_over_ethernet[0].ip4))
-                   {
-                     /* No source address available */
-                     p0->error =
-                       node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
-                     vlib_buffer_free (vm, &bi0, 1);
-                     continue;
-                   }
-
-                 /* Copy in destination address we are requesting from the
-                    incomplete adj */
-                 h0->ip4_over_ethernet[1].ip4.data_u32 =
-                   adj0->sub_type.nbr.next_hop.ip4.as_u32;
+                 /* No source address available */
+                 p0->error = node->errors[IP4_ARP_ERROR_NO_SOURCE_ADDRESS];
+                 vlib_buffer_free (vm, &bi0, 1);
+                 continue;
                }
+           }
+         h0->ip4_over_ethernet[1].ip4 = resolve0;
 
-             vlib_buffer_copy_trace_flag (vm, p0, bi0);
-             b0 = vlib_get_buffer (vm, bi0);
-             VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
-             vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
+         p0->error = node->errors[IP4_ARP_ERROR_REQUEST_SENT];
 
-             vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+         vlib_buffer_copy_trace_flag (vm, p0, bi0);
+         b0 = vlib_get_buffer (vm, bi0);
+         VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
+         vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
 
-             vlib_set_next_frame_buffer (vm, node,
-                                         adj0->rewrite_header.next_index,
-                                         bi0);
-           }
+         vlib_buffer_advance (b0, -adj0->rewrite_header.data_bytes);
+
+         vlib_set_next_frame_buffer (vm, node,
+                                     adj0->rewrite_header.next_index, bi0);
        }
 
       vlib_put_next_frame (vm, node, IP4_ARP_NEXT_DROP, n_left_to_next_drop);
@@ -1914,11 +1911,11 @@ VLIB_NODE_FN (ip4_glean_node) (vlib_main_t * vm, vlib_node_runtime_t * node,
 }
 
 static char *ip4_arp_error_strings[] = {
-  [IP4_ARP_ERROR_DROP] = "address overflow drops",
+  [IP4_ARP_ERROR_THROTTLED] = "ARP requests throttled",
+  [IP4_ARP_ERROR_RESOLVED] = "ARP requests resolved",
+  [IP4_ARP_ERROR_NO_BUFFERS] = "ARP requests out of buffer",
   [IP4_ARP_ERROR_REQUEST_SENT] = "ARP requests sent",
   [IP4_ARP_ERROR_NON_ARP_ADJ] = "ARPs to non-ARP adjacencies",
-  [IP4_ARP_ERROR_REPLICATE_DROP] = "ARP replication completed",
-  [IP4_ARP_ERROR_REPLICATE_FAIL] = "ARP replication failed",
   [IP4_ARP_ERROR_NO_SOURCE_ADDRESS] = "no source address for ARP request",
 };
 
@@ -1952,10 +1949,12 @@ VLIB_REGISTER_NODE (ip4_glean_node) =
 /* *INDENT-ON* */
 
 #define foreach_notrace_ip4_arp_error           \
-_(DROP)                                         \
+_(THROTTLED)                                    \
+_(RESOLVED)                                     \
+_(NO_BUFFERS)                                   \
 _(REQUEST_SENT)                                 \
-_(REPLICATE_DROP)                               \
-_(REPLICATE_FAIL)
+_(NON_ARP_ADJ)                                  \
+_(NO_SOURCE_ADDRESS)
 
 static clib_error_t *
 arp_notrace_init (vlib_main_t * vm)
@@ -2032,8 +2031,8 @@ ip4_probe_neighbor (vlib_main_t * vm, ip4_address_t * dst, u32 sw_if_index,
                                sw_if_index);
     }
 
-  clib_memcpy (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
-              sizeof (h->ip4_over_ethernet[0].ethernet));
+  clib_memcpy_fast (h->ip4_over_ethernet[0].ethernet, hi->hw_address,
+                   sizeof (h->ip4_over_ethernet[0].ethernet));
 
   h->ip4_over_ethernet[0].ip4 = src[0];
   h->ip4_over_ethernet[1].ip4 = dst[0];
@@ -2198,7 +2197,7 @@ ip4_rewrite_inline (vlib_main_t * vm,
   if (n_left_from >= 6)
     {
       int i;
-      for (i = 0; i < 6; i++)
+      for (i = 2; i < 6; i++)
        vlib_prefetch_buffer_header (bufs[i], LOAD);
     }