[dpdk-stable] patch 'net/netvsc: fix multiple channel Rx' has been queued to stable release 19.11.6

luca.boccassi at gmail.com luca.boccassi at gmail.com
Wed Oct 28 11:42:43 CET 2020


Hi,

FYI, your patch has been queued to stable release 19.11.6

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 10/30/20. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Thanks.

Luca Boccassi

---
>From d55a06baec093c15e47c64f0990f42100ecda104 Mon Sep 17 00:00:00 2001
From: Long Li <longli at microsoft.com>
Date: Mon, 10 Aug 2020 19:33:11 -0700
Subject: [PATCH] net/netvsc: fix multiple channel Rx

[ upstream commit ac837bdd22400b220d60336f22c18091a92a40c9 ]

netvsc uses rxbuf_info buffer to track received packets attached via
rte_pktmbuf_attach_extbuf() and ack the host based on usage count. It
uses the transaction_id in the VMBus packet to locate where to use
memory in the rxbuf_info.

This is not correct in multiple channel setup, as different channels may
return identical transaction_ids at a time, and may corrupt the
rxbuf_info buffer.

Fix this by defining rxbuf_info for each queue.

Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device")

Signed-off-by: Long Li <longli at microsoft.com>
Acked-by: Stephen Hemminger <stephen at networkplumber.org>
---
 drivers/net/netvsc/hn_nvs.c  | 13 +++++++++----
 drivers/net/netvsc/hn_rxtx.c | 33 ++++++++++++++++++++++++++-------
 drivers/net/netvsc/hn_var.h  |  6 +++---
 3 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c
index f88854dafc..eeb82ab9ee 100644
--- a/drivers/net/netvsc/hn_nvs.c
+++ b/drivers/net/netvsc/hn_nvs.c
@@ -223,9 +223,15 @@ hn_nvs_conn_rxbuf(struct hn_data *hv)
 		    resp.nvs_sect[0].slotcnt);
 	hv->rxbuf_section_cnt = resp.nvs_sect[0].slotcnt;
 
-	hv->rxbuf_info = rte_calloc("HN_RXBUF_INFO", hv->rxbuf_section_cnt,
-				    sizeof(*hv->rxbuf_info), RTE_CACHE_LINE_SIZE);
-	if (!hv->rxbuf_info) {
+	/*
+	 * Pimary queue's rxbuf_info is not allocated at creation time.
+	 * Now we can allocate it after we figure out the slotcnt.
+	 */
+	hv->primary->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
+			hv->rxbuf_section_cnt,
+			sizeof(*hv->primary->rxbuf_info),
+			RTE_CACHE_LINE_SIZE);
+	if (!hv->primary->rxbuf_info) {
 		PMD_DRV_LOG(ERR,
 			    "could not allocate rxbuf info");
 		return -ENOMEM;
@@ -255,7 +261,6 @@ hn_nvs_disconn_rxbuf(struct hn_data *hv)
 			    error);
 	}
 
-	rte_free(hv->rxbuf_info);
 	/*
 	 * Linger long enough for NVS to disconnect RXBUF.
 	 */
diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c
index d6e518c88e..7fb8852797 100644
--- a/drivers/net/netvsc/hn_rxtx.c
+++ b/drivers/net/netvsc/hn_rxtx.c
@@ -493,21 +493,21 @@ next:
 static void hn_rx_buf_free_cb(void *buf __rte_unused, void *opaque)
 {
 	struct hn_rx_bufinfo *rxb = opaque;
-	struct hn_data *hv = rxb->hv;
+	struct hn_rx_queue *rxq = rxb->rxq;
 
-	rte_atomic32_dec(&hv->rxbuf_outstanding);
+	rte_atomic32_dec(&rxq->rxbuf_outstanding);
 	hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
 }
 
-static struct hn_rx_bufinfo *hn_rx_buf_init(const struct hn_rx_queue *rxq,
+static struct hn_rx_bufinfo *hn_rx_buf_init(struct hn_rx_queue *rxq,
 					    const struct vmbus_chanpkt_rxbuf *pkt)
 {
 	struct hn_rx_bufinfo *rxb;
 
-	rxb = rxq->hv->rxbuf_info + pkt->hdr.xactid;
+	rxb = rxq->rxbuf_info + pkt->hdr.xactid;
 	rxb->chan = rxq->chan;
 	rxb->xactid = pkt->hdr.xactid;
-	rxb->hv = rxq->hv;
+	rxb->rxq = rxq;
 
 	rxb->shinfo.free_cb = hn_rx_buf_free_cb;
 	rxb->shinfo.fcb_opaque = rxb;
@@ -536,7 +536,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
 	 * some space available in receive area for later packets.
 	 */
 	if (dlen >= HN_RXCOPY_THRESHOLD &&
-	    (uint32_t)rte_atomic32_read(&hv->rxbuf_outstanding) <
+	    (uint32_t)rte_atomic32_read(&rxq->rxbuf_outstanding) <
 			hv->rxbuf_section_cnt / 2) {
 		struct rte_mbuf_ext_shared_info *shinfo;
 		const void *rxbuf;
@@ -553,7 +553,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
 
 		/* shinfo is already set to 1 by the caller */
 		if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 2)
-			rte_atomic32_inc(&hv->rxbuf_outstanding);
+			rte_atomic32_inc(&rxq->rxbuf_outstanding);
 
 		rte_pktmbuf_attach_extbuf(m, data, iova,
 					  dlen + headroom, shinfo);
@@ -850,6 +850,23 @@ struct hn_rx_queue *hn_rx_queue_alloc(struct hn_data *hv,
 		return NULL;
 	}
 
+	/* setup rxbuf_info for non-primary queue */
+	if (queue_id) {
+		rxq->rxbuf_info = rte_calloc("HN_RXBUF_INFO",
+					hv->rxbuf_section_cnt,
+					sizeof(*rxq->rxbuf_info),
+					RTE_CACHE_LINE_SIZE);
+
+		if (!rxq->rxbuf_info) {
+			PMD_DRV_LOG(ERR,
+				"Could not allocate rxbuf info for queue %d\n",
+				queue_id);
+			rte_free(rxq->event_buf);
+			rte_free(rxq);
+			return NULL;
+		}
+	}
+
 	return rxq;
 }
 
@@ -904,6 +921,7 @@ hn_dev_rx_queue_setup(struct rte_eth_dev *dev,
 
 fail:
 	rte_ring_free(rxq->rx_ring);
+	rte_free(rxq->rxbuf_info);
 	rte_free(rxq->event_buf);
 	rte_free(rxq);
 	return error;
@@ -926,6 +944,7 @@ hn_rx_queue_free(struct hn_rx_queue *rxq, bool keep_primary)
 	if (keep_primary && rxq == rxq->hv->primary)
 		return;
 
+	rte_free(rxq->rxbuf_info);
 	rte_free(rxq->event_buf);
 	rte_free(rxq);
 }
diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
index b8e351deeb..a4d47abca3 100644
--- a/drivers/net/netvsc/hn_var.h
+++ b/drivers/net/netvsc/hn_var.h
@@ -82,13 +82,15 @@ struct hn_rx_queue {
 	struct hn_stats stats;
 
 	void *event_buf;
+	struct hn_rx_bufinfo *rxbuf_info;
+	rte_atomic32_t  rxbuf_outstanding;
 };
 
 
 /* multi-packet data from host */
 struct hn_rx_bufinfo {
 	struct vmbus_channel *chan;
-	struct hn_data *hv;
+	struct hn_rx_queue *rxq;
 	uint64_t	xactid;
 	struct rte_mbuf_ext_shared_info shinfo;
 } __rte_cache_aligned;
@@ -110,9 +112,7 @@ struct hn_data {
 	uint32_t	link_speed;
 
 	struct rte_mem_resource *rxbuf_res;	/* UIO resource for Rx */
-	struct hn_rx_bufinfo *rxbuf_info;
 	uint32_t	rxbuf_section_cnt;	/* # of Rx sections */
-	rte_atomic32_t	rxbuf_outstanding;
 	uint16_t	max_queues;		/* Max available queues */
 	uint16_t	num_queues;
 	uint64_t	rss_offloads;
-- 
2.20.1

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2020-10-28 10:35:11.918542458 +0000
+++ 0004-net-netvsc-fix-multiple-channel-Rx.patch	2020-10-28 10:35:11.384828257 +0000
@@ -1,8 +1,10 @@
-From ac837bdd22400b220d60336f22c18091a92a40c9 Mon Sep 17 00:00:00 2001
+From d55a06baec093c15e47c64f0990f42100ecda104 Mon Sep 17 00:00:00 2001
 From: Long Li <longli at microsoft.com>
 Date: Mon, 10 Aug 2020 19:33:11 -0700
 Subject: [PATCH] net/netvsc: fix multiple channel Rx
 
+[ upstream commit ac837bdd22400b220d60336f22c18091a92a40c9 ]
+
 netvsc uses rxbuf_info buffer to track received packets attached via
 rte_pktmbuf_attach_extbuf() and ack the host based on usage count. It
 uses the transaction_id in the VMBus packet to locate where to use
@@ -15,7 +17,6 @@
 Fix this by defining rxbuf_info for each queue.
 
 Fixes: 4e9c73e96e83 ("net/netvsc: add Hyper-V network device")
-Cc: stable at dpdk.org
 
 Signed-off-by: Long Li <longli at microsoft.com>
 Acked-by: Stephen Hemminger <stephen at networkplumber.org>
@@ -57,10 +58,10 @@
  	 * Linger long enough for NVS to disconnect RXBUF.
  	 */
 diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c
-index 87b1184bc1..c8c4ee10c8 100644
+index d6e518c88e..7fb8852797 100644
 --- a/drivers/net/netvsc/hn_rxtx.c
 +++ b/drivers/net/netvsc/hn_rxtx.c
-@@ -524,21 +524,21 @@ next:
+@@ -493,21 +493,21 @@ next:
  static void hn_rx_buf_free_cb(void *buf __rte_unused, void *opaque)
  {
  	struct hn_rx_bufinfo *rxb = opaque;
@@ -87,7 +88,7 @@
  
  	rxb->shinfo.free_cb = hn_rx_buf_free_cb;
  	rxb->shinfo.fcb_opaque = rxb;
-@@ -568,7 +568,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
+@@ -536,7 +536,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
  	 * some space available in receive area for later packets.
  	 */
  	if (dlen >= HN_RXCOPY_THRESHOLD &&
@@ -96,7 +97,7 @@
  			hv->rxbuf_section_cnt / 2) {
  		struct rte_mbuf_ext_shared_info *shinfo;
  		const void *rxbuf;
-@@ -585,7 +585,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
+@@ -553,7 +553,7 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
  
  		/* shinfo is already set to 1 by the caller */
  		if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 2)
@@ -105,7 +106,7 @@
  
  		rte_pktmbuf_attach_extbuf(m, data, iova,
  					  dlen + headroom, shinfo);
-@@ -888,6 +888,23 @@ struct hn_rx_queue *hn_rx_queue_alloc(struct hn_data *hv,
+@@ -850,6 +850,23 @@ struct hn_rx_queue *hn_rx_queue_alloc(struct hn_data *hv,
  		return NULL;
  	}
  
@@ -129,7 +130,7 @@
  	return rxq;
  }
  
-@@ -953,6 +970,7 @@ hn_dev_rx_queue_setup(struct rte_eth_dev *dev,
+@@ -904,6 +921,7 @@ hn_dev_rx_queue_setup(struct rte_eth_dev *dev,
  
  fail:
  	rte_ring_free(rxq->rx_ring);
@@ -137,7 +138,7 @@
  	rte_free(rxq->event_buf);
  	rte_free(rxq);
  	return error;
-@@ -975,6 +993,7 @@ hn_rx_queue_free(struct hn_rx_queue *rxq, bool keep_primary)
+@@ -926,6 +944,7 @@ hn_rx_queue_free(struct hn_rx_queue *rxq, bool keep_primary)
  	if (keep_primary && rxq == rxq->hv->primary)
  		return;
  
@@ -146,10 +147,10 @@
  	rte_free(rxq);
  }
 diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
-index 7cb7713e93..4b63f87607 100644
+index b8e351deeb..a4d47abca3 100644
 --- a/drivers/net/netvsc/hn_var.h
 +++ b/drivers/net/netvsc/hn_var.h
-@@ -83,13 +83,15 @@ struct hn_rx_queue {
+@@ -82,13 +82,15 @@ struct hn_rx_queue {
  	struct hn_stats stats;
  
  	void *event_buf;
@@ -166,7 +167,7 @@
  	uint64_t	xactid;
  	struct rte_mbuf_ext_shared_info shinfo;
  } __rte_cache_aligned;
-@@ -111,9 +113,7 @@ struct hn_data {
+@@ -110,9 +112,7 @@ struct hn_data {
  	uint32_t	link_speed;
  
  	struct rte_mem_resource *rxbuf_res;	/* UIO resource for Rx */


More information about the stable mailing list