vppinfra: Improve code portability
[vpp.git] / src / plugins / dpdk / device / device.c
index 94b3f6b..0ba5956 100644 (file)
@@ -25,7 +25,6 @@
 #include <vlib/unix/unix.h>
 
 #define foreach_dpdk_tx_func_error                     \
-  _(BAD_RETVAL, "DPDK tx function returned an error")  \
   _(PKT_DROP, "Tx packet drops (dpdk tx failure)")
 
 typedef enum
@@ -153,52 +152,30 @@ dpdk_validate_rte_mbuf (vlib_main_t * vm, vlib_buffer_t * b,
  * support multiple queues. It returns the number of packets untransmitted
  * If all packets are transmitted (the normal case), the function returns 0.
  */
-static_always_inline
-  u32 tx_burst_vector_internal (vlib_main_t * vm,
-                               dpdk_device_t * xd,
-                               struct rte_mbuf **mb, u32 n_left)
+static_always_inline u32
+tx_burst_vector_internal (vlib_main_t *vm, dpdk_device_t *xd,
+                         struct rte_mbuf **mb, u32 n_left, int queue_id,
+                         u8 is_shared)
 {
-  dpdk_main_t *dm = &dpdk_main;
   dpdk_tx_queue_t *txq;
   u32 n_retry;
   int n_sent = 0;
-  int queue_id;
 
   n_retry = 16;
-  queue_id = vm->thread_index % xd->tx_q_used;
   txq = vec_elt_at_index (xd->tx_queues, queue_id);
 
   do
     {
-      clib_spinlock_lock_if_init (&txq->lock);
-
-      if (PREDICT_TRUE (xd->flags & DPDK_DEVICE_FLAG_PMD))
-       {
-         /* no wrap, transmit in one burst */
-         n_sent = rte_eth_tx_burst (xd->port_id, queue_id, mb, n_left);
-         n_retry--;
-       }
-      else
-       {
-         ASSERT (0);
-         n_sent = 0;
-       }
+      if (is_shared)
+       clib_spinlock_lock (&txq->lock);
 
-      clib_spinlock_unlock_if_init (&txq->lock);
+      /* no wrap, transmit in one burst */
+      n_sent = rte_eth_tx_burst (xd->port_id, queue_id, mb, n_left);
 
-      if (PREDICT_FALSE (n_sent < 0))
-       {
-         // emit non-fatal message, bump counter
-         vnet_main_t *vnm = dm->vnet_main;
-         vnet_interface_main_t *im = &vnm->interface_main;
-         u32 node_index;
+      if (is_shared)
+       clib_spinlock_unlock (&txq->lock);
 
-         node_index = vec_elt_at_index (im->hw_interfaces,
-                                        xd->hw_if_index)->tx_node_index;
-
-         vlib_error_count (vm, node_index, DPDK_TX_FUNC_ERROR_BAD_RETVAL, 1);
-         return n_left;        // untransmitted packets
-       }
+      n_retry--;
       n_left -= n_sent;
       mb += n_sent;
     }
@@ -212,7 +189,7 @@ dpdk_prefetch_buffer (vlib_main_t * vm, struct rte_mbuf *mb)
 {
   vlib_buffer_t *b = vlib_buffer_from_rte_mbuf (mb);
   CLIB_PREFETCH (mb, sizeof (struct rte_mbuf), STORE);
-  CLIB_PREFETCH (b, CLIB_CACHE_LINE_BYTES, LOAD);
+  clib_prefetch_load (b);
 }
 
 static_always_inline void
@@ -221,36 +198,62 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b,
 {
   int is_ip4 = b->flags & VNET_BUFFER_F_IS_IP4;
   u32 tso = b->flags & VNET_BUFFER_F_GSO, max_pkt_len;
-  u32 oflags, ip_cksum, tcp_cksum, udp_cksum;
+  u32 ip_cksum, tcp_cksum, udp_cksum, outer_hdr_len = 0;
+  u32 outer_ip_cksum, vxlan_tunnel;
   u64 ol_flags;
+  vnet_buffer_oflags_t oflags = 0;
 
   /* Is there any work for us? */
   if (PREDICT_TRUE (((b->flags & VNET_BUFFER_F_OFFLOAD) | tso) == 0))
     return;
 
-  oflags = vnet_buffer2 (b)->oflags;
+  oflags = vnet_buffer (b)->oflags;
   ip_cksum = oflags & VNET_BUFFER_OFFLOAD_F_IP_CKSUM;
   tcp_cksum = oflags & VNET_BUFFER_OFFLOAD_F_TCP_CKSUM;
   udp_cksum = oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM;
+  outer_ip_cksum = oflags & VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM;
+  vxlan_tunnel = oflags & VNET_BUFFER_OFFLOAD_F_TNL_VXLAN;
 
-  mb->l2_len = vnet_buffer (b)->l3_hdr_offset - b->current_data;
-  mb->l3_len = vnet_buffer (b)->l4_hdr_offset -
-    vnet_buffer (b)->l3_hdr_offset;
-  mb->outer_l3_len = 0;
-  mb->outer_l2_len = 0;
-  ol_flags = is_ip4 ? PKT_TX_IPV4 : PKT_TX_IPV6;
-  ol_flags |= ip_cksum ? PKT_TX_IP_CKSUM : 0;
-  ol_flags |= tcp_cksum ? PKT_TX_TCP_CKSUM : 0;
-  ol_flags |= udp_cksum ? PKT_TX_UDP_CKSUM : 0;
+  ol_flags = is_ip4 ? RTE_MBUF_F_TX_IPV4 : RTE_MBUF_F_TX_IPV6;
+  ol_flags |= ip_cksum ? RTE_MBUF_F_TX_IP_CKSUM : 0;
+  ol_flags |= tcp_cksum ? RTE_MBUF_F_TX_TCP_CKSUM : 0;
+  ol_flags |= udp_cksum ? RTE_MBUF_F_TX_UDP_CKSUM : 0;
+
+  if (vxlan_tunnel)
+    {
+      ol_flags |= outer_ip_cksum ?
+                   RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM :
+                   RTE_MBUF_F_TX_OUTER_IPV6;
+      ol_flags |= RTE_MBUF_F_TX_TUNNEL_VXLAN;
+      mb->l2_len =
+       vnet_buffer (b)->l3_hdr_offset - vnet_buffer2 (b)->outer_l4_hdr_offset;
+      mb->l3_len =
+       vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset;
+      mb->outer_l2_len =
+       vnet_buffer2 (b)->outer_l3_hdr_offset - b->current_data;
+      mb->outer_l3_len = vnet_buffer2 (b)->outer_l4_hdr_offset -
+                        vnet_buffer2 (b)->outer_l3_hdr_offset;
+      outer_hdr_len = mb->outer_l2_len + mb->outer_l3_len;
+    }
+  else
+    {
+      mb->l2_len = vnet_buffer (b)->l3_hdr_offset - b->current_data;
+      mb->l3_len =
+       vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset;
+      mb->outer_l2_len = 0;
+      mb->outer_l3_len = 0;
+    }
 
   if (tso)
     {
       mb->l4_len = vnet_buffer2 (b)->gso_l4_hdr_sz;
       mb->tso_segsz = vnet_buffer2 (b)->gso_size;
       /* ensure packet is large enough to require tso */
-      max_pkt_len = mb->l2_len + mb->l3_len + mb->l4_len + mb->tso_segsz;
+      max_pkt_len =
+       outer_hdr_len + mb->l2_len + mb->l3_len + mb->l4_len + mb->tso_segsz;
       if (mb->tso_segsz != 0 && mb->pkt_len > max_pkt_len)
-       ol_flags |= (tcp_cksum ? PKT_TX_TCP_SEG : PKT_TX_UDP_SEG);
+       ol_flags |=
+         (tcp_cksum ? RTE_MBUF_F_TX_TCP_SEG : RTE_MBUF_F_TX_UDP_SEG);
     }
 
   mb->ol_flags |= ol_flags;
@@ -273,11 +276,13 @@ VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) (vlib_main_t * vm,
   dpdk_main_t *dm = &dpdk_main;
   vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
   dpdk_device_t *xd = vec_elt_at_index (dm->devices, rd->dev_instance);
+  vnet_hw_if_tx_frame_t *tf = vlib_frame_scalar_args (f);
   u32 n_packets = f->n_vectors;
   u32 n_left;
   u32 thread_index = vm->thread_index;
-  int queue_id = thread_index;
-  u32 tx_pkts = 0, all_or_flags = 0;
+  int queue_id = tf->queue_id;
+  u8 is_shared = tf->shared_queue;
+  u32 tx_pkts = 0;
   dpdk_per_thread_data_t *ptd = vec_elt_at_index (dm->per_thread_data,
                                                  thread_index);
   struct rte_mbuf **mb;
@@ -309,7 +314,6 @@ VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) (vlib_main_t * vm,
       b[3] = vlib_buffer_from_rte_mbuf (mb[3]);
 
       or_flags = b[0]->flags | b[1]->flags | b[2]->flags | b[3]->flags;
-      all_or_flags |= or_flags;
 
       if (or_flags & VLIB_BUFFER_NEXT_PRESENT)
        {
@@ -356,18 +360,17 @@ VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) (vlib_main_t * vm,
       vlib_buffer_t *b2, *b3;
       u32 or_flags;
 
-      CLIB_PREFETCH (mb[2], CLIB_CACHE_LINE_BYTES, STORE);
-      CLIB_PREFETCH (mb[3], CLIB_CACHE_LINE_BYTES, STORE);
+      clib_prefetch_store (mb[2]);
+      clib_prefetch_store (mb[3]);
       b2 = vlib_buffer_from_rte_mbuf (mb[2]);
-      CLIB_PREFETCH (b2, CLIB_CACHE_LINE_BYTES, LOAD);
+      clib_prefetch_load (b2);
       b3 = vlib_buffer_from_rte_mbuf (mb[3]);
-      CLIB_PREFETCH (b3, CLIB_CACHE_LINE_BYTES, LOAD);
+      clib_prefetch_load (b3);
 
       b[0] = vlib_buffer_from_rte_mbuf (mb[0]);
       b[1] = vlib_buffer_from_rte_mbuf (mb[1]);
 
       or_flags = b[0]->flags | b[1]->flags;
-      all_or_flags |= or_flags;
 
       if (or_flags & VLIB_BUFFER_NEXT_PRESENT)
        {
@@ -403,7 +406,6 @@ VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) (vlib_main_t * vm,
   while (n_left > 0)
     {
       b[0] = vlib_buffer_from_rte_mbuf (mb[0]);
-      all_or_flags |= b[0]->flags;
 
       dpdk_validate_rte_mbuf (vm, b[0], 1);
       dpdk_buffer_tx_offload (xd, b[0], mb[0]);
@@ -418,7 +420,8 @@ VNET_DEVICE_CLASS_TX_FN (dpdk_device_class) (vlib_main_t * vm,
 
   /* transmit as many packets as possible */
   tx_pkts = n_packets = mb - ptd->mbufs;
-  n_left = tx_burst_vector_internal (vm, xd, ptd->mbufs, n_packets);
+  n_left = tx_burst_vector_internal (vm, xd, ptd->mbufs, n_packets, queue_id,
+                                    is_shared);
 
   {
     /* If there is no callback then drop any non-transmitted packets */
@@ -469,11 +472,15 @@ dpdk_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
   if (is_up)
     {
       if ((xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) == 0)
-       dpdk_device_start (xd);
-      xd->flags |= DPDK_DEVICE_FLAG_ADMIN_UP;
-      f64 now = vlib_time_now (dm->vlib_main);
-      dpdk_update_counters (xd, now);
-      dpdk_update_link_state (xd, now);
+       {
+         dpdk_device_start (xd);
+         if (vec_len (xd->errors))
+           return clib_error_create ("Interface start failed");
+         xd->flags |= DPDK_DEVICE_FLAG_ADMIN_UP;
+         f64 now = vlib_time_now (vlib_get_main ());
+         dpdk_update_counters (xd, now);
+         dpdk_update_link_state (xd, now);
+       }
     }
   else
     {
@@ -506,7 +513,7 @@ dpdk_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index,
     }
 
   xd->per_interface_next_index =
-    vlib_node_add_next (xm->vlib_main, dpdk_input_node.index, node_index);
+    vlib_node_add_next (vlib_get_main (), dpdk_input_node.index, node_index);
 }
 
 
@@ -528,11 +535,8 @@ dpdk_subif_add_del_function (vnet_main_t * vnm,
   else if (xd->num_subifs)
     xd->num_subifs--;
 
-  if ((xd->flags & DPDK_DEVICE_FLAG_PMD) == 0)
-    goto done;
-
   /* currently we program VLANS only for IXGBE VF */
-  if (xd->pmd != VNET_DPDK_PMD_IXGBEVF)
+  if (xd->driver->program_vlans == 0)
     goto done;
 
   if (t->sub.eth.flags.no_tags == 1)
@@ -546,7 +550,7 @@ dpdk_subif_add_del_function (vnet_main_t * vnm,
     }
 
   vlan_offload = rte_eth_dev_get_vlan_offload (xd->port_id);
-  vlan_offload |= ETH_VLAN_FILTER_OFFLOAD;
+  vlan_offload |= RTE_ETH_VLAN_FILTER_OFFLOAD;
 
   if ((r = rte_eth_dev_set_vlan_offload (xd->port_id, vlan_offload)))
     {
@@ -620,7 +624,6 @@ dpdk_interface_set_rss_queues (struct vnet_main_t *vnm,
   clib_memset (reta, 0, dev_info.reta_size * sizeof (*reta));
 
   valid_queue_count = 0;
-  /* *INDENT-OFF* */
   clib_bitmap_foreach (i, bitmap)  {
     if (i >= dev_info.nb_rx_queues)
       {
@@ -629,7 +632,6 @@ dpdk_interface_set_rss_queues (struct vnet_main_t *vnm,
       }
     reta[valid_queue_count++] = i;
   }
-  /* *INDENT-ON* */
 
   /* check valid_queue_count not zero, make coverity happy */
   if (valid_queue_count == 0)
@@ -646,10 +648,8 @@ dpdk_interface_set_rss_queues (struct vnet_main_t *vnm,
     }
 
   /* update reta table */
-  reta_conf =
-    (struct rte_eth_rss_reta_entry64 *) clib_mem_alloc (dev_info.reta_size /
-                                                       RTE_RETA_GROUP_SIZE *
-                                                       sizeof (*reta_conf));
+  reta_conf = (struct rte_eth_rss_reta_entry64 *) clib_mem_alloc (
+    dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE * sizeof (*reta_conf));
   if (reta_conf == NULL)
     {
       err = clib_error_return (0, "clib_mem_alloc failed");
@@ -657,13 +657,13 @@ dpdk_interface_set_rss_queues (struct vnet_main_t *vnm,
     }
 
   clib_memset (reta_conf, 0,
-              dev_info.reta_size / RTE_RETA_GROUP_SIZE *
-              sizeof (*reta_conf));
+              dev_info.reta_size / RTE_ETH_RETA_GROUP_SIZE *
+                sizeof (*reta_conf));
 
   for (i = 0; i < dev_info.reta_size; i++)
     {
-      uint32_t reta_id = i / RTE_RETA_GROUP_SIZE;
-      uint32_t reta_pos = i % RTE_RETA_GROUP_SIZE;
+      uint32_t reta_id = i / RTE_ETH_RETA_GROUP_SIZE;
+      uint32_t reta_pos = i % RTE_ETH_RETA_GROUP_SIZE;
 
       reta_conf[reta_id].mask = UINT64_MAX;
       reta_conf[reta_id].reta[reta_pos] = reta[i];
@@ -721,7 +721,6 @@ dpdk_interface_rx_mode_change (vnet_main_t *vnm, u32 hw_if_index, u32 qid,
   return 0;
 }
 
-/* *INDENT-OFF* */
 VNET_DEVICE_CLASS (dpdk_device_class) = {
   .name = "dpdk",
   .tx_function_n_errors = DPDK_TX_FUNC_N_ERROR,
@@ -740,7 +739,6 @@ VNET_DEVICE_CLASS (dpdk_device_class) = {
   .set_rss_queues_function = dpdk_interface_set_rss_queues,
   .rx_mode_change_function = dpdk_interface_rx_mode_change,
 };
-/* *INDENT-ON* */
 
 #define UP_DOWN_FLAG_EVENT 1
 
@@ -787,14 +785,12 @@ admin_up_down_process (vlib_main_t * vm,
   return 0;                    /* or not */
 }
 
-/* *INDENT-OFF* */
 VLIB_REGISTER_NODE (admin_up_down_process_node) = {
     .function = admin_up_down_process,
     .type = VLIB_NODE_TYPE_PROCESS,
     .name = "admin-up-down-process",
     .process_log2_n_stack_bytes = 17,  // 256KB
 };
-/* *INDENT-ON* */
 
 /*
  * fd.io coding-style-patch-verification: ON