diff options
Diffstat (limited to 'src/plugins/dpdk/device')
-rw-r--r-- | src/plugins/dpdk/device/device.c | 41 | ||||
-rw-r--r-- | src/plugins/dpdk/device/dpdk.h | 3 | ||||
-rwxr-xr-x | src/plugins/dpdk/device/init.c | 8 |
3 files changed, 52 insertions, 0 deletions
diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c index 8801bfd3a25..c755060d658 100644 --- a/src/plugins/dpdk/device/device.c +++ b/src/plugins/dpdk/device/device.c @@ -335,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 @@ -455,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); @@ -521,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)) diff --git a/src/plugins/dpdk/device/dpdk.h b/src/plugins/dpdk/device/dpdk.h index 55f63b37307..29a2c760e8d 100644 --- a/src/plugins/dpdk/device/dpdk.h +++ b/src/plugins/dpdk/device/dpdk.h @@ -38,6 +38,7 @@ #include <rte_version.h> #include <rte_eth_bond.h> #include <rte_sched.h> +#include <rte_net.h> #include <vnet/unix/pcap.h> #include <vnet/devices/devices.h> @@ -176,6 +177,8 @@ typedef struct #define DPDK_DEVICE_FLAG_HQOS (1 << 6) #define DPDK_DEVICE_FLAG_BOND_SLAVE (1 << 7) #define DPDK_DEVICE_FLAG_BOND_SLAVE_UP (1 << 8) +#define DPDK_DEVICE_FLAG_TX_OFFLOAD (1 << 9) +#define DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM (1 << 10) u16 nb_tx_desc; CLIB_CACHE_LINE_ALIGN_MARK (cacheline1); diff --git a/src/plugins/dpdk/device/init.c b/src/plugins/dpdk/device/init.c index 7ca3d358403..8a7080352e7 100755 --- a/src/plugins/dpdk/device/init.c +++ b/src/plugins/dpdk/device/init.c @@ -351,6 +351,11 @@ dpdk_lib_init (dpdk_main_t * dm) case VNET_DPDK_PMD_IGB: case VNET_DPDK_PMD_IXGBE: case VNET_DPDK_PMD_I40E: + xd->port_type = port_type_from_speed_capa (&dev_info); + xd->flags |= DPDK_DEVICE_FLAG_TX_OFFLOAD | + DPDK_DEVICE_FLAG_INTEL_PHDR_CKSUM; + + break; case VNET_DPDK_PMD_CXGBE: case VNET_DPDK_PMD_MLX4: case VNET_DPDK_PMD_MLX5: @@ -575,6 +580,9 @@ dpdk_lib_init (dpdk_main_t * dm) hi = vnet_get_hw_interface (dm->vnet_main, xd->hw_if_index); + if (xd->flags & DPDK_DEVICE_FLAG_TX_OFFLOAD) + hi->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD; + dpdk_device_setup (xd); if (vec_len (xd->errors)) |