From 8973d7c4ca12eb05cd1560405d4aae210efc0734 Mon Sep 17 00:00:00 2001 From: "Min Hu (Connor)" Date: Tue, 14 Jul 2020 14:16:08 +0800 Subject: [PATCH] net/hns3: support keeping CRC CRC is the end of frame, which occupies 4 bytes. Keeping CRC is a feature of MAC, which will not strip CRC field when receiving frames. The feature can be enabled using DEV_RX_OFFLOAD_KEEP_CRC offload by upper level application. And the feature is only supported for hns3 PF PMD driver, not supported for hns3 VF PMD driver Signed-off-by: Min Hu (Connor) Signed-off-by: Wei Hu (Xavier) --- drivers/net/hns3/hns3_ethdev.c | 10 +++++- drivers/net/hns3/hns3_ethdev_vf.c | 1 - drivers/net/hns3/hns3_rxtx.c | 54 +++++++++++++++++++++++++++++-- drivers/net/hns3/hns3_rxtx.h | 3 ++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index 4712cc20fa..81e773046e 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -4184,7 +4184,15 @@ hns3_cfg_mac_mode(struct hns3_hw *hw, bool enable) hns3_set_bit(loop_en, HNS3_MAC_LINE_LP_B, 0); hns3_set_bit(loop_en, HNS3_MAC_FCS_TX_B, val); hns3_set_bit(loop_en, HNS3_MAC_RX_FCS_B, val); - hns3_set_bit(loop_en, HNS3_MAC_RX_FCS_STRIP_B, val); + + /* + * If DEV_RX_OFFLOAD_KEEP_CRC offload is set, MAC will not strip CRC + * when receiving frames. Otherwise, CRC will be stripped. + */ + if (hw->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC) + hns3_set_bit(loop_en, HNS3_MAC_RX_FCS_STRIP_B, 0); + else + hns3_set_bit(loop_en, HNS3_MAC_RX_FCS_STRIP_B, val); hns3_set_bit(loop_en, HNS3_MAC_TX_OVERSIZE_TRUNCATE_B, val); hns3_set_bit(loop_en, HNS3_MAC_RX_OVERSIZE_TRUNCATE_B, val); hns3_set_bit(loop_en, HNS3_MAC_TX_UNDER_MIN_ERR_B, val); diff --git a/drivers/net/hns3/hns3_ethdev_vf.c b/drivers/net/hns3/hns3_ethdev_vf.c index b881bbe79e..1d2941f0e3 100644 --- a/drivers/net/hns3/hns3_ethdev_vf.c +++ b/drivers/net/hns3/hns3_ethdev_vf.c @@ -913,7 +913,6 @@ hns3vf_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info) DEV_RX_OFFLOAD_SCTP_CKSUM | DEV_RX_OFFLOAD_OUTER_IPV4_CKSUM | DEV_RX_OFFLOAD_OUTER_UDP_CKSUM | - DEV_RX_OFFLOAD_KEEP_CRC | DEV_RX_OFFLOAD_SCATTER | DEV_RX_OFFLOAD_VLAN_STRIP | DEV_RX_OFFLOAD_VLAN_FILTER | diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index b0253d5f60..c0f798159c 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -1312,6 +1312,12 @@ hns3_rx_queue_setup(struct rte_eth_dev *dev, uint16_t idx, uint16_t nb_desc, rxq->ol3_csum_erros = 0; rxq->ol4_csum_erros = 0; + /* CRC len set here is used for amending packet length */ + if (dev->data->dev_conf.rxmode.offloads & DEV_RX_OFFLOAD_KEEP_CRC) + rxq->crc_len = RTE_ETHER_CRC_LEN; + else + rxq->crc_len = 0; + rte_spinlock_lock(&hw->lock); dev->data->rx_queues[idx] = rxq; rte_spinlock_unlock(&hw->lock); @@ -1578,6 +1584,23 @@ hns3_rxd_to_vlan_tci(struct hns3_rx_queue *rxq, struct rte_mbuf *mb, } } +static inline void +recalculate_data_len(struct rte_mbuf *first_seg, struct rte_mbuf *last_seg, + struct rte_mbuf *rxm, struct hns3_rx_queue *rxq, + uint16_t data_len) +{ + uint8_t crc_len = rxq->crc_len; + + if (data_len <= crc_len) { + rte_pktmbuf_free_seg(rxm); + first_seg->nb_segs--; + last_seg->data_len = (uint16_t)(last_seg->data_len - + (crc_len - data_len)); + last_seg->next = NULL; + } else + rxm->data_len = (uint16_t)(data_len - crc_len); +} + uint16_t hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { @@ -1708,7 +1731,11 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxdp->rx.bd_base_info = 0; rxdp->addr = dma_addr; - /* Load remained descriptor data and extract necessary fields */ + /* + * Load remained descriptor data and extract necessary fields. + * Data size from buffer description may contains CRC len, + * packet len should subtract it. + */ data_len = (uint16_t)(rte_le_to_cpu_16(rxd.rx.size)); l234_info = rte_le_to_cpu_32(rxd.rx.l234_info); ol_info = rte_le_to_cpu_32(rxd.rx.ol_info); @@ -1729,9 +1756,31 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) continue; } - /* The last buffer of the received packet */ + /* + * The last buffer of the received packet. packet len from + * buffer description may contains CRC len, packet len should + * subtract it, same as data len. + */ pkt_len = (uint16_t)(rte_le_to_cpu_16(rxd.rx.pkt_len)); first_seg->pkt_len = pkt_len; + + /* + * This is the last buffer of the received packet. If the CRC + * is not stripped by the hardware: + * - Subtract the CRC length from the total packet length. + * - If the last buffer only contains the whole CRC or a part + * of it, free the mbuf associated to the last buffer. If part + * of the CRC is also contained in the previous mbuf, subtract + * the length of that CRC part from the data length of the + * previous mbuf. + */ + rxm->next = NULL; + if (unlikely(rxq->crc_len > 0)) { + first_seg->pkt_len -= rxq->crc_len; + recalculate_data_len(first_seg, last_seg, rxm, rxq, + data_len); + } + first_seg->port = rxq->port_id; first_seg->hash.rss = rte_le_to_cpu_32(rxd.rx.rss_hash); first_seg->ol_flags = PKT_RX_RSS_HASH; @@ -1740,7 +1789,6 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rte_le_to_cpu_32(rxd.rx.fd_id); first_seg->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID; } - rxm->next = NULL; gro_size = hns3_get_field(bd_base_info, HNS3_RXD_GRO_SIZE_M, HNS3_RXD_GRO_SIZE_S); diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h index ccd508b74b..0d20a27c8b 100644 --- a/drivers/net/hns3/hns3_rxtx.h +++ b/drivers/net/hns3/hns3_rxtx.h @@ -256,6 +256,9 @@ struct hns3_rx_queue { */ uint16_t pvid_state; + /* 4 if DEV_RX_OFFLOAD_KEEP_CRC offload set, 0 otherwise */ + uint8_t crc_len; + bool rx_deferred_start; /* don't start this queue in dev start */ bool configured; /* indicate if rx queue has been configured */ -- 2.20.1