[v4,12/13] net/enetc: enable Rx checksum offload validation

Message ID 20190412122840.1908-13-g.singh@nxp.com
State Accepted, archived
Delegated to: Ferruh Yigit
Headers show
Series
  • ENETC PMD basic features and bug fixes
Related show

Checks

Context Check Description
ci/Intel-compilation success Compilation OK
ci/checkpatch warning coding style issues

Commit Message

Gagandeep Singh April 12, 2019, 12:29 p.m.
Checksum Validation on Rx is supported.

Signed-off-by: Gagandeep Singh <g.singh@nxp.com>
---
 doc/guides/nics/features/enetc.ini |   2 +
 drivers/net/enetc/base/enetc_hw.h  |   5 ++
 drivers/net/enetc/enetc_ethdev.c   |  15 +++-
 drivers/net/enetc/enetc_rxtx.c     | 107 +++++++++++++++++++++++++----
 4 files changed, 115 insertions(+), 14 deletions(-)

Patch

diff --git a/doc/guides/nics/features/enetc.ini b/doc/guides/nics/features/enetc.ini
index 101dc0a69..39a520172 100644
--- a/doc/guides/nics/features/enetc.ini
+++ b/doc/guides/nics/features/enetc.ini
@@ -13,6 +13,8 @@  MTU update           = Y
 Jumbo frame          = Y
 Queue start/stop     = Y
 CRC offload          = Y
+L3 checksum offload  = P
+L4 checksum offload  = P
 Linux VFIO           = Y
 ARMv8                = Y
 Usage doc            = Y
diff --git a/drivers/net/enetc/base/enetc_hw.h b/drivers/net/enetc/base/enetc_hw.h
index 261ad157a..ff2bda592 100644
--- a/drivers/net/enetc/base/enetc_hw.h
+++ b/drivers/net/enetc/base/enetc_hw.h
@@ -99,6 +99,10 @@  enum enetc_bdr_type {TX, RX};
 #define ENETC_PM0_RX_EN			BIT(1)
 #define ENETC_PM0_CRC			BIT(6)
 
+#define ENETC_PAR_PORT_CFG		0x03050
+#define L3_CKSUM			BIT(0)
+#define L4_CKSUM			BIT(1)
+
 #define ENETC_PM0_MAXFRM		0x08014
 #define ENETC_SET_TX_MTU(val)		((val) << 16)
 #define ENETC_SET_MAXFRM(val)		((val) & 0xffff)
@@ -182,6 +186,7 @@  enum enetc_bdr_type {TX, RX};
 #define ENETC_TXBD_FLAGS_F		BIT(15)
 
 /* ENETC Parsed values (Little Endian) */
+#define ENETC_PARSE_ERROR		0x8000
 #define ENETC_PKT_TYPE_ETHER            0x0060
 #define ENETC_PKT_TYPE_IPV4             0x0000
 #define ENETC_PKT_TYPE_IPV6             0x0020
diff --git a/drivers/net/enetc/enetc_ethdev.c b/drivers/net/enetc/enetc_ethdev.c
index ffae8ae25..362e0740c 100644
--- a/drivers/net/enetc/enetc_ethdev.c
+++ b/drivers/net/enetc/enetc_ethdev.c
@@ -163,7 +163,10 @@  enetc_dev_infos_get(struct rte_eth_dev *dev __rte_unused,
 	dev_info->max_tx_queues = MAX_TX_RINGS;
 	dev_info->max_rx_pktlen = ENETC_MAC_MAXFRM_SIZE;
 	dev_info->rx_offload_capa =
-		(DEV_RX_OFFLOAD_KEEP_CRC |
+		(DEV_RX_OFFLOAD_IPV4_CKSUM |
+		 DEV_RX_OFFLOAD_UDP_CKSUM |
+		 DEV_RX_OFFLOAD_TCP_CKSUM |
+		 DEV_RX_OFFLOAD_KEEP_CRC |
 		 DEV_RX_OFFLOAD_JUMBO_FRAME);
 }
 
@@ -636,6 +639,7 @@  enetc_dev_configure(struct rte_eth_dev *dev)
 	struct enetc_hw *enetc_hw = &hw->hw;
 	struct rte_eth_conf *eth_conf = &dev->data->dev_conf;
 	uint64_t rx_offloads = eth_conf->rxmode.offloads;
+	uint32_t checksum = L3_CKSUM | L4_CKSUM;
 
 	PMD_INIT_FUNC_TRACE();
 
@@ -661,6 +665,15 @@  enetc_dev_configure(struct rte_eth_dev *dev)
 		enetc_port_wr(enetc_hw, ENETC_PM0_CMD_CFG, config);
 	}
 
+	if (rx_offloads & DEV_RX_OFFLOAD_IPV4_CKSUM)
+		checksum &= ~L3_CKSUM;
+
+	if (rx_offloads & (DEV_RX_OFFLOAD_UDP_CKSUM | DEV_RX_OFFLOAD_TCP_CKSUM))
+		checksum &= ~L4_CKSUM;
+
+	enetc_port_wr(enetc_hw, ENETC_PAR_PORT_CFG, checksum);
+
+
 	return 0;
 }
 
diff --git a/drivers/net/enetc/enetc_rxtx.c b/drivers/net/enetc/enetc_rxtx.c
index 4a758d25a..0ce7dbee7 100644
--- a/drivers/net/enetc/enetc_rxtx.c
+++ b/drivers/net/enetc/enetc_rxtx.c
@@ -115,69 +115,150 @@  enetc_refill_rx_ring(struct enetc_bdr *rx_ring, const int buff_cnt)
 	return j;
 }
 
+static inline void enetc_slow_parsing(struct rte_mbuf *m,
+				     uint64_t parse_results)
+{
+	m->ol_flags &= ~(PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD);
+
+	switch (parse_results) {
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4;
+		m->ol_flags |= PKT_RX_IP_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6;
+		m->ol_flags |= PKT_RX_IP_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_TCP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4 |
+				 RTE_PTYPE_L4_TCP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_TCP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6 |
+				 RTE_PTYPE_L4_TCP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_UDP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4 |
+				 RTE_PTYPE_L4_UDP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_UDP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6 |
+				 RTE_PTYPE_L4_UDP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_SCTP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4 |
+				 RTE_PTYPE_L4_SCTP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_SCTP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6 |
+				 RTE_PTYPE_L4_SCTP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV4_ICMP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV4 |
+				 RTE_PTYPE_L4_ICMP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	case ENETC_PARSE_ERROR | ENETC_PKT_TYPE_IPV6_ICMP:
+		m->packet_type = RTE_PTYPE_L2_ETHER |
+				 RTE_PTYPE_L3_IPV6 |
+				 RTE_PTYPE_L4_ICMP;
+		m->ol_flags |= PKT_RX_IP_CKSUM_GOOD |
+			       PKT_RX_L4_CKSUM_BAD;
+		return;
+	/* More switch cases can be added */
+	default:
+		m->packet_type = RTE_PTYPE_UNKNOWN;
+		m->ol_flags |= PKT_RX_IP_CKSUM_UNKNOWN |
+			       PKT_RX_L4_CKSUM_UNKNOWN;
+	}
+}
+
 
 static inline void __attribute__((hot))
 enetc_dev_rx_parse(struct rte_mbuf *m, uint16_t parse_results)
 {
 	ENETC_PMD_DP_DEBUG("parse summary = 0x%x   ", parse_results);
+	m->ol_flags |= PKT_RX_IP_CKSUM_GOOD | PKT_RX_L4_CKSUM_GOOD;
 
-	m->packet_type = RTE_PTYPE_UNKNOWN;
 	switch (parse_results) {
 	case ENETC_PKT_TYPE_ETHER:
 		m->packet_type = RTE_PTYPE_L2_ETHER;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV4:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV4;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV6:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV6;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV4_TCP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV4 |
 				 RTE_PTYPE_L4_TCP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV6_TCP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV6 |
 				 RTE_PTYPE_L4_TCP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV4_UDP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV4 |
 				 RTE_PTYPE_L4_UDP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV6_UDP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV6 |
 				 RTE_PTYPE_L4_UDP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV4_SCTP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV4 |
 				 RTE_PTYPE_L4_SCTP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV6_SCTP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV6 |
 				 RTE_PTYPE_L4_SCTP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV4_ICMP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV4 |
 				 RTE_PTYPE_L4_ICMP;
-		break;
+		return;
 	case ENETC_PKT_TYPE_IPV6_ICMP:
 		m->packet_type = RTE_PTYPE_L2_ETHER |
 				 RTE_PTYPE_L3_IPV6 |
 				 RTE_PTYPE_L4_ICMP;
-		break;
+		return;
 	/* More switch cases can be added */
 	default:
-		m->packet_type = RTE_PTYPE_UNKNOWN;
+		enetc_slow_parsing(m, parse_results);
 	}
+
 }
 
 static int