TCP/UDP checksum offload API
[vpp.git] / src / plugins / dpdk / device / device.c
index e84d524..c755060 100644 (file)
@@ -44,7 +44,7 @@ static char *dpdk_tx_func_error_strings[] = {
 #undef _
 };
 
-clib_error_t *
+static clib_error_t *
 dpdk_set_mac_address (vnet_hw_interface_t * hi, char *address)
 {
   int error;
@@ -66,26 +66,6 @@ dpdk_set_mac_address (vnet_hw_interface_t * hi, char *address)
     }
 }
 
-clib_error_t *
-dpdk_set_mc_filter (vnet_hw_interface_t * hi,
-                   struct ether_addr mc_addr_vec[], int naddr)
-{
-  int error;
-  dpdk_main_t *dm = &dpdk_main;
-  dpdk_device_t *xd = vec_elt_at_index (dm->devices, hi->dev_instance);
-
-  error = rte_eth_dev_set_mc_addr_list (xd->device_index, mc_addr_vec, naddr);
-
-  if (error)
-    {
-      return clib_error_return (0, "mc addr list failed: %d", error);
-    }
-  else
-    {
-      return NULL;
-    }
-}
-
 struct rte_mbuf *
 dpdk_replicate_packet_mb (vlib_buffer_t * b)
 {
@@ -274,7 +254,11 @@ static_always_inline
                                  &tx_vector[tx_tail], tx_head - tx_tail);
          rv = rte_ring_sp_enqueue_burst (hqos->swq,
                                          (void **) &tx_vector[tx_tail],
+#if RTE_VERSION >= RTE_VERSION_NUM(17, 5, 0, 0)
+                                         (uint16_t) (tx_head - tx_tail), 0);
+#else
                                          (uint16_t) (tx_head - tx_tail));
+#endif
        }
       else if (PREDICT_TRUE (xd->flags & DPDK_DEVICE_FLAG_PMD))
        {
@@ -323,7 +307,7 @@ dpdk_prefetch_buffer_by_index (vlib_main_t * vm, u32 bi)
   struct rte_mbuf *mb;
   b = vlib_get_buffer (vm, bi);
   mb = rte_mbuf_from_vlib_buffer (b);
-  CLIB_PREFETCH (mb, CLIB_CACHE_LINE_BYTES, LOAD);
+  CLIB_PREFETCH (mb, 2 * CLIB_CACHE_LINE_BYTES, STORE);
   CLIB_PREFETCH (b, CLIB_CACHE_LINE_BYTES, LOAD);
 }
 
@@ -351,6 +335,37 @@ dpdk_buffer_recycle (vlib_main_t * vm, vlib_node_runtime_t * node,
   vec_add1 (dm->recycle[my_cpu], bi);
 }
 
+static_always_inline void
+dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b,
+                       struct rte_mbuf *mb)
+{
+  u32 ip_cksum = b->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM;
+  u32 tcp_cksum = b->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
+  u32 udp_cksum = b->flags & VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
+  int is_ip4 = b->flags & VNET_BUFFER_F_IS_IP4;
+  u64 ol_flags;
+
+  /* Is there any work for us? */
+  if (PREDICT_TRUE ((ip_cksum | tcp_cksum | udp_cksum) == 0))
+    return;
+
+  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;
+  mb->ol_flags |= ol_flags;
+
+  /* we are trying to help compiler here by using local ol_flags with known
+     state of all flags */
+  if (xd->flags & DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM)
+    rte_net_intel_cksum_flags_prepare (mb, ol_flags);
+}
+
 /*
  * Transmits the packets on the frame to the interface associated with the
  * node. It first copies packets on the frame to a tx_vector containing the
@@ -471,6 +486,15 @@ dpdk_interface_tx (vlib_main_t * vm,
       mb2 = rte_mbuf_from_vlib_buffer (b2);
       mb3 = rte_mbuf_from_vlib_buffer (b3);
 
+      if (PREDICT_FALSE ((xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD) &&
+                        (or_flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)))
+       {
+         dpdk_buffer_tx_offload (xd, b0, mb0);
+         dpdk_buffer_tx_offload (xd, b1, mb1);
+         dpdk_buffer_tx_offload (xd, b2, mb2);
+         dpdk_buffer_tx_offload (xd, b3, mb3);
+       }
+
       if (PREDICT_FALSE (or_flags & VLIB_BUFFER_RECYCLE))
        {
          dpdk_buffer_recycle (vm, node, b0, bi0, &mb0);
@@ -537,6 +561,7 @@ dpdk_interface_tx (vlib_main_t * vm,
       dpdk_validate_rte_mbuf (vm, b0, 1);
 
       mb0 = rte_mbuf_from_vlib_buffer (b0);
+      dpdk_buffer_tx_offload (xd, b0, mb0);
       dpdk_buffer_recycle (vm, node, b0, bi0, &mb0);
 
       if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
@@ -628,55 +653,29 @@ dpdk_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
   uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
   dpdk_main_t *dm = &dpdk_main;
   dpdk_device_t *xd = vec_elt_at_index (dm->devices, hif->dev_instance);
-  int rv = 0;
+
+  if (xd->flags & DPDK_DEVICE_FLAG_PMD_INIT_FAIL)
+    return clib_error_return (0, "Interface not initialized");
 
   if (is_up)
     {
-      f64 now = vlib_time_now (dm->vlib_main);
-
+      vnet_hw_interface_set_flags (vnm, xd->hw_if_index,
+                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
       if ((xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) == 0)
-       {
-         rv = rte_eth_dev_start (xd->device_index);
-         if (!rv && xd->default_mac_address)
-           rv = rte_eth_dev_default_mac_addr_set (xd->device_index,
-                                                  (struct ether_addr *)
-                                                  xd->default_mac_address);
-       }
-
-      if (xd->flags & DPDK_DEVICE_FLAG_PROMISC)
-       rte_eth_promiscuous_enable (xd->device_index);
-      else
-       rte_eth_promiscuous_disable (xd->device_index);
-
-      rte_eth_allmulticast_enable (xd->device_index);
+       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);
     }
   else
     {
-      xd->flags &= ~DPDK_DEVICE_FLAG_ADMIN_UP;
-
-      rte_eth_allmulticast_disable (xd->device_index);
       vnet_hw_interface_set_flags (vnm, xd->hw_if_index, 0);
-      rte_eth_dev_stop (xd->device_index);
-
-      /* For bonded interface, stop slave links */
-      if (xd->pmd == VNET_DPDK_PMD_BOND)
-       {
-         u8 slink[16];
-         int nlink = rte_eth_bond_slaves_get (xd->device_index, slink, 16);
-         while (nlink >= 1)
-           {
-             u8 dpdk_port = slink[--nlink];
-             rte_eth_dev_stop (dpdk_port);
-           }
-       }
+      if ((xd->flags & DPDK_DEVICE_FLAG_ADMIN_UP) != 0)
+       dpdk_device_stop (xd);
+      xd->flags &= ~DPDK_DEVICE_FLAG_ADMIN_UP;
     }
 
-  if (rv < 0)
-    clib_warning ("rte_eth_dev_%s error: %d", is_up ? "start" : "stop", rv);
-
   return /* no error */ 0;
 }