PMD now supports offloading the ip and tcp/udp checksum header calculation (including tunneled packets) to the hardware.
Signed-off-by: Moti Haimovsky <mo...@mellanox.com> --- drivers/net/mlx4/mlx4.c | 7 +++++++ drivers/net/mlx4/mlx4.h | 2 ++ drivers/net/mlx4/mlx4_ethdev.c | 6 ++++++ drivers/net/mlx4/mlx4_prm.h | 2 ++ drivers/net/mlx4/mlx4_rxtx.c | 25 +++++++++++++++++++++---- drivers/net/mlx4/mlx4_rxtx.h | 2 ++ drivers/net/mlx4/mlx4_txq.c | 4 +++- 7 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c index b084903..3149be6 100644 --- a/drivers/net/mlx4/mlx4.c +++ b/drivers/net/mlx4/mlx4.c @@ -397,6 +397,7 @@ struct mlx4_conf { .ports.present = 0, }; unsigned int vf; + unsigned int tunnel_en; int i; (void)pci_drv; @@ -456,6 +457,9 @@ struct mlx4_conf { rte_errno = ENODEV; goto error; } + /* Only cx3-pro supports L3 tunneling */ + tunnel_en = (device_attr.vendor_part_id == + PCI_DEVICE_ID_MELLANOX_CONNECTX3PRO); INFO("%u port(s) detected", device_attr.phys_port_cnt); conf.ports.present |= (UINT64_C(1) << device_attr.phys_port_cnt) - 1; if (mlx4_args(pci_dev->device.devargs, &conf)) { @@ -529,6 +533,9 @@ struct mlx4_conf { priv->pd = pd; priv->mtu = ETHER_MTU; priv->vf = vf; + priv->tunnel_en = tunnel_en; + priv->hw_csum = + !!(device_attr.device_cap_flags & IBV_DEVICE_RAW_IP_CSUM); /* Configure the first MAC address by default. */ if (mlx4_get_mac(priv, &mac.addr_bytes)) { ERROR("cannot get MAC address, is mlx4_en loaded?" diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h index 93e5502..439a828 100644 --- a/drivers/net/mlx4/mlx4.h +++ b/drivers/net/mlx4/mlx4.h @@ -104,6 +104,8 @@ struct priv { unsigned int vf:1; /* This is a VF device. */ unsigned int intr_alarm:1; /* An interrupt alarm is scheduled. */ unsigned int isolated:1; /* Toggle isolated mode. */ + unsigned int hw_csum:1; /* Checksum offload is supported. */ + unsigned int tunnel_en:1; /* Device tunneling is enabled */ struct rte_intr_handle intr_handle; /* Port interrupt handle. */ struct rte_flow_drop *flow_drop_queue; /* Flow drop queue. */ LIST_HEAD(mlx4_flows, rte_flow) flows; diff --git a/drivers/net/mlx4/mlx4_ethdev.c b/drivers/net/mlx4/mlx4_ethdev.c index a9e8059..e4ecbfa 100644 --- a/drivers/net/mlx4/mlx4_ethdev.c +++ b/drivers/net/mlx4/mlx4_ethdev.c @@ -553,6 +553,12 @@ info->max_mac_addrs = 1; info->rx_offload_capa = 0; info->tx_offload_capa = 0; + if (priv->hw_csum) + info->tx_offload_capa |= (DEV_TX_OFFLOAD_IPV4_CKSUM | + DEV_TX_OFFLOAD_UDP_CKSUM | + DEV_TX_OFFLOAD_TCP_CKSUM); + if (priv->tunnel_en) + info->tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM; if (mlx4_get_ifname(priv, &ifname) == 0) info->if_index = if_nametoindex(ifname); info->speed_capa = diff --git a/drivers/net/mlx4/mlx4_prm.h b/drivers/net/mlx4/mlx4_prm.h index 8b0248a..38e9a45 100644 --- a/drivers/net/mlx4/mlx4_prm.h +++ b/drivers/net/mlx4/mlx4_prm.h @@ -60,6 +60,8 @@ /* WQE flags */ #define MLX4_OPCODE_SEND 0x0a #define MLX4_EN_BIT_WQE_OWN 0x80000000 +#define MLX4_WQE_CTRL_IIP_HDR_CSUM (1 << 28) +#define MLX4_WQE_CTRL_IL4_HDR_CSUM (1 << 27) #define SIZE_TO_TXBBS(size) (RTE_ALIGN((size), (TXBB_SIZE)) / (TXBB_SIZE)) diff --git a/drivers/net/mlx4/mlx4_rxtx.c b/drivers/net/mlx4/mlx4_rxtx.c index dae0e47..3415f63 100644 --- a/drivers/net/mlx4/mlx4_rxtx.c +++ b/drivers/net/mlx4/mlx4_rxtx.c @@ -475,9 +475,27 @@ MLX4_WQE_CTRL_FENCE : 0) | ((wqe_real_size / 16) & 0x3f); owner_opcode = MLX4_OPCODE_SEND | ((sq->head & sq->txbb_cnt) ? MLX4_EN_BIT_WQE_OWN : 0); + /* Should we enable HW CKSUM offload ? */ + if (txq->priv->hw_csum && + (pkt->ol_flags & + (PKT_TX_IP_CKSUM | PKT_TX_TCP_CKSUM | PKT_TX_UDP_CKSUM))) { + const uint64_t is_tunneled = pkt->ol_flags & + (PKT_TX_TUNNEL_GRE | + PKT_TX_TUNNEL_VXLAN); + + if (is_tunneled && txq->tunnel_en) { + owner_opcode |= MLX4_WQE_CTRL_IIP_HDR_CSUM | + MLX4_WQE_CTRL_IL4_HDR_CSUM; + if (pkt->ol_flags & PKT_TX_OUTER_IP_CKSUM) + srcrb_flags |= MLX4_WQE_CTRL_IP_HDR_CSUM; + } else { + srcrb_flags |= MLX4_WQE_CTRL_IP_HDR_CSUM | + MLX4_WQE_CTRL_TCP_UDP_CSUM; + } + } /* fill in ctrl info but ownership */ mlx4_set_ctrl_seg(ctrl, fence_size, srcrb_flags, 0); - /* If we used a bounce buffer then copy wqe back into sq */ + /* If we used a bounce buffer then copy wqe back into sq */ if (unlikely(bounce)) ctrl = mlx4_bounce_to_desc(txq, head_idx, wqe_size); /* @@ -485,9 +503,8 @@ * setting ownership bit (because HW can start * executing as soon as we do). */ - rte_wmb(); - ctrl->owner_opcode = rte_cpu_to_be_32(owner_opcode); - + rte_wmb(); + ctrl->owner_opcode = rte_cpu_to_be_32(owner_opcode); sq->head += nr_txbbs; rte_wmb(); return 0; diff --git a/drivers/net/mlx4/mlx4_rxtx.h b/drivers/net/mlx4/mlx4_rxtx.h index 35e0de7..b4675b7 100644 --- a/drivers/net/mlx4/mlx4_rxtx.h +++ b/drivers/net/mlx4/mlx4_rxtx.h @@ -146,6 +146,8 @@ struct txq { unsigned int socket; /**< CPU socket ID for allocations. */ struct mlx4_sq msq; /**< Info for directly manipulating the SQ. */ struct mlx4_cq mcq; /**< Info for directly manipulating the CQ. */ + uint16_t tunnel_en:1; + /* When set TX offload for tunneled packets are supported. */ char *bounce_buf; /**< Side memory to be used when wqe wraps around */ }; diff --git a/drivers/net/mlx4/mlx4_txq.c b/drivers/net/mlx4/mlx4_txq.c index 6f6ea9c..cecd5e8 100644 --- a/drivers/net/mlx4/mlx4_txq.c +++ b/drivers/net/mlx4/mlx4_txq.c @@ -306,7 +306,7 @@ struct txq_mp2mr_mbuf_check_data { struct mlx4dv_obj mlxdv; struct mlx4dv_qp dv_qp; struct mlx4dv_cq dv_cq; - struct txq tmpl = { + struct txq tmpl = { .priv = priv, .socket = socket }; @@ -334,6 +334,8 @@ struct txq_mp2mr_mbuf_check_data { (void *)dev, strerror(rte_errno)); goto error; } + if (priv->tunnel_en) + tmpl.tunnel_en = 1; DEBUG("priv->device_attr.max_qp_wr is %d", priv->device_attr.max_qp_wr); DEBUG("priv->device_attr.max_sge is %d", -- 1.8.3.1