From: Chengchang Tang Date: Tue, 23 Mar 2021 11:21:01 +0000 (+0800) Subject: net/hns3: support outer UDP checksum X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=d0ab89e633241a2fd82815df012c06864efa1607;p=dpdk.git net/hns3: support outer UDP checksum Kunpeng930 support outer UDP cksum, this patch add support for it. Signed-off-by: Chengchang Tang Signed-off-by: Min Hu (Connor) --- diff --git a/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index f4ee2f80ac..5082833f2b 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -87,6 +87,7 @@ New Features * Added support for freeing Tx mbuf on demand. * Added support for copper port in Kunpeng930. * Added support for runtime config to select IO burst function. + * Added support for outer UDP checksum in Kunpeng930. * **Updated NXP DPAA driver.** diff --git a/drivers/net/hns3/hns3_cmd.c b/drivers/net/hns3/hns3_cmd.c index 8b9f0759fb..03f8048f27 100644 --- a/drivers/net/hns3/hns3_cmd.c +++ b/drivers/net/hns3/hns3_cmd.c @@ -433,6 +433,9 @@ hns3_parse_capability(struct hns3_hw *hw, if (hns3_get_bit(caps, HNS3_CAPS_RXD_ADV_LAYOUT_B)) hns3_set_bit(hw->capability, HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B, 1); + if (hns3_get_bit(caps, HNS3_CAPS_UDP_TUNNEL_CSUM_B)) + hns3_set_bit(hw->capability, + HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B, 1); } static uint32_t diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 28aa27a3e3..3949153502 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -2620,6 +2620,9 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info) DEV_TX_OFFLOAD_MBUF_FAST_FREE | hns3_txvlan_cap_get(hw)); + if (hns3_dev_outer_udp_cksum_supported(hw)) + info->tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_UDP_CKSUM; + if (hns3_dev_indep_txrx_supported(hw)) info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP | RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP; diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index ec4b475fe7..0fc0a1c422 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -798,6 +798,7 @@ enum { #define HNS3_DEV_SUPPORT_INDEP_TXRX_B 0x6 #define HNS3_DEV_SUPPORT_STASH_B 0x7 #define HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B 0x9 +#define HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B 0xA #define hns3_dev_dcb_supported(hw) \ hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_DCB_B) @@ -831,6 +832,9 @@ enum { #define hns3_dev_rxd_adv_layout_supported(hw) \ hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_RXD_ADV_LAYOUT_B) +#define hns3_dev_outer_udp_cksum_supported(hw) \ + hns3_get_bit((hw)->capability, HNS3_DEV_SUPPORT_OUTER_UDP_CKSUM_B) + #define HNS3_DEV_PRIVATE_TO_HW(adapter) \ (&((struct hns3_adapter *)adapter)->hw) #define HNS3_DEV_PRIVATE_TO_PF(adapter) \ diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index f3eaefb878..e1e41b88b9 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -988,6 +988,9 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info) DEV_TX_OFFLOAD_MBUF_FAST_FREE | hns3_txvlan_cap_get(hw)); + if (hns3_dev_outer_udp_cksum_supported(hw)) + info->tx_offload_capa |= DEV_TX_OFFLOAD_OUTER_UDP_CKSUM; + if (hns3_dev_indep_txrx_supported(hw)) info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP | RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP; diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index f5c7d71f3a..75292799b4 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -2967,7 +2967,7 @@ hns3_fill_first_desc(struct hns3_tx_queue *txq, struct hns3_desc *desc, hdr_len += (ol_flags & PKT_TX_TUNNEL_MASK) ? rxm->outer_l2_len + rxm->outer_l3_len : 0; paylen = rxm->pkt_len - hdr_len; - desc->tx.paylen = rte_cpu_to_le_32(paylen); + desc->tx.paylen_fd_dop_ol4cs |= rte_cpu_to_le_32(paylen); hns3_set_tso(desc, paylen, rxm); /* @@ -3204,8 +3204,10 @@ hns3_parse_tunneling_params(struct hns3_tx_queue *txq, struct rte_mbuf *m, { struct hns3_desc *tx_ring = txq->tx_ring; struct hns3_desc *desc = &tx_ring[tx_desc_id]; + uint64_t ol_flags = m->ol_flags; uint32_t tmp_outer = 0; uint32_t tmp_inner = 0; + uint32_t tmp_ol4cs; int ret; /* @@ -3215,7 +3217,7 @@ hns3_parse_tunneling_params(struct hns3_tx_queue *txq, struct rte_mbuf *m, * calculations, the length of the L2 header include the outer and * inner, will be filled during the parsing of tunnel packects. */ - if (!(m->ol_flags & PKT_TX_TUNNEL_MASK)) { + if (!(ol_flags & PKT_TX_TUNNEL_MASK)) { /* * For non tunnel type the tunnel type id is 0, so no need to * assign a value to it. Only the inner(normal) L2 header length @@ -3230,7 +3232,8 @@ hns3_parse_tunneling_params(struct hns3_tx_queue *txq, struct rte_mbuf *m, * inner l2_len. It would lead a cksum error. So driver has to * calculate the header length. */ - if (unlikely(!(m->ol_flags & PKT_TX_OUTER_IP_CKSUM) && + if (unlikely(!(ol_flags & + (PKT_TX_OUTER_IP_CKSUM | PKT_TX_OUTER_UDP_CKSUM)) && m->outer_l2_len == 0)) { struct rte_net_hdr_lens hdr_len; (void)rte_net_get_ptype(m, &hdr_len, @@ -3247,6 +3250,9 @@ hns3_parse_tunneling_params(struct hns3_tx_queue *txq, struct rte_mbuf *m, desc->tx.ol_type_vlan_len_msec = rte_cpu_to_le_32(tmp_outer); desc->tx.type_cs_vlan_tso_len = rte_cpu_to_le_32(tmp_inner); + tmp_ol4cs = ol_flags & PKT_TX_OUTER_UDP_CKSUM ? + BIT(HNS3_TXD_OL4CS_B) : 0; + desc->tx.paylen_fd_dop_ol4cs = rte_cpu_to_le_32(tmp_ol4cs); return 0; } @@ -3376,31 +3382,78 @@ hns3_pkt_need_linearized(struct rte_mbuf *tx_pkts, uint32_t bd_num, return false; } +static bool +hns3_outer_ipv4_cksum_prepared(struct rte_mbuf *m, uint64_t ol_flags, + uint32_t *l4_proto) +{ + struct rte_ipv4_hdr *ipv4_hdr; + ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, + m->outer_l2_len); + if (ol_flags & PKT_TX_OUTER_IP_CKSUM) + ipv4_hdr->hdr_checksum = 0; + if (ol_flags & PKT_TX_OUTER_UDP_CKSUM) { + struct rte_udp_hdr *udp_hdr; + /* + * If OUTER_UDP_CKSUM is support, HW can caclulate the pseudo + * header for TSO packets + */ + if (ol_flags & PKT_TX_TCP_SEG) + return true; + udp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_udp_hdr *, + m->outer_l2_len + m->outer_l3_len); + udp_hdr->dgram_cksum = rte_ipv4_phdr_cksum(ipv4_hdr, ol_flags); + + return true; + } + *l4_proto = ipv4_hdr->next_proto_id; + return false; +} + +static bool +hns3_outer_ipv6_cksum_prepared(struct rte_mbuf *m, uint64_t ol_flags, + uint32_t *l4_proto) +{ + struct rte_ipv6_hdr *ipv6_hdr; + ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, + m->outer_l2_len); + if (ol_flags & PKT_TX_OUTER_UDP_CKSUM) { + struct rte_udp_hdr *udp_hdr; + /* + * If OUTER_UDP_CKSUM is support, HW can caclulate the pseudo + * header for TSO packets + */ + if (ol_flags & PKT_TX_TCP_SEG) + return true; + udp_hdr = rte_pktmbuf_mtod_offset(m, struct rte_udp_hdr *, + m->outer_l2_len + m->outer_l3_len); + udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(ipv6_hdr, ol_flags); + + return true; + } + *l4_proto = ipv6_hdr->proto; + return false; +} + static void hns3_outer_header_cksum_prepare(struct rte_mbuf *m) { uint64_t ol_flags = m->ol_flags; uint32_t paylen, hdr_len, l4_proto; + struct rte_udp_hdr *udp_hdr; if (!(ol_flags & (PKT_TX_OUTER_IPV4 | PKT_TX_OUTER_IPV6))) return; if (ol_flags & PKT_TX_OUTER_IPV4) { - struct rte_ipv4_hdr *ipv4_hdr; - ipv4_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv4_hdr *, - m->outer_l2_len); - l4_proto = ipv4_hdr->next_proto_id; - if (ol_flags & PKT_TX_OUTER_IP_CKSUM) - ipv4_hdr->hdr_checksum = 0; + if (hns3_outer_ipv4_cksum_prepared(m, ol_flags, &l4_proto)) + return; } else { - struct rte_ipv6_hdr *ipv6_hdr; - ipv6_hdr = rte_pktmbuf_mtod_offset(m, struct rte_ipv6_hdr *, - m->outer_l2_len); - l4_proto = ipv6_hdr->proto; + if (hns3_outer_ipv6_cksum_prepared(m, ol_flags, &l4_proto)) + return; } + /* driver should ensure the outer udp cksum is 0 for TUNNEL TSO */ if (l4_proto == IPPROTO_UDP && (ol_flags & PKT_TX_TCP_SEG)) { - struct rte_udp_hdr *udp_hdr; hdr_len = m->l2_len + m->l3_len + m->l4_len; hdr_len += m->outer_l2_len + m->outer_l3_len; paylen = m->pkt_len - hdr_len; @@ -3686,7 +3739,7 @@ hns3_tx_setup_4bd(struct hns3_desc *txdp, struct rte_mbuf **pkts) dma_addr = rte_mbuf_data_iova(*pkts); txdp->addr = rte_cpu_to_le_64(dma_addr); txdp->tx.send_size = rte_cpu_to_le_16((*pkts)->data_len); - txdp->tx.paylen = 0; + txdp->tx.paylen_fd_dop_ol4cs = 0; txdp->tx.type_cs_vlan_tso_len = 0; txdp->tx.ol_type_vlan_len_msec = 0; txdp->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(bd_flag); @@ -3702,7 +3755,7 @@ hns3_tx_setup_1bd(struct hns3_desc *txdp, struct rte_mbuf **pkts) dma_addr = rte_mbuf_data_iova(*pkts); txdp->addr = rte_cpu_to_le_64(dma_addr); txdp->tx.send_size = rte_cpu_to_le_16((*pkts)->data_len); - txdp->tx.paylen = 0; + txdp->tx.paylen_fd_dop_ol4cs = 0; txdp->tx.type_cs_vlan_tso_len = 0; txdp->tx.ol_type_vlan_len_msec = 0; txdp->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(bd_flag); diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h index 9adeb24e9a..cd042009a2 100644 --- a/drivers/net/hns3/hns3_rxtx.h +++ b/drivers/net/hns3/hns3_rxtx.h @@ -149,6 +149,7 @@ #define HNS3_TXD_MSS_S 0 #define HNS3_TXD_MSS_M (0x3fff << HNS3_TXD_MSS_S) +#define HNS3_TXD_OL4CS_B 22 #define HNS3_L2_LEN_UNIT 1UL #define HNS3_L3_LEN_UNIT 2UL #define HNS3_L4_LEN_UNIT 2UL @@ -234,7 +235,7 @@ struct hns3_desc { }; }; - uint32_t paylen; + uint32_t paylen_fd_dop_ol4cs; uint16_t tp_fe_sc_vld_ra_ri; uint16_t mss; } tx; @@ -503,6 +504,7 @@ struct hns3_queue_info { }; #define HNS3_TX_CKSUM_OFFLOAD_MASK ( \ + PKT_TX_OUTER_UDP_CKSUM | \ PKT_TX_OUTER_IP_CKSUM | \ PKT_TX_IP_CKSUM | \ PKT_TX_TCP_SEG | \ diff --git a/drivers/net/hns3/hns3_rxtx_vec_sve.c b/drivers/net/hns3/hns3_rxtx_vec_sve.c index 2a22a1aac1..90e45c616c 100644 --- a/drivers/net/hns3/hns3_rxtx_vec_sve.c +++ b/drivers/net/hns3/hns3_rxtx_vec_sve.c @@ -408,8 +408,9 @@ hns3_tx_fill_hw_ring_sve(struct hns3_tx_queue *txq, (uint64_t *)&txdp->tx.outer_vlan_tag, offsets, svdup_n_u64(0)); /* save offset 24~31byte of every BD */ - svst1_scatter_u64offset_u64(pg, (uint64_t *)&txdp->tx.paylen, - offsets, svdup_n_u64(valid_bit)); + svst1_scatter_u64offset_u64(pg, + (uint64_t *)&txdp->tx.paylen_fd_dop_ol4cs, + offsets, svdup_n_u64(valid_bit)); /* Increment bytes counter */ uint32_t idx;