[dpdk-stable] patch 'net/netvsc: fix underflow when Rx external mbuf' has been queued to stable release 19.11.4

luca.boccassi at gmail.com luca.boccassi at gmail.com
Fri Jul 24 13:59:31 CEST 2020


Hi,

FYI, your patch has been queued to stable release 19.11.4

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 07/26/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 1411ee42815cc1652c93172a1aec0d2adef3eb51 Mon Sep 17 00:00:00 2001
From: Long Li <longli at microsoft.com>
Date: Tue, 23 Jun 2020 18:11:45 -0700
Subject: [PATCH] net/netvsc: fix underflow when Rx external mbuf

[ upstream commit d43b8c710836db953fad1bb6449a827e19b5a87a ]

When rte_pktmbuf_attach_extbuf() is used, the driver should not decrease
the reference count in its callback function hn_rx_buf_free_cb, because
the reference count is already decreased by rte_pktmbuf. Doing it twice
may result in underflow and driver may never send an ack packet over
vmbus to host.

Also declares rxbuf_outstanding as atomic, because this value is shared
among all receive queues.

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  |  1 -
 drivers/net/netvsc/hn_rxtx.c | 32 ++++++++++++--------------------
 drivers/net/netvsc/hn_var.h  |  2 +-
 3 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/drivers/net/netvsc/hn_nvs.c b/drivers/net/netvsc/hn_nvs.c
index 477202b2a..f88854daf 100644
--- a/drivers/net/netvsc/hn_nvs.c
+++ b/drivers/net/netvsc/hn_nvs.c
@@ -99,7 +99,6 @@ __hn_nvs_execute(struct hn_data *hv,
 	/* Silently drop received packets while waiting for response */
 	if (hdr->type == NVS_TYPE_RNDIS) {
 		hn_nvs_ack_rxbuf(chan, xactid);
-		--hv->rxbuf_outstanding;
 		goto retry;
 	}
 
diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c
index 19f00a052..53681721d 100644
--- a/drivers/net/netvsc/hn_rxtx.c
+++ b/drivers/net/netvsc/hn_rxtx.c
@@ -488,24 +488,13 @@ next:
 	return 0;
 }
 
-/*
- * Ack the consumed RXBUF associated w/ this channel packet,
- * so that this RXBUF can be recycled by the hypervisor.
- */
-static void hn_rx_buf_release(struct hn_rx_bufinfo *rxb)
-{
-	struct rte_mbuf_ext_shared_info *shinfo = &rxb->shinfo;
-	struct hn_data *hv = rxb->hv;
-
-	if (rte_mbuf_ext_refcnt_update(shinfo, -1) == 0) {
-		hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
-		--hv->rxbuf_outstanding;
-	}
-}
-
 static void hn_rx_buf_free_cb(void *buf __rte_unused, void *opaque)
 {
-	hn_rx_buf_release(opaque);
+	struct hn_rx_bufinfo *rxb = opaque;
+	struct hn_data *hv = rxb->hv;
+
+	rte_atomic32_dec(&hv->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,
@@ -545,7 +534,8 @@ 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 &&
-	    hv->rxbuf_outstanding < hv->rxbuf_section_cnt / 2) {
+	    (uint32_t)rte_atomic32_read(&hv->rxbuf_outstanding) <
+			hv->rxbuf_section_cnt / 2) {
 		struct rte_mbuf_ext_shared_info *shinfo;
 		const void *rxbuf;
 		rte_iova_t iova;
@@ -559,8 +549,9 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
 		iova = rte_mem_virt2iova(rxbuf) + RTE_PTR_DIFF(data, rxbuf);
 		shinfo = &rxb->shinfo;
 
-		if (rte_mbuf_ext_refcnt_update(shinfo, 1) == 1)
-			++hv->rxbuf_outstanding;
+		/* 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_pktmbuf_attach_extbuf(m, data, iova,
 					  dlen + headroom, shinfo);
@@ -800,7 +791,8 @@ hn_nvs_handle_rxbuf(struct rte_eth_dev *dev,
 	}
 
 	/* Send ACK now if external mbuf not used */
-	hn_rx_buf_release(rxb);
+	if (rte_mbuf_ext_refcnt_update(&rxb->shinfo, -1) == 0)
+		hn_nvs_ack_rxbuf(rxb->chan, rxb->xactid);
 }
 
 /*
diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
index 4c1e6b8c3..b8e351dee 100644
--- a/drivers/net/netvsc/hn_var.h
+++ b/drivers/net/netvsc/hn_var.h
@@ -112,7 +112,7 @@ struct hn_data {
 	struct rte_mem_resource *rxbuf_res;	/* UIO resource for Rx */
 	struct hn_rx_bufinfo *rxbuf_info;
 	uint32_t	rxbuf_section_cnt;	/* # of Rx sections */
-	volatile uint32_t rxbuf_outstanding;
+	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-07-24 12:53:53.653156710 +0100
+++ 0133-net-netvsc-fix-underflow-when-Rx-external-mbuf.patch	2020-07-24 12:53:48.427009068 +0100
@@ -1,8 +1,10 @@
-From d43b8c710836db953fad1bb6449a827e19b5a87a Mon Sep 17 00:00:00 2001
+From 1411ee42815cc1652c93172a1aec0d2adef3eb51 Mon Sep 17 00:00:00 2001
 From: Long Li <longli at microsoft.com>
 Date: Tue, 23 Jun 2020 18:11:45 -0700
 Subject: [PATCH] net/netvsc: fix underflow when Rx external mbuf
 
+[ upstream commit d43b8c710836db953fad1bb6449a827e19b5a87a ]
+
 When rte_pktmbuf_attach_extbuf() is used, the driver should not decrease
 the reference count in its callback function hn_rx_buf_free_cb, because
 the reference count is already decreased by rte_pktmbuf. Doing it twice
@@ -13,7 +15,6 @@
 among all receive queues.
 
 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>
@@ -36,10 +37,10 @@
  	}
  
 diff --git a/drivers/net/netvsc/hn_rxtx.c b/drivers/net/netvsc/hn_rxtx.c
-index 6a52885d5..cc4ced37a 100644
+index 19f00a052..53681721d 100644
 --- a/drivers/net/netvsc/hn_rxtx.c
 +++ b/drivers/net/netvsc/hn_rxtx.c
-@@ -519,24 +519,13 @@ next:
+@@ -488,24 +488,13 @@ next:
  	return 0;
  }
  
@@ -69,7 +70,7 @@
  }
  
  static struct hn_rx_bufinfo *hn_rx_buf_init(const struct hn_rx_queue *rxq,
-@@ -576,7 +565,8 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
+@@ -545,7 +534,8 @@ 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 &&
@@ -79,7 +80,7 @@
  		struct rte_mbuf_ext_shared_info *shinfo;
  		const void *rxbuf;
  		rte_iova_t iova;
-@@ -590,8 +580,9 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
+@@ -559,8 +549,9 @@ static void hn_rxpkt(struct hn_rx_queue *rxq, struct hn_rx_bufinfo *rxb,
  		iova = rte_mem_virt2iova(rxbuf) + RTE_PTR_DIFF(data, rxbuf);
  		shinfo = &rxb->shinfo;
  
@@ -91,7 +92,7 @@
  
  		rte_pktmbuf_attach_extbuf(m, data, iova,
  					  dlen + headroom, shinfo);
-@@ -832,7 +823,8 @@ hn_nvs_handle_rxbuf(struct rte_eth_dev *dev,
+@@ -800,7 +791,8 @@ hn_nvs_handle_rxbuf(struct rte_eth_dev *dev,
  	}
  
  	/* Send ACK now if external mbuf not used */
@@ -102,10 +103,10 @@
  
  /*
 diff --git a/drivers/net/netvsc/hn_var.h b/drivers/net/netvsc/hn_var.h
-index 881832d85..7cb7713e9 100644
+index 4c1e6b8c3..b8e351dee 100644
 --- a/drivers/net/netvsc/hn_var.h
 +++ b/drivers/net/netvsc/hn_var.h
-@@ -113,7 +113,7 @@ struct hn_data {
+@@ -112,7 +112,7 @@ struct hn_data {
  	struct rte_mem_resource *rxbuf_res;	/* UIO resource for Rx */
  	struct hn_rx_bufinfo *rxbuf_info;
  	uint32_t	rxbuf_section_cnt;	/* # of Rx sections */


More information about the stable mailing list