[RFC] net/gve: add IPv4 checksum offloading capability
Checks
Commit Message
Gvnic's DQO format allows offloading IPv4 checksum.
Made changes to Tx and Rx path to translate DPDK flags
to descriptor for offloading (and vice-versa).
Added ptype adminq support to only add this flags for
supported L3/L4 packet-types.
---
drivers/net/gve/gve_ethdev.c | 29 +++++++++++++++++++++++++--
drivers/net/gve/gve_ethdev.h | 5 +++++
drivers/net/gve/gve_rx_dqo.c | 38 ++++++++++++++++++++++++++++++++++--
drivers/net/gve/gve_tx_dqo.c | 2 +-
4 files changed, 69 insertions(+), 5 deletions(-)
@@ -434,8 +434,14 @@ gve_dev_info_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
RTE_ETH_TX_OFFLOAD_TCP_TSO;
- if (priv->queue_format == GVE_DQO_RDA_FORMAT)
- dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_TCP_LRO;
+ if (!gve_is_gqi(priv)) {
+ dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM;
+ dev_info->rx_offload_capa |=
+ RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
+ RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
+ RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
+ RTE_ETH_RX_OFFLOAD_TCP_LRO;
+ }
dev_info->default_rxconf = (struct rte_eth_rxconf) {
.rx_free_thresh = GVE_DEFAULT_RX_FREE_THRESH,
@@ -938,6 +944,8 @@ gve_teardown_device_resources(struct gve_priv *priv)
if (err)
PMD_DRV_LOG(ERR, "Could not deconfigure device resources: err=%d", err);
}
+ rte_free(priv->ptype_lut_dqo);
+ priv->ptype_lut_dqo = NULL;
gve_free_counter_array(priv);
gve_free_irq_db(priv);
gve_clear_device_resources_ok(priv);
@@ -997,8 +1005,25 @@ gve_setup_device_resources(struct gve_priv *priv)
PMD_DRV_LOG(ERR, "Could not config device resources: err=%d", err);
goto free_irq_dbs;
}
+
+ priv->ptype_lut_dqo = rte_zmalloc("gve_ptype_lut_dqo",
+ sizeof(struct gve_ptype_lut), 0);
+ if (priv->ptype_lut_dqo == NULL) {
+ PMD_DRV_LOG(ERR, "Failed to alloc ptype lut.");
+ err = -ENOMEM;
+ goto free_irq_dbs;
+ }
+ err = gve_adminq_get_ptype_map_dqo(priv, priv->ptype_lut_dqo);
+ if (unlikely(err)) {
+ PMD_DRV_LOG(ERR, "Failed to get ptype map: err=%d", err);
+ goto free_ptype_lut;
+ }
+
return 0;
+free_ptype_lut:
+ rte_free(priv->ptype_lut_dqo);
+ priv->ptype_lut_dqo = NULL;
free_irq_dbs:
gve_free_irq_db(priv);
free_cnt_array:
@@ -36,6 +36,10 @@
RTE_MBUF_F_TX_L4_MASK | \
RTE_MBUF_F_TX_TCP_SEG)
+#define GVE_TX_CKSUM_OFFLOAD_MASK_DQO ( \
+ GVE_TX_CKSUM_OFFLOAD_MASK | \
+ RTE_MBUF_F_TX_IP_CKSUM)
+
#define GVE_RTE_RSS_OFFLOAD_ALL ( \
RTE_ETH_RSS_IPV4 | \
RTE_ETH_RSS_NONFRAG_IPV4_TCP | \
@@ -295,6 +299,7 @@ struct gve_priv {
uint16_t stats_end_idx; /* end index of array of stats written by NIC */
struct gve_rss_config rss_config;
+ struct gve_ptype_lut *ptype_lut_dqo;
};
static inline bool
@@ -75,6 +75,40 @@ gve_rx_refill_dqo(struct gve_rx_queue *rxq)
rxq->bufq_tail = next_avail;
}
+static inline uint16_t
+gve_parse_csum_ol_flags(volatile struct gve_rx_compl_desc_dqo *rx_desc,
+ struct gve_priv *priv) {
+ uint64_t ol_flags = 0;
+ struct gve_ptype ptype =
+ priv->ptype_lut_dqo->ptypes[rx_desc->packet_type];
+
+ if(!rx_desc->l3_l4_processed)
+ return ol_flags;
+
+ if (ptype.l3_type == GVE_L3_TYPE_IPV4) {
+ if (rx_desc->csum_ip_err)
+ ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_BAD;
+ else
+ ol_flags |= RTE_MBUF_F_RX_IP_CKSUM_GOOD;
+ }
+
+ if (rx_desc->csum_l4_err) {
+ ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_BAD;
+ return ol_flags;
+ }
+ switch (ptype.l4_type) {
+ case GVE_L4_TYPE_TCP:
+ case GVE_L4_TYPE_UDP:
+ case GVE_L4_TYPE_ICMP:
+ case GVE_L4_TYPE_SCTP:
+ ol_flags |= RTE_MBUF_F_RX_L4_CKSUM_GOOD;
+ break;
+ default:
+ break;
+ }
+ return ol_flags;
+}
+
uint16_t
gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
{
@@ -125,8 +159,8 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
rxm->data_len = pkt_len;
rxm->port = rxq->port_id;
rxm->ol_flags = 0;
-
- rxm->ol_flags |= RTE_MBUF_F_RX_RSS_HASH;
+ rxm->ol_flags |= RTE_MBUF_F_RX_RSS_HASH |
+ gve_parse_csum_ol_flags(rx_desc, rxq->hw);
rxm->hash.rss = rte_be_to_cpu_32(rx_desc->hash);
rx_pkts[nb_rx++] = rxm;
@@ -138,7 +138,7 @@ gve_tx_burst_dqo(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
/* fill the last descriptor with End of Packet (EOP) bit */
txd->pkt.end_of_packet = 1;
- if (ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK)
+ if (ol_flags & GVE_TX_CKSUM_OFFLOAD_MASK_DQO)
txd->pkt.checksum_offload_enable = 1;
txq->nb_free -= nb_used;