vxlan: leverage vlib_get_buffers in vxlan_encap_inline
[vpp.git] / src / vnet / vxlan / encap.c
index f9871d5..2426a8c 100644 (file)
@@ -20,6 +20,7 @@
 #include <vnet/ethernet/ethernet.h>
 #include <vnet/vxlan/vxlan.h>
 #include <vnet/qos/qos_types.h>
+#include <vnet/adj/rewrite.h>
 
 /* Statistics (not all errors) */
 #define foreach_vxlan_encap_error    \
@@ -48,6 +49,7 @@ typedef struct {
   u32 vni;
 } vxlan_encap_trace_t;
 
+#ifndef CLIB_MARCH_VARIANT
 u8 * format_vxlan_encap_trace (u8 * s, va_list * args)
 {
   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*args, vlib_main_t *);
@@ -59,6 +61,7 @@ u8 * format_vxlan_encap_trace (u8 * s, va_list * args)
              t->tunnel_index, t->vni);
   return s;
 }
+#endif
 
 always_inline uword
 vxlan_encap_inline (vlib_main_t * vm,
@@ -78,6 +81,8 @@ vxlan_encap_inline (vlib_main_t * vm,
   u32 next0 = 0, next1 = 0;
   vxlan_tunnel_t * t0 = NULL, * t1 = NULL;
   index_t dpoi_idx0 = INDEX_INVALID, dpoi_idx1 = INDEX_INVALID;
+  vlib_buffer_t *bufs[VLIB_FRAME_SIZE];
+  vlib_buffer_t **b = bufs;
 
   from = vlib_frame_vector_args (from_frame);
   n_left_from = from_frame->n_vectors;
@@ -87,13 +92,13 @@ vxlan_encap_inline (vlib_main_t * vm,
   STATIC_ASSERT_SIZEOF(ip6_vxlan_header_t, 56);
   STATIC_ASSERT_SIZEOF(ip4_vxlan_header_t, 36);
 
-  word const underlay_hdr_len = is_ip4 ?
+  u8 const underlay_hdr_len = is_ip4 ?
     sizeof(ip4_vxlan_header_t) : sizeof(ip6_vxlan_header_t);
   u16 const l3_len = is_ip4 ? sizeof(ip4_header_t) : sizeof(ip6_header_t);
-  u32 const csum_flags = is_ip4 ?
-    VNET_BUFFER_F_OFFLOAD_IP_CKSUM | VNET_BUFFER_F_IS_IP4 |
-    VNET_BUFFER_F_OFFLOAD_UDP_CKSUM :
-    VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
+  u32 const csum_flags = is_ip4 ? VNET_BUFFER_F_OFFLOAD_IP_CKSUM |
+      VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM :
+      VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
+  vlib_get_buffers (vm, from, bufs, n_left_from);
 
   while (n_left_from > 0)
     {
@@ -106,33 +111,27 @@ vxlan_encap_inline (vlib_main_t * vm,
        {
          /* Prefetch next iteration. */
          {
-           vlib_buffer_t * p2, * p3;
+           vlib_prefetch_buffer_header (b[2], LOAD);
+           vlib_prefetch_buffer_header (b[3], LOAD);
 
-           p2 = vlib_get_buffer (vm, from[2]);
-           p3 = vlib_get_buffer (vm, from[3]);
-
-           vlib_prefetch_buffer_header (p2, LOAD);
-           vlib_prefetch_buffer_header (p3, LOAD);
-
-           CLIB_PREFETCH (p2->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
-           CLIB_PREFETCH (p3->data, 2*CLIB_CACHE_LINE_BYTES, LOAD);
+           CLIB_PREFETCH (b[2]->data - CLIB_CACHE_LINE_BYTES, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
+           CLIB_PREFETCH (b[3]->data - CLIB_CACHE_LINE_BYTES, 2 * CLIB_CACHE_LINE_BYTES, LOAD);
          }
 
-         u32 bi0 = from[0];
-         u32 bi1 = from[1];
-
-         vlib_buffer_t * b0 = vlib_get_buffer (vm, bi0);
-         vlib_buffer_t * b1 = vlib_get_buffer (vm, bi1);
-          u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
-          u32 flow_hash1 = vnet_l2_compute_flow_hash (b1);
-
-         to_next[0] = bi0;
-         to_next[1] = bi1;
+         u32 bi0 = to_next[0] = from[0];
+         u32 bi1 = to_next[1] = from[1];
          from += 2;
          to_next += 2;
          n_left_to_next -= 2;
          n_left_from -= 2;
 
+         vlib_buffer_t * b0 = b[0];
+         vlib_buffer_t * b1 = b[1];
+         b += 2;
+
+          u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
+          u32 flow_hash1 = vnet_l2_compute_flow_hash (b1);
+
          /* Get next node index and adj index from tunnel next_dpo */
          if (sw_if_index0 != vnet_buffer(b0)->sw_if_index[VLIB_TX])
            {
@@ -170,8 +169,9 @@ vxlan_encap_inline (vlib_main_t * vm,
           vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpoi_idx0;
           vnet_buffer(b1)->ip.adj_index[VLIB_TX] = dpoi_idx1;
 
-          ASSERT(vec_len(t0->rewrite) == underlay_hdr_len);
-          ASSERT(vec_len(t1->rewrite) == underlay_hdr_len);
+          ASSERT(t0->rewrite_header.data_bytes == underlay_hdr_len);
+          ASSERT(t1->rewrite_header.data_bytes == underlay_hdr_len);
+          vnet_rewrite_two_headers(*t0, *t1, vlib_buffer_get_current(b0), vlib_buffer_get_current(b1), underlay_hdr_len);
 
           vlib_buffer_advance (b0, -underlay_hdr_len);
           vlib_buffer_advance (b1, -underlay_hdr_len);
@@ -181,6 +181,9 @@ vxlan_encap_inline (vlib_main_t * vm,
           u16 payload_l0 = clib_host_to_net_u16 (len0 - l3_len);
           u16 payload_l1 = clib_host_to_net_u16 (len1 - l3_len);
 
+          void * underlay0 = vlib_buffer_get_current(b0);
+          void * underlay1 = vlib_buffer_get_current(b1);
+
           ip4_header_t * ip4_0, * ip4_1;
          qos_bits_t ip4_0_tos = 0, ip4_1_tos = 0;
           ip6_header_t * ip6_0, * ip6_1;
@@ -188,12 +191,8 @@ vxlan_encap_inline (vlib_main_t * vm,
           u8 * l3_0, * l3_1;
          if (is_ip4)
            {
-              ip4_vxlan_header_t * hdr0 = vlib_buffer_get_current(b0);
-              ip4_vxlan_header_t * rewrite0 = (void *)t0->rewrite;
-              ip4_vxlan_header_t * hdr1 = vlib_buffer_get_current(b1);
-              ip4_vxlan_header_t * rewrite1 = (void *)t1->rewrite;
-              *hdr0 = *rewrite0;
-              *hdr1 = *rewrite1;
+              ip4_vxlan_header_t * hdr0 = underlay0;
+              ip4_vxlan_header_t * hdr1 = underlay1;
 
              /* Fix the IP4 checksum and length */
              ip4_0 = &hdr0->ip4;
@@ -219,12 +218,8 @@ vxlan_encap_inline (vlib_main_t * vm,
            }
          else /* ipv6 */
            {
-              ip6_vxlan_header_t * hdr0 = vlib_buffer_get_current(b0);
-              ip6_vxlan_header_t * rewrite0 = (void *) t0->rewrite;
-              ip6_vxlan_header_t * hdr1 = vlib_buffer_get_current(b0);
-              ip6_vxlan_header_t * rewrite1 = (void *) t1->rewrite;
-              *hdr0 = *rewrite0;
-              *hdr1 = *rewrite1;
+              ip6_vxlan_header_t * hdr0 = underlay0;
+              ip6_vxlan_header_t * hdr1 = underlay1;
 
              /* Fix IP6 payload length */
               ip6_0 = &hdr0->ip6;
@@ -292,10 +287,22 @@ vxlan_encap_inline (vlib_main_t * vm,
                 udp1->checksum = 0xffff;
             }
 
+        /* save inner packet flow_hash for load-balance node */
+        vnet_buffer (b0)->ip.flow_hash = flow_hash0;
+        vnet_buffer (b1)->ip.flow_hash = flow_hash1;
+
+       if (sw_if_index0 == sw_if_index1)
+       {
+          vlib_increment_combined_counter (tx_counter, thread_index,
+              sw_if_index0, 2, len0 + len1);
+       }
+       else
+       {
           vlib_increment_combined_counter (tx_counter, thread_index,
               sw_if_index0, 1, len0);
           vlib_increment_combined_counter (tx_counter, thread_index,
               sw_if_index1, 1, len1);
+       }
           pkts_encapsulated += 2;
 
          if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED)) 
@@ -321,16 +328,17 @@ vxlan_encap_inline (vlib_main_t * vm,
 
       while (n_left_from > 0 && n_left_to_next > 0)
        {
-         u32 bi0 = from[0];
-         vlib_buffer_t * b0 = vlib_get_buffer (vm, bi0);
-          u32 flow_hash0 = vnet_l2_compute_flow_hash(b0);
-
-         to_next[0] = bi0;
+         u32 bi0 = to_next[0] = from[0];
          from += 1;
          to_next += 1;
          n_left_from -= 1;
          n_left_to_next -= 1;
 
+         vlib_buffer_t * b0 = b[0];
+         b += 1;
+
+          u32 flow_hash0 = vnet_l2_compute_flow_hash(b0);
+
          /* Get next node index and adj index from tunnel next_dpo */
          if (sw_if_index0 != vnet_buffer(b0)->sw_if_index[VLIB_TX])
            {
@@ -344,8 +352,11 @@ vxlan_encap_inline (vlib_main_t * vm,
            }
          vnet_buffer(b0)->ip.adj_index[VLIB_TX] = dpoi_idx0;
 
-          ASSERT(vec_len(t0->rewrite) == underlay_hdr_len);
+          ASSERT(t0->rewrite_header.data_bytes == underlay_hdr_len);
+          vnet_rewrite_one_header(*t0, vlib_buffer_get_current(b0), underlay_hdr_len);
+
           vlib_buffer_advance (b0, -underlay_hdr_len);
+          void * underlay0 = vlib_buffer_get_current(b0);
 
          u32 len0 = vlib_buffer_length_in_chain (vm, b0);
           u16 payload_l0 = clib_host_to_net_u16 (len0 - l3_len);
@@ -357,9 +368,7 @@ vxlan_encap_inline (vlib_main_t * vm,
           u8 * l3_0;
          if (is_ip4)
            {
-              ip4_vxlan_header_t * rewrite = (void *)t0->rewrite;
-              ip4_vxlan_header_t * hdr = vlib_buffer_get_current(b0);
-              *hdr = *rewrite;
+              ip4_vxlan_header_t * hdr = underlay0;
 
              /* Fix the IP4 checksum and length */
               ip4_0 = &hdr->ip4;
@@ -376,9 +385,7 @@ vxlan_encap_inline (vlib_main_t * vm,
            }
          else /* ip6 path */
            {
-              ip6_vxlan_header_t * hdr = vlib_buffer_get_current(b0);
-              ip6_vxlan_header_t * rewrite = (void *) t0->rewrite;
-              *hdr = *rewrite;
+              ip6_vxlan_header_t * hdr = underlay0;
 
              /* Fix IP6 payload length */
               ip6_0 = &hdr->ip6;
@@ -423,6 +430,9 @@ vxlan_encap_inline (vlib_main_t * vm,
                 udp0->checksum = 0xffff;
             }
 
+          /* reuse inner packet flow_hash for load-balance node */
+          vnet_buffer (b0)->ip.flow_hash = flow_hash0;
+
           vlib_increment_combined_counter (tx_counter, thread_index,
               sw_if_index0, 1, len0);
           pkts_encapsulated ++;
@@ -450,8 +460,7 @@ vxlan_encap_inline (vlib_main_t * vm,
   return from_frame->n_vectors;
 }
 
-static uword
-vxlan4_encap (vlib_main_t * vm,
+VLIB_NODE_FN (vxlan4_encap_node) (vlib_main_t * vm,
              vlib_node_runtime_t * node,
              vlib_frame_t * from_frame)
 {
@@ -461,8 +470,7 @@ vxlan4_encap (vlib_main_t * vm,
                             /* csum_offload */ 0);
 }
 
-static uword
-vxlan6_encap (vlib_main_t * vm,
+VLIB_NODE_FN (vxlan6_encap_node) (vlib_main_t * vm,
              vlib_node_runtime_t * node,
              vlib_frame_t * from_frame)
 {
@@ -472,7 +480,6 @@ vxlan6_encap (vlib_main_t * vm,
 }
 
 VLIB_REGISTER_NODE (vxlan4_encap_node) = {
-  .function = vxlan4_encap,
   .name = "vxlan4-encap",
   .vector_size = sizeof (u32),
   .format_trace = format_vxlan_encap_trace,
@@ -485,10 +492,7 @@ VLIB_REGISTER_NODE (vxlan4_encap_node) = {
   },
 };
 
-VLIB_NODE_FUNCTION_MULTIARCH (vxlan4_encap_node, vxlan4_encap)
-
 VLIB_REGISTER_NODE (vxlan6_encap_node) = {
-  .function = vxlan6_encap,
   .name = "vxlan6-encap",
   .vector_size = sizeof (u32),
   .format_trace = format_vxlan_encap_trace,
@@ -501,5 +505,3 @@ VLIB_REGISTER_NODE (vxlan6_encap_node) = {
   },
 };
 
-VLIB_NODE_FUNCTION_MULTIARCH (vxlan6_encap_node, vxlan6_encap)
-