DPDK-dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] graph: fix xstats of cloned nodes
From: Robin Jarry @ 2026-07-08  9:21 UTC (permalink / raw)
  To: Andrey Yudin, Jerin Jacob, Kiran Kumar K, Nithin Dabilpuram,
	Zhirun Yan, Pavan Nikhilesh
  Cc: dev, stable
In-Reply-To: <20260708081420.1100574-1-Andrey.Yudin@infotecs.ru>

Andrey Yudin, Jul 08, 2026 at 10:14:
> When cloning a node with xstats enabled, xstat_desc entries are copied
> into the rte_node_register structure, but the nb_xstats field is not.
>
> As a result, the cloned node reports zero available xstats,
> making xstats unusable.
>
> Copy the nb_xstats field when cloning the node so that cloned nodes
> preserve the xstats configuration of the original node.
>
> Fixes: 070db97e017b ("graph: support node xstats")
> Cc: stable@dpdk.org
> Signed-off-by: Andrey Yudin <Andrey.Yudin@infotecs.ru>
> ---
>  lib/graph/node.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/lib/graph/node.c b/lib/graph/node.c
> index 1fce3e6632..bb39c616de 100644
> --- a/lib/graph/node.c
> +++ b/lib/graph/node.c
> @@ -208,6 +208,7 @@ node_clone(struct node *node, const char *name)
>  			goto free;
>  		}
>  
> +		reg->xstats->nb_xstats = node->xstats->nb_xstats;
>  		for (i = 0; i < node->xstats->nb_xstats; i++)
>  			if (rte_strscpy(reg->xstats->xstat_desc[i], node->xstats->xstat_desc[i],
>  					RTE_NODE_XSTAT_DESC_SIZE) < 0)

Reviewed-by: Robin Jarry <rjarry@redhat.com>


^ permalink raw reply

* RE: [PATCH] build: fix libpcap detection with unusable header
From: Maayan Kashani @ 2026-07-08  8:09 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: Bruce Richardson, dev, Raslan Darawsheh, stable, David Marchand
In-Reply-To: <CAOaVG14co-O8rB43VLkAzKNr7yynTnR1NzJyW_UMV9FCmUyzZg@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 4071 bytes --]

Understood. Thanks.

Regards,
Maayan Kashani

From: Stephen Hemminger <stephen@networkplumber.org>
Sent: Wednesday, 8 July 2026 10:11
To: Maayan Kashani <mkashani@nvidia.com>
Cc: Bruce Richardson <bruce.richardson@intel.com>; dev <dev@dpdk.org>; Raslan Darawsheh <rasland@nvidia.com>; stable <stable@dpdk.org>; David Marchand <david.marchand@redhat.com>
Subject: Re: [PATCH] build: fix libpcap detection with unusable header

External email: Use caution opening links or attachments

Not sure. Working around busted packages in DPDK is a bad idea.

On Wed, Jul 8, 2026, 08:38 Maayan Kashani <mkashani@nvidia.com<mailto:mkashani@nvidia.com>> wrote:
Hi, Bruce,
we encountered DPDK build issue on Tencent 4.6.
It is not expected; the package/image appears corrupted.
RPM verification confirms the headers differ from the packaged contents.
The DPDK change is still valid because optional dependency detection should
test for usable declarations, not just file existence and library presence.”

Regards,
Maayan Kashani

> -----Original Message-----
> From: Bruce Richardson <bruce.richardson@intel.com<mailto:bruce.richardson@intel.com>>
> Sent: Tuesday, 7 July 2026 17:16
> To: Maayan Kashani <mkashani@nvidia.com<mailto:mkashani@nvidia.com>>
> Cc: dev@dpdk.org<mailto:dev@dpdk.org>; Raslan Darawsheh <rasland@nvidia.com<mailto:rasland@nvidia.com>>;
> stable@dpdk.org<mailto:stable@dpdk.org>; David Marchand <david.marchand@redhat.com<mailto:david.marchand@redhat.com>>; Stephen
> Hemminger <stephen@networkplumber.org<mailto:stephen@networkplumber.org>>
> Subject: Re: [PATCH] build: fix libpcap detection with unusable header
>
> External email: Use caution opening links or attachments
>
>
> On Tue, Jul 07, 2026 at 04:30:28PM +0300, Maayan Kashani wrote:
> > The libpcap detection only checked that the library was present, that
> > <pcap.h> could be included, and that a trivial program links. None of
> > these fail when a distribution ships a libpcap-devel package whose
> > <pcap.h> is empty (present but declaring nothing) while libpcap.so is
> > installed: has_header() passes on an empty file and the link test does
> > not reference any pcap symbol. RTE_HAS_LIBPCAP was then set and the
> > pcap-dependent code (bpf_convert.c, port source/sink, dumpcap) failed
> > to build with errors such as:
> >
>
> Why would a distribution ship a devel package with an empty header file for
> pcap.h? Is that expected behaviour in some scenario that I'm unaware of,
> because it seems strange to me?
>
> /Bruce
>
> >   bpf_convert.c: error: invalid use of undefined type
> >                  'const struct bpf_insn'
> >
> > Require an actual pcap declaration (pcap_create) to be visible in the
> > header before enabling libpcap support, so a broken or empty header
> > disables the optional pcap features instead of breaking the build.
> >
> > Fixes: d6024c0a6757 ("build: cleanup libpcap dependent components")
> > Cc: stable@dpdk.org<mailto:stable@dpdk.org>
> >
> > Signed-off-by: Maayan Kashani <mkashani@nvidia.com<mailto:mkashani@nvidia.com>>
> > ---
> >  config/meson.build | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/config/meson.build b/config/meson.build index
> > d7f5e55c18f..4bfb8535781 100644
> > --- a/config/meson.build
> > +++ b/config/meson.build
> > @@ -290,7 +290,10 @@ if not pcap_dep.found()
> >      # pcap got a pkg-config file only in 1.9.0
> >      pcap_dep = cc.find_library(pcap_lib, required: false)  endif -if
> > (pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
> > +# has_header() passes even when pcap.h is empty; require a real
> declaration.
> > +if (pcap_dep.found()
> > +        and cc.has_header_symbol('pcap.h', 'pcap_create', dependencies:
> pcap_dep,
> > +                args: '-D_GNU_SOURCE')
> >          and cc.links(min_c_code, dependencies: pcap_dep))
> >      dpdk_conf.set('RTE_HAS_LIBPCAP', 1)
> >      dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
> > --
> > 2.21.0
> >

[-- Attachment #2: Type: text/html, Size: 8741 bytes --]

^ permalink raw reply

* Re: [PATCH] build: fix libpcap detection with unusable header
From: Bruce Richardson @ 2026-07-08  7:54 UTC (permalink / raw)
  To: Maayan Kashani
  Cc: dev@dpdk.org, Raslan Darawsheh, stable@dpdk.org, David Marchand,
	Stephen Hemminger
In-Reply-To: <MW6PR12MB70707673C99F020A595212EBB2FF2@MW6PR12MB7070.namprd12.prod.outlook.com>

On Wed, Jul 08, 2026 at 06:37:59AM +0000, Maayan Kashani wrote:
> Hi, Bruce, we encountered DPDK build issue on Tencent 4.6.  It is not
> expected; the package/image appears corrupted.  RPM verification confirms
> the headers differ from the packaged contents.  The DPDK change is still
> valid because optional dependency detection should test for usable
> declarations, not just file existence and library presence.”
> 
I would disagree. Following that logic of checking for broken packages,
you're only handling a very small subset of that. If we start checking
this, we really should check for each and every definition in the file that
we need - otherwise we can still have issues with a broken package, for
example, it's broken in missing one definition that we need.

IMHO, in all these cases its better to let things fail, rather than working
around them, in order to prompt correction of the broken package.

/Bruce

^ permalink raw reply

* Re: [v4] net/cksum: compute raw cksum for several segments
From: su sai @ 2026-07-08  7:26 UTC (permalink / raw)
  To: Stephen Hemminger, Marat Khalili; +Cc: dev@dpdk.org
In-Reply-To: <20260703074132.2a718abe@phoenix.local>

[-- Attachment #1: Type: text/plain, Size: 1756 bytes --]

Rename test_l4_cksum_multi_mbufs to test_l4_cksum_mbuf_chain, resolve
double-free issue.

On Fri, Jul 3, 2026 at 10:41 PM Stephen Hemminger <
stephen@networkplumber.org> wrote:

> On Thu, 18 Jun 2026 14:32:42 +0800
> Su Sai <spiderdetective.ss@gmail.com> wrote:
>
> > The rte_raw_cksum_mbuf function is used to compute
> > the raw checksum of a packet.
> > If the packet payload stored in multi mbuf, the function
> > will goto the hard case. In hard case,
> > the variable 'tmp' is a type of uint32_t,
> > so rte_bswap16 will drop high 16 bit.
> > Meanwhile, the variable 'sum' is a type of uint32_t,
> > so 'sum += tmp' will drop the carry when overflow.
> > Both drop will make cksum incorrect.
> > This commit fixes the above bug.
> >
> > Signed-off-by: Su Sai <spiderdetective.ss@gmail.com>
> > Acked-by: Marat Khalili <marat.khalili@huawei.com>
> > ---
>
> Still one error in the test.
>
> Error — double-free in test_l4_cksum_multi_mbufs() (app/test/test_cksum.c)
> The segments are chained into one packet (rte_pktmbuf_chain sets
> m[0]->next = m[1], m[1]->next = m[2]), but cleanup then calls
> rte_pktmbuf_free_bulk(m, segs_len) over the array.
> rte_pktmbuf_free_bulk walks the ->next chain of each array element, so
> index 0 frees the entire chain (m[0], m[1], m[2]), and indices 1 and 2
> then free m[1]/m[2] a second time. This fires on the normal success
> path every run, and on the fail path whenever ≥2 segments were chained
> — a debug/ASAN build will abort on the sanity check, and a normal build
> corrupts pool accounting. The array-of-independent-mbufs contract that
> free_bulk expects doesn't hold here because the elements alias one
> chain. Free the chain once through its head:
>

[-- Attachment #2: Type: text/html, Size: 10924 bytes --]

^ permalink raw reply

* [v5] net/cksum: compute raw cksum for several segments
From: Su Sai @ 2026-07-08  7:17 UTC (permalink / raw)
  To: stephen, marat.khalili; +Cc: dev, spiderdetective.ss
In-Reply-To: <20260703074132.2a718abe@phoenix.local>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset=y, Size: 7147 bytes --]

The rte_raw_cksum_mbuf function is used to compute
the raw checksum of a packet.
If the packet payload stored in multi mbuf, the function
will goto the hard case. In hard case,
the variable 'tmp' is a type of uint32_t,
so rte_bswap16 will drop high 16 bit.
Meanwhile, the variable 'sum' is a type of uint32_t,
so 'sum += tmp' will drop the carry when overflow.
Both drop will make cksum incorrect.
This commit fixes the above bug.

Signed-off-by: Su Sai <spiderdetective.ss@gmail.com>
Acked-by: Marat Khalili <marat.khalili@huawei.com>
---
 .mailmap              |   1 +
 app/test/test_cksum.c | 109 ++++++++++++++++++++++++++++++++++++++++++
 lib/net/rte_cksum.h   |  27 +++++++++--
 3 files changed, 133 insertions(+), 4 deletions(-)

diff --git a/.mailmap b/.mailmap
index 4001e5fb0e..bcf73cb902 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1630,6 +1630,7 @@ Sylvia Grundwürmer <sylvia.grundwuermer@b-plus.com>
 Sylwester Dziedziuch <sylwesterx.dziedziuch@intel.com>
 Sylwia Wnuczko <sylwia.wnuczko@intel.com>
 Szymon Sliwa <szs@semihalf.com>
+Su Sai <spiderdetective.ss@gmail.com> <susai.ss@bytedance.com>
 Szymon T Cudzilo <szymon.t.cudzilo@intel.com>
 Tadhg Kearney <tadhg.kearney@intel.com>
 Taekyung Kim <kim.tae.kyung@navercorp.com>
diff --git a/app/test/test_cksum.c b/app/test/test_cksum.c
index ea443382a1..73f2511731 100644
--- a/app/test/test_cksum.c
+++ b/app/test/test_cksum.c
@@ -85,6 +85,42 @@ static const char test_cksum_ipv4_opts_udp[] = {
 	0x00, 0x35, 0x00, 0x09, 0x89, 0x6f, 0x78,
 };
 
+/*
+ * generated in scapy with
+ * Ether()/IP()/TCP(options=[NOP,NOP,Timestamps])/os.urandom(113))
+ */
+static const char test_cksum_ipv4_tcp_multi_segs[] = {
+	0x00, 0x16, 0x3e, 0x0b, 0x6b, 0xd2, 0xee, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x45, 0x00,
+	0x00, 0xa5, 0x46, 0x10, 0x40, 0x00, 0x40, 0x06,
+	0x80, 0xb5, 0xc0, 0xa8, 0xf9, 0x1d, 0xc0, 0xa8,
+	0xf9, 0x1e, 0xdc, 0xa2, 0x14, 0x51, 0xbb, 0x8f,
+	0xa0, 0x00, 0xe4, 0x7c, 0xe4, 0xb8, 0x80, 0x10,
+	0x02, 0x00, 0x4b, 0xc1, 0x00, 0x00, 0x01, 0x01,
+	0x08, 0x0a, 0x90, 0x60, 0xf4, 0xff, 0x03, 0xc5,
+	0xb4, 0x19, 0x77, 0x34, 0xd4, 0xdc, 0x84, 0x86,
+	0xff, 0x44, 0x09, 0x63, 0x36, 0x2e, 0x26, 0x9b,
+	0x90, 0x70, 0xf2, 0xed, 0xc8, 0x5b, 0x87, 0xaa,
+	0xb4, 0x67, 0x6b, 0x32, 0x3d, 0xc4, 0xbf, 0x15,
+	0xa9, 0x16, 0x6c, 0x2a, 0x9d, 0xb2, 0xb7, 0x6b,
+	0x58, 0x44, 0x58, 0x12, 0x4b, 0x8f, 0xe5, 0x12,
+	0x11, 0x90, 0x94, 0x68, 0x37, 0xad, 0x0a, 0x9b,
+	0xd6, 0x79, 0xf2, 0xb7, 0x31, 0xcf, 0x44, 0x22,
+	0xc8, 0x99, 0x3f, 0xe5, 0xe7, 0xac, 0xc7, 0x0b,
+	0x86, 0xdf, 0xda, 0xed, 0x0a, 0x0f, 0x86, 0xd7,
+	0x48, 0xe2, 0xf1, 0xc2, 0x43, 0xed, 0x47, 0x3a,
+	0xea, 0x25, 0x2d, 0xd6, 0x60, 0x38, 0x30, 0x07,
+	0x28, 0xdd, 0x1f, 0x0c, 0xdd, 0x7b, 0x7c, 0xd9,
+	0x35, 0x9d, 0x14, 0xaa, 0xc6, 0x35, 0xd1, 0x03,
+	0x38, 0xb1, 0xf5,
+};
+
+static const uint8_t test_cksum_ipv4_tcp_multi_segs_len[] = {
+	66,  /* the first seg contains all headers, including L2 to L4 */
+	61,  /* the second seg length is odd, test byte order independent */
+	52,  /* three segs are sufficient to test the most complex scenarios */
+};
+
 /* test l3/l4 checksum api */
 static int
 test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len)
@@ -223,6 +259,73 @@ test_l4_cksum(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len)
 	return -1;
 }
 
+/* test l4 checksum api for a packet with mbuf chain */
+static int
+test_l4_cksum_mbuf_chain(struct rte_mempool *pktmbuf_pool, const char *pktdata, size_t len,
+			     const uint8_t *segs, size_t segs_len)
+{
+	struct rte_mbuf *m[NB_MBUF] = {0};
+	struct rte_mbuf *m_hdr = NULL;
+	struct rte_net_hdr_lens hdr_lens;
+	size_t i, off = 0;
+	uint32_t packet_type, l3;
+	void *l3_hdr;
+	char *data;
+
+	for (i = 0; i < segs_len; i++) {
+		m[i] = rte_pktmbuf_alloc(pktmbuf_pool);
+		if (m[i] == NULL)
+			GOTO_FAIL("Cannot allocate mbuf");
+
+		data = rte_pktmbuf_append(m[i], segs[i]);
+		if (data == NULL) {
+			rte_pktmbuf_free(m[i]);
+			m[i] = NULL;
+			GOTO_FAIL("Cannot append data");
+		}
+
+		memcpy(data, pktdata + off, segs[i]);
+		off += segs[i];
+
+		if (m_hdr) {
+			if (rte_pktmbuf_chain(m_hdr, m[i])) {
+				rte_pktmbuf_free(m[i]);
+				m[i] = NULL;
+				GOTO_FAIL("Cannot chain mbuf");
+			}
+		} else {
+			m_hdr = m[i];
+		}
+	}
+
+	if (off != len)
+		GOTO_FAIL("Invalid segs");
+
+	packet_type = rte_net_get_ptype(m_hdr, &hdr_lens, RTE_PTYPE_ALL_MASK);
+	l3 = packet_type & RTE_PTYPE_L3_MASK;
+
+	l3_hdr = rte_pktmbuf_mtod_offset(m_hdr, void *, hdr_lens.l2_len);
+	off = hdr_lens.l2_len + hdr_lens.l3_len;
+
+	if (l3 == RTE_PTYPE_L3_IPV4 || l3 == RTE_PTYPE_L3_IPV4_EXT) {
+		if (rte_ipv4_udptcp_cksum_mbuf_verify(m_hdr, l3_hdr, off) != 0)
+			GOTO_FAIL("Invalid L4 checksum verification for mbuf chain");
+	} else if (l3 == RTE_PTYPE_L3_IPV6 || l3 == RTE_PTYPE_L3_IPV6_EXT) {
+		if (rte_ipv6_udptcp_cksum_mbuf_verify(m_hdr, l3_hdr, off) != 0)
+			GOTO_FAIL("Invalid L4 checksum verification for mbuf chain");
+	}
+
+	rte_pktmbuf_free(m_hdr);
+
+	return 0;
+
+fail:
+	if (m_hdr)
+		rte_pktmbuf_free(m_hdr);
+
+	return -1;
+}
+
 static int
 test_cksum(void)
 {
@@ -256,6 +359,12 @@ test_cksum(void)
 			  sizeof(test_cksum_ipv4_opts_udp)) < 0)
 		GOTO_FAIL("checksum error on ipv4_opts_udp");
 
+	if (test_l4_cksum_mbuf_chain(pktmbuf_pool, test_cksum_ipv4_tcp_multi_segs,
+			  sizeof(test_cksum_ipv4_tcp_multi_segs),
+			  test_cksum_ipv4_tcp_multi_segs_len,
+			  sizeof(test_cksum_ipv4_tcp_multi_segs_len)) < 0)
+		GOTO_FAIL("checksum error on mbuf chain check");
+
 	rte_mempool_free(pktmbuf_pool);
 
 	return 0;
diff --git a/lib/net/rte_cksum.h b/lib/net/rte_cksum.h
index a8e8927952..679ba82eb6 100644
--- a/lib/net/rte_cksum.h
+++ b/lib/net/rte_cksum.h
@@ -80,6 +80,25 @@ __rte_raw_cksum_reduce(uint32_t sum)
 	return (uint16_t)sum;
 }
 
+/**
+ * @internal Reduce a sum to the non-complemented checksum.
+ * Helper routine for the rte_raw_cksum_mbuf().
+ *
+ * @param sum
+ *   Value of the sum.
+ * @return
+ *   The non-complemented checksum.
+ */
+static inline uint16_t
+__rte_raw_cksum_reduce_u64(uint64_t sum)
+{
+	uint32_t tmp;
+
+	tmp = __rte_raw_cksum_reduce((uint32_t)sum);
+	tmp += __rte_raw_cksum_reduce((uint32_t)(sum >> 32));
+	return __rte_raw_cksum_reduce(tmp);
+}
+
 /**
  * Process the non-complemented checksum of a buffer.
  *
@@ -119,8 +138,8 @@ rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
 {
 	const struct rte_mbuf *seg;
 	const char *buf;
-	uint32_t sum, tmp;
-	uint32_t seglen, done;
+	uint32_t seglen, done, tmp;
+	uint64_t sum;
 
 	/* easy case: all data in the first segment */
 	if (off + len <= rte_pktmbuf_data_len(m)) {
@@ -157,7 +176,7 @@ rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
 	for (;;) {
 		tmp = __rte_raw_cksum(buf, seglen, 0);
 		if (done & 1)
-			tmp = rte_bswap16((uint16_t)tmp);
+			tmp = rte_bswap32(tmp);
 		sum += tmp;
 		done += seglen;
 		if (done == len)
@@ -169,7 +188,7 @@ rte_raw_cksum_mbuf(const struct rte_mbuf *m, uint32_t off, uint32_t len,
 			seglen = len - done;
 	}
 
-	*cksum = __rte_raw_cksum_reduce(sum);
+	*cksum = __rte_raw_cksum_reduce_u64(sum);
 	return 0;
 }
 
-- 
2.20.1


^ permalink raw reply related

* Re: [PATCH] build: fix libpcap detection with unusable header
From: Stephen Hemminger @ 2026-07-08  7:11 UTC (permalink / raw)
  To: Maayan Kashani
  Cc: Bruce Richardson, dev, Raslan Darawsheh, stable, David Marchand
In-Reply-To: <MW6PR12MB70707673C99F020A595212EBB2FF2@MW6PR12MB7070.namprd12.prod.outlook.com>

[-- Attachment #1: Type: text/plain, Size: 3453 bytes --]

Not sure. Working around busted packages in DPDK is a bad idea.

On Wed, Jul 8, 2026, 08:38 Maayan Kashani <mkashani@nvidia.com> wrote:

> Hi, Bruce,
> we encountered DPDK build issue on Tencent 4.6.
> It is not expected; the package/image appears corrupted.
> RPM verification confirms the headers differ from the packaged contents.
> The DPDK change is still valid because optional dependency detection
> should
> test for usable declarations, not just file existence and library
> presence.”
>
> Regards,
> Maayan Kashani
>
> > -----Original Message-----
> > From: Bruce Richardson <bruce.richardson@intel.com>
> > Sent: Tuesday, 7 July 2026 17:16
> > To: Maayan Kashani <mkashani@nvidia.com>
> > Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>;
> > stable@dpdk.org; David Marchand <david.marchand@redhat.com>; Stephen
> > Hemminger <stephen@networkplumber.org>
> > Subject: Re: [PATCH] build: fix libpcap detection with unusable header
> >
> > External email: Use caution opening links or attachments
> >
> >
> > On Tue, Jul 07, 2026 at 04:30:28PM +0300, Maayan Kashani wrote:
> > > The libpcap detection only checked that the library was present, that
> > > <pcap.h> could be included, and that a trivial program links. None of
> > > these fail when a distribution ships a libpcap-devel package whose
> > > <pcap.h> is empty (present but declaring nothing) while libpcap.so is
> > > installed: has_header() passes on an empty file and the link test does
> > > not reference any pcap symbol. RTE_HAS_LIBPCAP was then set and the
> > > pcap-dependent code (bpf_convert.c, port source/sink, dumpcap) failed
> > > to build with errors such as:
> > >
> >
> > Why would a distribution ship a devel package with an empty header file
> for
> > pcap.h? Is that expected behaviour in some scenario that I'm unaware of,
> > because it seems strange to me?
> >
> > /Bruce
> >
> > >   bpf_convert.c: error: invalid use of undefined type
> > >                  'const struct bpf_insn'
> > >
> > > Require an actual pcap declaration (pcap_create) to be visible in the
> > > header before enabling libpcap support, so a broken or empty header
> > > disables the optional pcap features instead of breaking the build.
> > >
> > > Fixes: d6024c0a6757 ("build: cleanup libpcap dependent components")
> > > Cc: stable@dpdk.org
> > >
> > > Signed-off-by: Maayan Kashani <mkashani@nvidia.com>
> > > ---
> > >  config/meson.build | 5 ++++-
> > >  1 file changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/config/meson.build b/config/meson.build index
> > > d7f5e55c18f..4bfb8535781 100644
> > > --- a/config/meson.build
> > > +++ b/config/meson.build
> > > @@ -290,7 +290,10 @@ if not pcap_dep.found()
> > >      # pcap got a pkg-config file only in 1.9.0
> > >      pcap_dep = cc.find_library(pcap_lib, required: false)  endif -if
> > > (pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
> > > +# has_header() passes even when pcap.h is empty; require a real
> > declaration.
> > > +if (pcap_dep.found()
> > > +        and cc.has_header_symbol('pcap.h', 'pcap_create',
> dependencies:
> > pcap_dep,
> > > +                args: '-D_GNU_SOURCE')
> > >          and cc.links(min_c_code, dependencies: pcap_dep))
> > >      dpdk_conf.set('RTE_HAS_LIBPCAP', 1)
> > >      dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
> > > --
> > > 2.21.0
> > >
>

[-- Attachment #2: Type: text/html, Size: 5045 bytes --]

^ permalink raw reply

* RE: [PATCH] build: fix libpcap detection with unusable header
From: Maayan Kashani @ 2026-07-08  6:37 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: dev@dpdk.org, Raslan Darawsheh, stable@dpdk.org, David Marchand,
	Stephen Hemminger
In-Reply-To: <ak0KN_oZGU1WkPHm@bricha3-mobl1.ger.corp.intel.com>

Hi, Bruce, 
we encountered DPDK build issue on Tencent 4.6.
It is not expected; the package/image appears corrupted. 
RPM verification confirms the headers differ from the packaged contents. 
The DPDK change is still valid because optional dependency detection should 
test for usable declarations, not just file existence and library presence.”

Regards,
Maayan Kashani

> -----Original Message-----
> From: Bruce Richardson <bruce.richardson@intel.com>
> Sent: Tuesday, 7 July 2026 17:16
> To: Maayan Kashani <mkashani@nvidia.com>
> Cc: dev@dpdk.org; Raslan Darawsheh <rasland@nvidia.com>;
> stable@dpdk.org; David Marchand <david.marchand@redhat.com>; Stephen
> Hemminger <stephen@networkplumber.org>
> Subject: Re: [PATCH] build: fix libpcap detection with unusable header
> 
> External email: Use caution opening links or attachments
> 
> 
> On Tue, Jul 07, 2026 at 04:30:28PM +0300, Maayan Kashani wrote:
> > The libpcap detection only checked that the library was present, that
> > <pcap.h> could be included, and that a trivial program links. None of
> > these fail when a distribution ships a libpcap-devel package whose
> > <pcap.h> is empty (present but declaring nothing) while libpcap.so is
> > installed: has_header() passes on an empty file and the link test does
> > not reference any pcap symbol. RTE_HAS_LIBPCAP was then set and the
> > pcap-dependent code (bpf_convert.c, port source/sink, dumpcap) failed
> > to build with errors such as:
> >
> 
> Why would a distribution ship a devel package with an empty header file for
> pcap.h? Is that expected behaviour in some scenario that I'm unaware of,
> because it seems strange to me?
> 
> /Bruce
> 
> >   bpf_convert.c: error: invalid use of undefined type
> >                  'const struct bpf_insn'
> >
> > Require an actual pcap declaration (pcap_create) to be visible in the
> > header before enabling libpcap support, so a broken or empty header
> > disables the optional pcap features instead of breaking the build.
> >
> > Fixes: d6024c0a6757 ("build: cleanup libpcap dependent components")
> > Cc: stable@dpdk.org
> >
> > Signed-off-by: Maayan Kashani <mkashani@nvidia.com>
> > ---
> >  config/meson.build | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/config/meson.build b/config/meson.build index
> > d7f5e55c18f..4bfb8535781 100644
> > --- a/config/meson.build
> > +++ b/config/meson.build
> > @@ -290,7 +290,10 @@ if not pcap_dep.found()
> >      # pcap got a pkg-config file only in 1.9.0
> >      pcap_dep = cc.find_library(pcap_lib, required: false)  endif -if
> > (pcap_dep.found() and cc.has_header('pcap.h', dependencies: pcap_dep)
> > +# has_header() passes even when pcap.h is empty; require a real
> declaration.
> > +if (pcap_dep.found()
> > +        and cc.has_header_symbol('pcap.h', 'pcap_create', dependencies:
> pcap_dep,
> > +                args: '-D_GNU_SOURCE')
> >          and cc.links(min_c_code, dependencies: pcap_dep))
> >      dpdk_conf.set('RTE_HAS_LIBPCAP', 1)
> >      dpdk_extra_ldflags += '-l@0@'.format(pcap_lib)
> > --
> > 2.21.0
> >

^ permalink raw reply

* Re: [PATCH] examples: Fix vm_power_manager scratch area to /run/dpdk/powermanager
From: Sudheendra S @ 2026-07-08  2:27 UTC (permalink / raw)
  To: Bruce Richardson
  Cc: Stephen Hemminger, dev, Anatoly Burakov, Sivaprasad Tummala
In-Reply-To: <ahm4Qr5gLBf6sxof@bricha3-mobl1.ger.corp.intel.com>

[-- Attachment #1: Type: text/plain, Size: 4152 bytes --]

Hi Stephen,

I totally understand that you and the team are very busy.  I hope to get
some direction since this is first time ever to be submitting a patch to
DPDK.

From what I understand from the above email exchange changes needed are :

   1. I see that rte_eal_get_runtime_dir() is RTE_EXPORTED_SYMBOL.  I will
   verify that channel_manager has access to this symbol.
   2. Upon successful creation of /run/dpdk, I can mkdir
   CHANNEL_MGR_SOCKET_PATH (/var/run/dpdk/powermonitor) and opendir() that for
   subsequent processing.
   3. Fixup the documentation to reflect correct powermonitor path

Please let me know if I am missing anything or if I misinterpreting any
part of the email exchange.

Appreciate your timely help and support.

On Fri, May 29, 2026 at 9:01 AM Bruce Richardson <bruce.richardson@intel.com>
wrote:

> On Fri, May 29, 2026 at 08:23:24AM -0700, Stephen Hemminger wrote:
> > On Fri, 29 May 2026 09:01:34 +0100
> > Bruce Richardson <bruce.richardson@intel.com> wrote:
> >
> > > On Thu, May 28, 2026 at 07:04:48PM +0000, Sudheendra Sampath wrote:
> > > > This patch for bug 1832 will do the following:
> > > > 1.  If /run/dpdk is not present, it will create it first with and
> > > >     then create powermanager directory underneath it.
> > > > 2.  If /run/dpdk is present, it will verify it is actually a
> directory
> > > >     before creating subdirectory, powermanager.
> > > >
> > > I would suggest using $XDG_RUNTIME_DIR for the directory path, rather
> than
> > > hardcoding it by default. If XDG_RUNTIME_DIR is not set, then maybe
> > > consider using /run/dpdk. However, rather than /run/dpdk, I'd suggest
> using
> > > the normal runtime dir path on most distros as the default:
> > > /run/user/<uid>.
> > >
> > > /Bruce
> >
> > The login in EAL is a little more detailed.
> > The choice is from systemd conventions which follows filesystem
> hierarchy.
> >
> >
> > int eal_create_runtime_dir(void)
> > {
> >       const char *directory;
> >       char run_dir[PATH_MAX];
> >       char tmp[PATH_MAX];
> >       int ret;
> >
> >       /* from RuntimeDirectory= see systemd.exec */
> >       directory = getenv("RUNTIME_DIRECTORY");
> >       if (directory == NULL) {
> >               /*
> >                * Used standard convention defined in
> >                * XDG Base Directory Specification and
> >                * Filesystem Hierarchy Standard.
> >                */
> >               if (getuid() == 0)
> >                       directory = "/var/run";
> >               else
> >                       directory = getenv("XDG_RUNTIME_DIR") ? : "/tmp";
> >       }
> >
> >       /* create DPDK subdirectory under runtime dir */
> >       ret = snprintf(tmp, sizeof(tmp), "%s/dpdk", directory);
> >       if (ret < 0 || ret == sizeof(tmp)) {
> >               EAL_LOG(ERR, "Error creating DPDK runtime path name");
> >               return -1;
> >       }
> >
> >       /* create prefix-specific subdirectory under DPDK runtime dir */
> >       ret = snprintf(run_dir, sizeof(run_dir), "%s/%s",
> >                       tmp, eal_get_hugefile_prefix());
> >       if (ret < 0 || ret == sizeof(run_dir)) {
> >               EAL_LOG(ERR, "Error creating prefix-specific runtime path
> name");
> >               return -1;
> >       }
> >
> >       /* create the path if it doesn't exist. no "mkdir -p" here, so do
> it
> >        * step by step.
> >        */
> >       ret = mkdir(tmp, 0700);
> >       if (ret < 0 && errno != EEXIST) {
> >               EAL_LOG(ERR, "Error creating '%s': %s",
> >                       tmp, strerror(errno));
> >               return -1;
> >       }
> >
> >       ret = mkdir(run_dir, 0700);
> >       if (ret < 0 && errno != EEXIST) {
> >               EAL_LOG(ERR, "Error creating '%s': %s",
> >                       run_dir, strerror(errno));
> >               return -1;
> >       }
>
> Yes. Can the power manager call the rte_eal_get_runtime_dir() API and use
> that as a basis for its working directory? Save duplicating all this logic.
>
> /Bruce
>

[-- Attachment #2: Type: text/html, Size: 5586 bytes --]

^ permalink raw reply

* Re: [PATCH v5] dts: report dut/NIC info during DTS run
From: Patrick Robb @ 2026-07-08  1:46 UTC (permalink / raw)
  To: Koushik Bhargav Nimoji; +Cc: luca.vizzarro, dev, abailey, ahassick, lylavoie
In-Reply-To: <20260625154712.2255474-1-knimoji@iol.unh.edu>

[-- Attachment #1: Type: text/plain, Size: 52 bytes --]

Tested-by: Patrick Robb <patrickrobb1997@gmail.com>

[-- Attachment #2: Type: text/html, Size: 126 bytes --]

^ permalink raw reply

* Re: [PATCH v3] dts: update dts check format script and resolve errors
From: Patrick Robb @ 2026-07-08  1:16 UTC (permalink / raw)
  To: Koushik Bhargav Nimoji; +Cc: luca.vizzarro, dev, abailey, ahassick, lylavoie
In-Reply-To: <CAKYPG+yPEA2pH4hv3PHDGkVoc=NggT4+GWrvLg0E3V4JvRLBVA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 40 bytes --]

Applied to next-dts, thank you Koushik.

[-- Attachment #2: Type: text/html, Size: 61 bytes --]

^ permalink raw reply

* Re: [PATCH v2 2/2] dts: add latency coverage for cryptodev testing
From: Patrick Robb @ 2026-07-08  0:56 UTC (permalink / raw)
  To: Andrew Bailey; +Cc: luca.vizzarro, dev, knimoji
In-Reply-To: <20260706132633.465385-2-abailey@iol.unh.edu>

[-- Attachment #1: Type: text/plain, Size: 36 bytes --]

Applied to next-dts, thanks Andrew.

[-- Attachment #2: Type: text/html, Size: 57 bytes --]

^ permalink raw reply

* Re: [PATCH v2 1/2] dts: update parsing for cryptodev latency
From: Patrick Robb @ 2026-07-08  0:56 UTC (permalink / raw)
  To: Andrew Bailey; +Cc: luca.vizzarro, dev, knimoji
In-Reply-To: <CABJ3N2Xkr3zihiTbzdByigibcy4i_txxCk-0Drzw3E1weze6rw@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 36 bytes --]

Applied to next-dts, thanks Andrew.

[-- Attachment #2: Type: text/html, Size: 57 bytes --]

^ permalink raw reply

* Re: [PATCH v2] dev: fix hotplug notification to secondary
From: fengchengwen @ 2026-07-08  0:38 UTC (permalink / raw)
  To: David Marchand, dev
In-Reply-To: <20260707115551.967336-1-david.marchand@redhat.com>

Reviewed-by: Chengwen Feng <fengchengwen@huawei.com>

On 7/7/2026 7:55 PM, David Marchand wrote:
> There was a logical error when making some last minute change.
> Fix the no_shconf evaluation.
> 
> Bugzilla ID: 1963
> Fixes: 1a2e26d8701d ("dev: skip multi-process in hotplug")
> 
> Signed-off-by: David Marchand <david.marchand@redhat.com>
> ---
> Changes since v1:
> - separated the unit test from the fix,
> 
> ---
>  lib/eal/common/eal_common_dev.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/lib/eal/common/eal_common_dev.c b/lib/eal/common/eal_common_dev.c
> index 9ed62a20e0..b43b0a4bb3 100644
> --- a/lib/eal/common/eal_common_dev.c
> +++ b/lib/eal/common/eal_common_dev.c
> @@ -269,7 +269,7 @@ rte_dev_probe(const char *devargs)
>  {
>  	const struct internal_config *internal_conf =
>  		eal_get_internal_configuration();
> -	bool do_mp = !!internal_conf->no_shconf;
> +	bool do_mp = internal_conf->no_shconf == 0;
>  	struct eal_dev_mp_req req;
>  	struct rte_device *dev;
>  	int ret;
> @@ -428,7 +428,7 @@ rte_dev_remove(struct rte_device *dev)
>  {
>  	const struct internal_config *internal_conf =
>  		eal_get_internal_configuration();
> -	bool do_mp = !!internal_conf->no_shconf;
> +	bool do_mp = internal_conf->no_shconf == 0;
>  	struct eal_dev_mp_req req;
>  	char *devargs;
>  	int ret;


^ permalink raw reply

* Re: [PATCH v3 9/9] net/gve: restrict max ring size in GQ QPL to 2K
From: Joshua Washington @ 2026-07-07 22:13 UTC (permalink / raw)
  To: Joshua Washington, Harshitha Ramamurthy
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-10-joshwash@google.com>

On Tue, Jul 7, 2026 at 12:40 PM Joshua Washington <joshwash@google.com> wrote:
>
> The GQ QPL queue format has a maximum supported ring size of 2k.
> However, it is possible in some cases for the device to pass a larger
> ring size as the max ring size. Restrict the ring size in the driver to
> ensure that rings with invalid queue depths are not created.
>
> Fixes: cde01d164f8f ("net/gve: support modifying ring size in GQ format")
> Cc: stable@dpdk.org
> Signed-off-by: Joshua Washington <joshwash@google.com>
> Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
> ---
>  drivers/net/gve/base/gve_adminq.c | 12 +++++++++---
>  drivers/net/gve/gve_ethdev.h      |  1 +
>  2 files changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
> index 2b25c7f390..315e2456fd 100644
> --- a/drivers/net/gve/base/gve_adminq.c
> +++ b/drivers/net/gve/base/gve_adminq.c
> @@ -6,6 +6,7 @@
>  #include "../gve_ethdev.h"
>  #include "gve_adminq.h"
>  #include "gve_register.h"
> +#include "rte_common.h"

Looks like I forgot to fix the include formatting here. I will fix in
the next revision.

>
>  #define GVE_MAX_ADMINQ_RELEASE_CHECK   500
>  #define GVE_ADMINQ_SLEEP_LEN           20
> @@ -946,15 +947,20 @@ static void
>  gve_set_max_desc_cnt(struct gve_priv *priv,
>         const struct gve_device_option_modify_ring *modify_ring)
>  {
> +       priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
> +       priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
> +
>         if (priv->queue_format == GVE_DQO_RDA_FORMAT) {
>                 PMD_DRV_LOG(DEBUG, "Overriding max ring size from device for DQ "
>                             "queue format to 4096.");
>                 priv->max_rx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
>                 priv->max_tx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
> -               return;
> +       } else if (priv->queue_format == GVE_GQI_QPL_FORMAT) {
> +               priv->max_rx_desc_cnt = RTE_MIN(priv->max_rx_desc_cnt,
> +                                               GVE_MAX_RING_SIZE_GQ_QPL);
> +               priv->max_tx_desc_cnt = RTE_MIN(priv->max_tx_desc_cnt,
> +                                               GVE_MAX_RING_SIZE_GQ_QPL);
>         }
> -       priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
> -       priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
>  }
>
>  static void gve_enable_supported_features(struct gve_priv *priv,
> diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
> index 4a7e5ecdf3..c9a176ff17 100644
> --- a/drivers/net/gve/gve_ethdev.h
> +++ b/drivers/net/gve/gve_ethdev.h
> @@ -21,6 +21,7 @@
>  #define DQO_TX_MULTIPLIER 4
>
>  #define GVE_DEFAULT_MAX_RING_SIZE      1024
> +#define GVE_MAX_RING_SIZE_GQ_QPL       2048
>  #define GVE_DEFAULT_MIN_RX_RING_SIZE   512
>  #define GVE_DEFAULT_MIN_TX_RING_SIZE   256
>
> --
> 2.55.0.rc2.803.g1fd1e6609c-goog
>


-- 

Joshua Washington | Software Engineer | joshwash@google.com | (414) 366-4423

^ permalink raw reply

* Re: [PATCH v4] dts: update test suite names to be clear and consistent
From: Andrew Bailey @ 2026-07-07 17:47 UTC (permalink / raw)
  To: Luca Vizzarro; +Cc: patrickrobb1997, dev, lylavoie, knimoji, ahassick
In-Reply-To: <0b37dd2e-59ba-4f4a-84f9-3ae6e37f062e@arm.com>

[-- Attachment #1: Type: text/plain, Size: 288 bytes --]

Thank you Luca for the suggestion,

This also does not seem to work. I believe it is because the .rst files are
being changed more than some threshold since they are only a couple lines
long to begin with. So git sees them as new files entirely rather than a
rename of the previous file.

[-- Attachment #2: Type: text/html, Size: 318 bytes --]

^ permalink raw reply

* [PATCH] net/i40e: fix FDIR flexible payload issues
From: sandeep.penigalapati @ 2026-07-08  0:20 UTC (permalink / raw)
  To: dev; +Cc: bruce.richardson, stable, Sandeep Penigalapati

From: Sandeep Penigalapati <sandeep.penigalapati@intel.com>

This fixes two issues in the i40e Flow Director flexible payload path.

The bitmask array bound was checked after the write to
bitmask[nb_bitmask], allowing a one-slot out-of-bounds write when the
number of partial-mask words exceeds I40E_FDIR_BITMASK_NUM_WORD. Move
the check before the write and use '>=' so the array is never indexed
out of bounds.

In addition, i40e_flow_set_fdir_flex_pit() programs the global GLQF_ORT
register, which is shared by all PFs on the NIC. It was called before
the flex mask was validated, so a rule that is later rejected still left
the global register modified, affecting other PFs. Validate the flex
mask first and only touch the hardware registers once it has passed.

Fixes: 6ced3dd72f5f ("net/i40e: support flexible payload parsing for FDIR")
Cc: stable@dpdk.org
Signed-off-by: Sandeep Penigalapati <sandeep.penigalapati@intel.com>
---
 drivers/net/intel/i40e/i40e_fdir.c | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/drivers/net/intel/i40e/i40e_fdir.c b/drivers/net/intel/i40e/i40e_fdir.c
index ad256a5a11..8a233f8a97 100644
--- a/drivers/net/intel/i40e/i40e_fdir.c
+++ b/drivers/net/intel/i40e/i40e_fdir.c
@@ -1230,12 +1230,12 @@ i40e_flow_store_flex_mask(struct i40e_pf *pf,
 			flex_mask.word_mask |=
 				I40E_FLEX_WORD_MASK(i / sizeof(uint16_t));
 			if (mask_tmp != UINT16_MAX) {
+				if (nb_bitmask >= I40E_FDIR_BITMASK_NUM_WORD)
+					return -1;
 				flex_mask.bitmask[nb_bitmask].mask = ~mask_tmp;
 				flex_mask.bitmask[nb_bitmask].offset =
 					i / sizeof(uint16_t);
 				nb_bitmask++;
-				if (nb_bitmask > I40E_FDIR_BITMASK_NUM_WORD)
-					return -1;
 			}
 		}
 	}
@@ -1488,15 +1488,17 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 				}
 			}
 
-			if (cfg_flex_pit)
-				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
-						filter->input.flow_ext.raw_id);
-
 			/* Store flex mask to SW */
 			for (i = 0; i < I40E_FDIR_MAX_FLEX_LEN; i++)
 				flex_mask[i] =
 					filter->input.flow_ext.flex_mask[i];
 
+			/* Validate the flex mask before writing any hardware
+			 * register. i40e_flow_set_fdir_flex_pit() below programs
+			 * the global GLQF_ORT register, which is shared by all
+			 * PFs on the NIC, so it must not be touched for a rule
+			 * that is going to be rejected.
+			 */
 			ret = i40e_flow_store_flex_mask(pf, pctype, flex_mask);
 			if (ret == -1) {
 				PMD_DRV_LOG(ERR, "Exceed maximal"
@@ -1506,9 +1508,14 @@ i40e_flow_add_del_fdir_filter(struct rte_eth_dev *dev,
 				PMD_DRV_LOG(ERR, "Conflict with the"
 					    " first flexible rule");
 				return -EINVAL;
-			} else if (ret == 0) {
-				i40e_flow_set_fdir_flex_msk(pf, pctype);
 			}
+
+			if (cfg_flex_pit)
+				i40e_flow_set_fdir_flex_pit(pf, layer_idx,
+						filter->input.flow_ext.raw_id);
+
+			if (ret == 0)
+				i40e_flow_set_fdir_flex_msk(pf, pctype);
 		}
 
 		ret = i40e_sw_fdir_filter_insert(pf, &check_filter);
-- 
2.27.0


^ permalink raw reply related

* Re: [PATCH v2 0/9] Stability fixes for GVE
From: Bruce Richardson @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Joshua Washington; +Cc: Stephen Hemminger, dev
In-Reply-To: <CALuQH+UE2kJdfbny0qLSxB+izFSPTQJXVCwDNbUotrcQL4LYhw@mail.gmail.com>

On Tue, Jul 07, 2026 at 12:02:18PM -0400, Joshua Washington wrote:
> >
> > Better but fails on 32 bit build during post-merge testing
> > DPDK 26.07.0-rc2
> 
> Will fix in v3. Is there a way I can test 32-bit compile using
> test-meson-builds.sh? It doesn't seem to be covered there by default.

It is covered if the necessary 32-bit multilib packages are available. I
verified using my ubuntu install here, and after installing gcc-multilib
package I had 32-bit builds from test-meson-builds.sh. Unfortunately, the
multilib package for 32-bit conflicts with the packages for arm and PPC
building, which is why I didnt have them installed myself before now.

/Bruce

^ permalink raw reply

* [PATCH v3 9/9] net/gve: restrict max ring size in GQ QPL to 2K
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Harshitha Ramamurthy,
	Rushil Gupta
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

The GQ QPL queue format has a maximum supported ring size of 2k.
However, it is possible in some cases for the device to pass a larger
ring size as the max ring size. Restrict the ring size in the driver to
ensure that rings with invalid queue depths are not created.

Fixes: cde01d164f8f ("net/gve: support modifying ring size in GQ format")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/base/gve_adminq.c | 12 +++++++++---
 drivers/net/gve/gve_ethdev.h      |  1 +
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/net/gve/base/gve_adminq.c b/drivers/net/gve/base/gve_adminq.c
index 2b25c7f390..315e2456fd 100644
--- a/drivers/net/gve/base/gve_adminq.c
+++ b/drivers/net/gve/base/gve_adminq.c
@@ -6,6 +6,7 @@
 #include "../gve_ethdev.h"
 #include "gve_adminq.h"
 #include "gve_register.h"
+#include "rte_common.h"
 
 #define GVE_MAX_ADMINQ_RELEASE_CHECK	500
 #define GVE_ADMINQ_SLEEP_LEN		20
@@ -946,15 +947,20 @@ static void
 gve_set_max_desc_cnt(struct gve_priv *priv,
 	const struct gve_device_option_modify_ring *modify_ring)
 {
+	priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
+	priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
+
 	if (priv->queue_format == GVE_DQO_RDA_FORMAT) {
 		PMD_DRV_LOG(DEBUG, "Overriding max ring size from device for DQ "
 			    "queue format to 4096.");
 		priv->max_rx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
 		priv->max_tx_desc_cnt = GVE_MAX_QUEUE_SIZE_DQO;
-		return;
+	} else if (priv->queue_format == GVE_GQI_QPL_FORMAT) {
+		priv->max_rx_desc_cnt = RTE_MIN(priv->max_rx_desc_cnt,
+						GVE_MAX_RING_SIZE_GQ_QPL);
+		priv->max_tx_desc_cnt = RTE_MIN(priv->max_tx_desc_cnt,
+						GVE_MAX_RING_SIZE_GQ_QPL);
 	}
-	priv->max_rx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.rx);
-	priv->max_tx_desc_cnt = be16_to_cpu(modify_ring->max_ring_size.tx);
 }
 
 static void gve_enable_supported_features(struct gve_priv *priv,
diff --git a/drivers/net/gve/gve_ethdev.h b/drivers/net/gve/gve_ethdev.h
index 4a7e5ecdf3..c9a176ff17 100644
--- a/drivers/net/gve/gve_ethdev.h
+++ b/drivers/net/gve/gve_ethdev.h
@@ -21,6 +21,7 @@
 #define DQO_TX_MULTIPLIER 4
 
 #define GVE_DEFAULT_MAX_RING_SIZE	1024
+#define GVE_MAX_RING_SIZE_GQ_QPL	2048
 #define GVE_DEFAULT_MIN_RX_RING_SIZE	512
 #define GVE_DEFAULT_MIN_TX_RING_SIZE	256
 
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 8/9] net/gve: don't reset ring size bounds to default on reset
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Jasper Tran O'Leary; +Cc: dev, stable
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

On device reset, GVE skips describe_device functionality, as the device
is not expected to change on a reset. However, before skipping the
describe_device functionality, GVE still sets the ring sizes to their
default values. This effectively removes the ability to create queues
with higher-than-default descriptor counts after a reset.

Fix this behavior by only setting the default ring size bounds is
describe_device is being executed.

Fixes: 1bf64edce3c4 ("net/gve: add reset path")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/gve_ethdev.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/gve/gve_ethdev.c b/drivers/net/gve/gve_ethdev.c
index f73784a109..c990920a4d 100644
--- a/drivers/net/gve/gve_ethdev.c
+++ b/drivers/net/gve/gve_ethdev.c
@@ -1579,12 +1579,12 @@ gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
 		goto free_adminq;
 	}
 
-	/* Set default descriptor counts */
-	gve_set_default_ring_size_bounds(priv);
-
 	if (skip_describe_device)
 		goto setup_device;
 
+	/* Set default descriptor counts */
+	gve_set_default_ring_size_bounds(priv);
+
 	/* Get the initial information we need from the device */
 	err = gve_adminq_describe_device(priv);
 	if (err) {
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 7/9] net/gve: increase range of DMA memzone ids to 64 bits
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Xiaoyun Li, Junfeng Guo,
	Haiyue Wang
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

Long running programs can very easily eclipse this 16-bit range, leading
to name collisions and failed DMA region allocations despite there being
plenty of available memory.

Fixes: c9ba2caf6302 ("net/gve/base: add OS-specific implementation")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/base/gve_osdep.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/gve/base/gve_osdep.h b/drivers/net/gve/base/gve_osdep.h
index c47ce4da85..55629a0e1a 100644
--- a/drivers/net/gve/base/gve_osdep.h
+++ b/drivers/net/gve/base/gve_osdep.h
@@ -175,14 +175,14 @@ struct gve_dma_mem {
 static inline void *
 gve_alloc_dma_mem(struct gve_dma_mem *mem, u64 size)
 {
-	static RTE_ATOMIC(uint16_t) gve_dma_memzone_id;
+	static RTE_ATOMIC(uint64_t) gve_dma_memzone_id;
 	const struct rte_memzone *mz = NULL;
 	char z_name[RTE_MEMZONE_NAMESIZE];
 
 	if (!mem)
 		return NULL;
 
-	snprintf(z_name, sizeof(z_name), "gve_dma_%u",
+	snprintf(z_name, sizeof(z_name), "gve_dma_%" PRIu64,
 		 rte_atomic_fetch_add_explicit(&gve_dma_memzone_id, 1, rte_memory_order_relaxed));
 	mz = rte_memzone_reserve_aligned(z_name, size, SOCKET_ID_ANY,
 					 RTE_MEMZONE_IOVA_CONTIG,
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 6/9] net/gve: free ctx mbuf if packet dropped after first segment
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Rushil Gupta, Junfeng Guo
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

GVE GQ has support for multi-descriptor RX. It is possible for a packet
to be dropped after the first descriptor has been processed an mbuf has
been added to the context. In such a case, the mbuf head should be freed
before clearing the context so that mbufs aren't leaked.

In addition, clear mbuf from sw_ring after adding the packet to the
context to avoid double-freeing buffers that have not been reposted, but
have been reported to the application.

Fixes: 496d4d2c8b54 ("net/gve: support jumbo frame for GQI")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/gve_rx.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/gve/gve_rx.c b/drivers/net/gve/gve_rx.c
index cda87af294..567b82d020 100644
--- a/drivers/net/gve/gve_rx.c
+++ b/drivers/net/gve/gve_rx.c
@@ -205,6 +205,8 @@ gve_rx_burst(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		if (gve_rx(rxq, rxd, rx_id)) {
 			if (!ctx->drop_pkt)
 				rx_pkts[nb_rx++] = ctx->mbuf_head;
+			else if (ctx->mbuf_head != NULL)
+				rte_pktmbuf_free(ctx->mbuf_head);
 			rxq->nb_avail += ctx->total_frags;
 			gve_rx_ctx_clear(ctx);
 		}
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 5/9] net/gve: set mbuf to null in software ring after use
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Junfeng Guo, Xiaoyun Li,
	Rushil Gupta
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

Currently, it is possible for mbufs to be uncleared in the sw_ring after
being returned to the application. This causes an erroneous
dual-ownership over the buffer until GVE cleans the buffer queue and
posts new mbufs, overwriting the older pointers. It is possible in such
a case for a double free to occur while tearing down rings, as both
the application and the driver could attempt to free the same mbuf.
Release ownership of the mbuf from the sw_ring as soon as appropriate to
avoid such a scenario.

Fixes: a46583cf43c8 ("net/gve: support Rx/Tx")
Fixes: 45da16b5b181 ("net/gve: support basic Rx data path for DQO")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/gve_rx.c     | 1 +
 drivers/net/gve/gve_rx_dqo.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/net/gve/gve_rx.c b/drivers/net/gve/gve_rx.c
index 625649cdcf..cda87af294 100644
--- a/drivers/net/gve/gve_rx.c
+++ b/drivers/net/gve/gve_rx.c
@@ -152,6 +152,7 @@ gve_rx(struct gve_rx_queue *rxq, volatile struct gve_rx_desc *rxd, uint16_t rx_i
 
 	rxe = rxq->sw_ring[rx_id];
 	gve_rx_mbuf(rxq, rxe, frag_size, rx_id);
+	rxq->sw_ring[rx_id] = NULL;
 	rxq->stats.bytes += frag_size;
 
 	if (is_first_frag) {
diff --git a/drivers/net/gve/gve_rx_dqo.c b/drivers/net/gve/gve_rx_dqo.c
index c4e2d32067..3665d9e4cd 100644
--- a/drivers/net/gve/gve_rx_dqo.c
+++ b/drivers/net/gve/gve_rx_dqo.c
@@ -207,6 +207,7 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 
 		rxm = rxq->sw_ring[rx_buf_id];
 		gve_completed_buf_list_push(rxq, rx_buf_id);
+		rxq->sw_ring[rx_buf_id] = NULL;
 
 		/* Free buffer and report error. */
 		if (unlikely(rx_desc->rx_error)) {
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 4/9] net/gve: validate buf ID before processing Rx packet
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Ankit Garg
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

The buffer id is part of the RX completion descriptor for packets in the
DQ format. This value can technically go up to 64K, while the max RX
ring size is 4K, meaning that there could similarly be an expected 4K RX
buffer IDs. Validate that the RX buffer ID is valid before attempting to
access it in the sw_ring to prevent a potential out of bounds in the
event of a hardware error.

Fixes: 1aed73b23ac0 ("net/gve: support out-of-order completions on DQ Rx")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/gve_rx_dqo.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/net/gve/gve_rx_dqo.c b/drivers/net/gve/gve_rx_dqo.c
index cc343f3fd8..c4e2d32067 100644
--- a/drivers/net/gve/gve_rx_dqo.c
+++ b/drivers/net/gve/gve_rx_dqo.c
@@ -200,6 +200,11 @@ gve_rx_burst_dqo(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 		}
 
 		rx_buf_id = rte_le_to_cpu_16(rx_desc->buf_id);
+		if (unlikely(rx_buf_id >= rxq->nb_rx_desc)) {
+			PMD_DRV_DP_LOG(ERR, "Invalid buf_id %d", rx_buf_id);
+			continue;
+		}
+
 		rxm = rxq->sw_ring[rx_buf_id];
 		gve_completed_buf_list_push(rxq, rx_buf_id);
 
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 3/9] net/gve: copy data to QPL buffer when mbuf read does not
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Xiaoyun Li, Junfeng Guo
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

The rte_pktmbuf_read method does not guarantee that data will be copied
from an mbuf. If the requested data is all contiguous, the method will
instead return a pointer to the memory location within the buffer that
should be read from, leaving the destination buffer empty.

This is problematic for TSO/multi-segment TX packets which only make use
of two mbufs. If all data in the second mbuf is contiguous, the data
will not be read to QPL memory.

Update the QPL copy logic to copy if the rte_pktmbuf_read does not.

Fixes: a46583cf43c8 ("net/gve: support Rx/Tx")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
v3:
  Fix 32-bit compile issue
v2:
  Removed unused declaration and definition of addr

 drivers/net/gve/gve_tx.c | 38 +++++++++++++++++++++++---------------
 1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/drivers/net/gve/gve_tx.c b/drivers/net/gve/gve_tx.c
index 59c82b04ed..c0400b07bf 100644
--- a/drivers/net/gve/gve_tx.c
+++ b/drivers/net/gve/gve_tx.c
@@ -255,10 +255,10 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 	struct rte_mbuf **sw_ring = txq->sw_ring;
 	uint16_t mask = txq->nb_tx_desc - 1;
 	uint16_t tx_id = txq->tx_tail & mask;
-	uint64_t ol_flags, addr, fifo_addr;
 	uint32_t tx_tail = txq->tx_tail;
 	struct rte_mbuf *tx_pkt, *first;
 	uint16_t sw_id = txq->sw_tail;
+	uint64_t ol_flags, fifo_addr;
 	uint16_t nb_used, i;
 	uint64_t bytes = 0;
 	uint16_t nb_tx = 0;
@@ -273,6 +273,9 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		gve_tx_clean_swr_qpl(txq);
 
 	for (nb_tx = 0; nb_tx < nb_pkts; nb_tx++) {
+		const void *mbuf_header_addr;
+		void *qpl_write_addr;
+
 		tx_pkt = *tx_pkts++;
 		ol_flags = tx_pkt->ol_flags;
 
@@ -306,7 +309,6 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			if (!is_fifo_avail(txq, hlen))
 				goto end_of_tx;
 		}
-		addr = (uint64_t)(tx_pkt->buf_addr) + tx_pkt->data_off;
 		fifo_addr = gve_tx_alloc_from_fifo(txq, tx_id, hlen);
 
 		/* For TSO, check if there's enough fifo space for data first */
@@ -317,26 +319,32 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 					goto end_of_tx;
 			}
 		}
-		if (tx_pkt->nb_segs == 1 || ol_flags & RTE_MBUF_F_TX_TCP_SEG)
-			rte_memcpy((void *)(size_t)(fifo_addr + txq->fifo_base),
-				   (void *)(size_t)addr, hlen);
-		else
-			rte_pktmbuf_read(tx_pkt, 0, hlen,
-					 (void *)(size_t)(fifo_addr + txq->fifo_base));
+
+		qpl_write_addr = (void *)(size_t)(fifo_addr + txq->fifo_base);
+		mbuf_header_addr = rte_pktmbuf_read(tx_pkt, 0, hlen, qpl_write_addr);
+
+		/* Header data is linear in the mbuf head. Copy directly. */
+		if (mbuf_header_addr != qpl_write_addr)
+			rte_memcpy(qpl_write_addr, mbuf_header_addr, hlen);
+
 		gve_tx_fill_pkt_desc(txd, tx_pkt, nb_used, hlen, fifo_addr);
 
 		if (ol_flags & RTE_MBUF_F_TX_TCP_SEG) {
+			const void *mbuf_payload_addr;
+
 			tx_id = (tx_id + 1) & mask;
 			txd = &txr[tx_id];
-			addr = (uint64_t)(tx_pkt->buf_addr) + tx_pkt->data_off + hlen;
 			fifo_addr = gve_tx_alloc_from_fifo(txq, tx_id, tx_pkt->pkt_len - hlen);
-			if (tx_pkt->nb_segs == 1)
-				rte_memcpy((void *)(size_t)(fifo_addr + txq->fifo_base),
-					   (void *)(size_t)addr,
+			qpl_write_addr = (void *)(size_t)(txq->fifo_base + fifo_addr);
+			mbuf_payload_addr = rte_pktmbuf_read(tx_pkt, hlen, tx_pkt->pkt_len - hlen,
+							     qpl_write_addr);
+
+			/* Payload data is contiguous. Take the offset from the
+			 * read request and copy from there.
+			 */
+			if (mbuf_payload_addr != qpl_write_addr)
+				rte_memcpy(qpl_write_addr, mbuf_payload_addr,
 					   tx_pkt->pkt_len - hlen);
-			else
-				rte_pktmbuf_read(tx_pkt, hlen, tx_pkt->pkt_len - hlen,
-						 (void *)(size_t)(fifo_addr + txq->fifo_base));
 
 			gve_tx_fill_seg_desc(txd, ol_flags, tx_offload,
 					     tx_pkt->pkt_len - hlen, fifo_addr);
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related

* [PATCH v3 2/9] net/gve: delay adding mbuf head to software ring
From: Joshua Washington @ 2026-07-07 16:40 UTC (permalink / raw)
  To: Jeroen de Borst, Joshua Washington, Xiaoyun Li, Junfeng Guo
  Cc: dev, stable, Jasper Tran O'Leary
In-Reply-To: <20260707164020.2936476-1-joshwash@google.com>

The GQ TX datapath was set up to write the mbuf head into the sw_ring
before writing the descriptors. This poses a problem because it's
possible for the packet to be dropped due to lacking the FIFO space to
do a proper TX. In such a case, the packet won't be sent, and will lead
to leaked mbufs in the subsequent segments.

There is also no real reason that the head mbuf must be set in the
sw_ring separately from the others; the mbuf chain is not actually
walked as part of GQ TX.

Fixes: a46583cf43c8 ("net/gve: support Rx/Tx")
Cc: stable@dpdk.org
Signed-off-by: Joshua Washington <joshwash@google.com>
Reviewed-by: Jasper Tran O'Leary <jtranoleary@google.com>
---
 drivers/net/gve/gve_tx.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/gve/gve_tx.c b/drivers/net/gve/gve_tx.c
index 5c73c21b8d..59c82b04ed 100644
--- a/drivers/net/gve/gve_tx.c
+++ b/drivers/net/gve/gve_tx.c
@@ -301,7 +301,6 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 			(uint32_t)(tx_offload.l2_len + tx_offload.l3_len + tx_offload.l4_len) :
 			tx_pkt->pkt_len;
 
-		sw_ring[sw_id] = tx_pkt;
 		if (!is_fifo_avail(txq, hlen)) {
 			gve_tx_clean(txq);
 			if (!is_fifo_avail(txq, hlen))
@@ -344,13 +343,14 @@ gve_tx_burst_qpl(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
 		}
 
 		/* record mbuf in sw_ring for free */
-		for (i = 1; i < first->nb_segs; i++) {
+		for (i = 0; i < first->nb_segs; i++) {
+			if (!tx_pkt)
+				break;
+			sw_ring[sw_id] = tx_pkt;
 			sw_id = (sw_id + 1) & mask;
 			tx_pkt = tx_pkt->next;
-			sw_ring[sw_id] = tx_pkt;
 		}
 
-		sw_id = (sw_id + 1) & mask;
 		tx_id = (tx_id + 1) & mask;
 
 		txq->nb_free -= nb_used;
-- 
2.55.0.rc2.803.g1fd1e6609c-goog


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox