[dpdk-dev,36/38] net/dpaa: add support for checksum offload

Message ID 1497591668-3320-37-git-send-email-shreyansh.jain@nxp.com (mailing list archive)
State Superseded, archived
Delegated to: Thomas Monjalon
Headers

Checks

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

Commit Message

Shreyansh Jain June 16, 2017, 5:41 a.m. UTC
  Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
---
 doc/guides/nics/features/dpaa.ini |  2 +
 drivers/net/dpaa/dpaa_ethdev.c    |  4 ++
 drivers/net/dpaa/dpaa_rxtx.c      | 88 +++++++++++++++++++++++++++++++++++++++
 drivers/net/dpaa/dpaa_rxtx.h      | 19 +++++++++
 4 files changed, 113 insertions(+)
  

Comments

Ferruh Yigit June 28, 2017, 3:50 p.m. UTC | #1
On 6/16/2017 6:41 AM, Shreyansh Jain wrote:
> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>

<...>

> @@ -363,6 +439,18 @@ dpaa_eth_queue_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
>  						}
>  						rte_pktmbuf_free(mbuf);
>  					}
> +					if (mbuf->ol_flags & DPAA_TX_CKSUM_OFFLOAD_MASK) {
> +						if (mbuf->data_off < DEFAULT_TX_ICEOF +
> +							sizeof(struct dpaa_eth_parse_results_t)) {
> +							PMD_DRV_LOG(DEBUG, "Checksum offload Err: "
> +								"Not enough Headroom "
> +								"space for correct Checksum offload."
> +								"So Calculating checksum in Software.");
> +							dpaa_checksum(mbuf);
> +						} else
> +							dpaa_checksum_offload(mbuf, &fd_arr[loop],
> +								mbuf->buf_addr);
> +					}

There is a tx_pkt_prepare() dev_ops.
Does it make sense to move this calculations to that function?

>  				} else {
>  					PMD_DRV_LOG(DEBUG, "Number of Segments not supported");
>  					/* Set frames_to_send & nb_bufs so that

<...>
  
Shreyansh Jain July 4, 2017, 2:48 p.m. UTC | #2
Hello Ferruh,

On Wednesday 28 June 2017 09:20 PM, Ferruh Yigit wrote:
> On 6/16/2017 6:41 AM, Shreyansh Jain wrote:
>> Signed-off-by: Hemant Agrawal <hemant.agrawal@nxp.com>
>> Signed-off-by: Shreyansh Jain <shreyansh.jain@nxp.com>
> 
> <...>
> 
>> @@ -363,6 +439,18 @@ dpaa_eth_queue_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
>>  						}
>>  						rte_pktmbuf_free(mbuf);
>>  					}
>> +					if (mbuf->ol_flags & DPAA_TX_CKSUM_OFFLOAD_MASK) {
>> +						if (mbuf->data_off < DEFAULT_TX_ICEOF +
>> +							sizeof(struct dpaa_eth_parse_results_t)) {
>> +							PMD_DRV_LOG(DEBUG, "Checksum offload Err: "
>> +								"Not enough Headroom "
>> +								"space for correct Checksum offload."
>> +								"So Calculating checksum in Software.");
>> +							dpaa_checksum(mbuf);
>> +						} else
>> +							dpaa_checksum_offload(mbuf, &fd_arr[loop],
>> +								mbuf->buf_addr);
>> +					}
> 
> There is a tx_pkt_prepare() dev_ops.
> Does it make sense to move this calculations to that function?

I did have a look at this before sending the v2.
In case of DPAA driver, it is not possible to segregate the preparation phase from transmission phase.
Further, there are still applications which don't call the prep function - in those cases, the I/O wouldn't happen.
And, making an internal call to prep (on basis of some (!prep) checks), is performance impact.

> 
>>  				} else {
>>  					PMD_DRV_LOG(DEBUG, "Number of Segments not supported");
>>  					/* Set frames_to_send & nb_bufs so that
> 
> <...>
> 

-
Shreyansh
  

Patch

diff --git a/doc/guides/nics/features/dpaa.ini b/doc/guides/nics/features/dpaa.ini
index 2e19664..c8e3561 100644
--- a/doc/guides/nics/features/dpaa.ini
+++ b/doc/guides/nics/features/dpaa.ini
@@ -14,6 +14,8 @@  Allmulticast mode    = Y
 Unicast MAC filter   = Y
 RSS hash             = Y
 Flow control         = Y
+L3 checksum offload  = Y
+L4 checksum offload  = Y
 Packet type parsing  = Y
 Basic stats          = Y
 ARMv8                = Y
diff --git a/drivers/net/dpaa/dpaa_ethdev.c b/drivers/net/dpaa/dpaa_ethdev.c
index 4d2bae0..da14a1c 100644
--- a/drivers/net/dpaa/dpaa_ethdev.c
+++ b/drivers/net/dpaa/dpaa_ethdev.c
@@ -184,6 +184,10 @@  static void dpaa_eth_dev_info(struct rte_eth_dev *dev,
 		(DEV_RX_OFFLOAD_IPV4_CKSUM |
 		DEV_RX_OFFLOAD_UDP_CKSUM  |
 		DEV_RX_OFFLOAD_TCP_CKSUM);
+	dev_info->tx_offload_capa =
+		(DEV_TX_OFFLOAD_IPV4_CKSUM  |
+		DEV_TX_OFFLOAD_UDP_CKSUM   |
+		DEV_TX_OFFLOAD_TCP_CKSUM);
 }
 
 static int dpaa_eth_link_update(struct rte_eth_dev *dev,
diff --git a/drivers/net/dpaa/dpaa_rxtx.c b/drivers/net/dpaa/dpaa_rxtx.c
index e2db3cc..eef0d49 100644
--- a/drivers/net/dpaa/dpaa_rxtx.c
+++ b/drivers/net/dpaa/dpaa_rxtx.c
@@ -195,6 +195,82 @@  static inline void dpaa_eth_packet_info(struct rte_mbuf *m,
 		m->ol_flags |= PKT_RX_VLAN_PKT;
 }
 
+static inline void dpaa_checksum(struct rte_mbuf *mbuf)
+{
+	struct ether_hdr *eth_hdr = rte_pktmbuf_mtod(mbuf, struct ether_hdr *);
+	char *l3_hdr = (char *)eth_hdr + mbuf->l2_len;
+	struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)l3_hdr;
+	struct ipv6_hdr *ipv6_hdr = (struct ipv6_hdr *)l3_hdr;
+
+	PMD_TX_LOG(DEBUG, "Calculating checksum for mbuf: %p", mbuf);
+
+	if (((mbuf->packet_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV4) ||
+	    ((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+	    RTE_PTYPE_L3_IPV4_EXT)) {
+		ipv4_hdr = (struct ipv4_hdr *)l3_hdr;
+		ipv4_hdr->hdr_checksum = 0;
+		ipv4_hdr->hdr_checksum = rte_ipv4_cksum(ipv4_hdr);
+	} else if (((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+		   RTE_PTYPE_L3_IPV6) ||
+		   ((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+		   RTE_PTYPE_L3_IPV6_EXT))
+		ipv6_hdr = (struct ipv6_hdr *)l3_hdr;
+
+	if ((mbuf->packet_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) {
+		struct tcp_hdr *tcp_hdr = (struct tcp_hdr *)(l3_hdr +
+					  mbuf->l3_len);
+		tcp_hdr->cksum = 0;
+		if (eth_hdr->ether_type == htons(ETHER_TYPE_IPv4))
+			tcp_hdr->cksum = rte_ipv4_udptcp_cksum(ipv4_hdr,
+							       tcp_hdr);
+		else /* assume ethertype == ETHER_TYPE_IPv6 */
+			tcp_hdr->cksum = rte_ipv6_udptcp_cksum(ipv6_hdr,
+							       tcp_hdr);
+	} else if ((mbuf->packet_type & RTE_PTYPE_L4_MASK) ==
+		   RTE_PTYPE_L4_UDP) {
+		struct udp_hdr *udp_hdr = (struct udp_hdr *)(l3_hdr +
+							     mbuf->l3_len);
+		udp_hdr->dgram_cksum = 0;
+		if (eth_hdr->ether_type == htons(ETHER_TYPE_IPv4))
+			udp_hdr->dgram_cksum = rte_ipv4_udptcp_cksum(ipv4_hdr,
+								     udp_hdr);
+		else /* assume ethertype == ETHER_TYPE_IPv6 */
+			udp_hdr->dgram_cksum = rte_ipv6_udptcp_cksum(ipv6_hdr,
+								     udp_hdr);
+	}
+}
+
+static inline void dpaa_checksum_offload(struct rte_mbuf *mbuf,
+					 struct qm_fd *fd, char *prs_buf)
+{
+	struct dpaa_eth_parse_results_t *prs;
+
+	PMD_TX_LOG(DEBUG, " Offloading checksum for mbuf: %p", mbuf);
+
+	prs = GET_TX_PRS(prs_buf);
+	prs->l3r = 0;
+	prs->l4r = 0;
+	if (((mbuf->packet_type & RTE_PTYPE_L3_MASK) == RTE_PTYPE_L3_IPV4) ||
+	   ((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+	   RTE_PTYPE_L3_IPV4_EXT))
+		prs->l3r = DPAA_L3_PARSE_RESULT_IPV4;
+	else if (((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+		   RTE_PTYPE_L3_IPV6) ||
+		 ((mbuf->packet_type & RTE_PTYPE_L3_MASK) ==
+		RTE_PTYPE_L3_IPV6_EXT))
+		prs->l3r = DPAA_L3_PARSE_RESULT_IPV6;
+
+	if ((mbuf->packet_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP)
+		prs->l4r = DPAA_L4_PARSE_RESULT_TCP;
+	else if ((mbuf->packet_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP)
+		prs->l4r = DPAA_L4_PARSE_RESULT_UDP;
+
+	prs->ip_off[0] = mbuf->l2_len;
+	prs->l4_off = mbuf->l3_len + mbuf->l2_len;
+	/* Enable L3 (and L4, if TCP or UDP) HW checksum*/
+	fd->cmd = DPAA_FD_CMD_RPD | DPAA_FD_CMD_DTC;
+}
+
 static inline struct rte_mbuf *dpaa_eth_fd_to_mbuf(struct qm_fd *fd,
 							uint32_t ifid)
 {
@@ -363,6 +439,18 @@  dpaa_eth_queue_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs)
 						}
 						rte_pktmbuf_free(mbuf);
 					}
+					if (mbuf->ol_flags & DPAA_TX_CKSUM_OFFLOAD_MASK) {
+						if (mbuf->data_off < DEFAULT_TX_ICEOF +
+							sizeof(struct dpaa_eth_parse_results_t)) {
+							PMD_DRV_LOG(DEBUG, "Checksum offload Err: "
+								"Not enough Headroom "
+								"space for correct Checksum offload."
+								"So Calculating checksum in Software.");
+							dpaa_checksum(mbuf);
+						} else
+							dpaa_checksum_offload(mbuf, &fd_arr[loop],
+								mbuf->buf_addr);
+					}
 				} else {
 					PMD_DRV_LOG(DEBUG, "Number of Segments not supported");
 					/* Set frames_to_send & nb_bufs so that
diff --git a/drivers/net/dpaa/dpaa_rxtx.h b/drivers/net/dpaa/dpaa_rxtx.h
index f688934..b1c292b 100644
--- a/drivers/net/dpaa/dpaa_rxtx.h
+++ b/drivers/net/dpaa/dpaa_rxtx.h
@@ -41,6 +41,22 @@ 
 
 /* IC offsets from buffer header address */
 #define DEFAULT_RX_ICEOF	16
+#define DEFAULT_TX_ICEOF	16
+
+/*
+ * Values for the L3R field of the FM Parse Results
+ */
+/* L3 Type field: First IP Present IPv4 */
+#define DPAA_L3_PARSE_RESULT_IPV4 0x80
+/* L3 Type field: First IP Present IPv6 */
+#define DPAA_L3_PARSE_RESULT_IPV6	0x40
+/* Values for the L4R field of the FM Parse Results
+ * See $8.8.4.7.20 - L4 HXS - L4 Results from DPAA-Rev2 Reference Manual.
+ */
+/* L4 Type field: UDP */
+#define DPAA_L4_PARSE_RESULT_UDP	0x40
+/* L4 Type field: TCP */
+#define DPAA_L4_PARSE_RESULT_TCP	0x20
 
 #define DPAA_MAX_DEQUEUE_NUM_FRAMES    63
 	/** <Maximum number of frames to be dequeued in a single rx call*/
@@ -225,6 +241,9 @@  struct annotations_t {
 #define GET_RX_PRS(_buf) \
 	(struct dpaa_eth_parse_results_t *)((uint8_t *)_buf + DEFAULT_RX_ICEOF)
 
+#define GET_TX_PRS(_buf) \
+	(struct dpaa_eth_parse_results_t *)((uint8_t *)_buf + DEFAULT_TX_ICEOF)
+
 uint16_t dpaa_eth_queue_rx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs);
 
 uint16_t dpaa_eth_queue_tx(void *q, struct rte_mbuf **bufs, uint16_t nb_bufs);