Skip to contentSkip to conversation

pktmbuf free bulk cleanups

PATCH NAK Stephen Hemminger 3 participants 26 messages May 8 – May 11 Network drivers

lore
Share & tools
lore
#0 lore raw

cover pktmbuf free bulk cleanups

Looking at one driver noticed that rte_pktmbuf_free_bulk was not being used. That motivated me to make a coccinelle script to do a tree wide cleanup.

Then noticed that callers were having to check for NULL before calling rte_pktmbuf_free_bulk, so changed it to handle NULL array similar to free() and rte_free().

Do another tree wide pass to fix that and catch some other unnecessary null checks in code.

Stephen Hemminger (20):
devtools/cocci: add transform for rte_pktmbuf_free_bulk
eventdev: use rte_pktmbuf_free_bulk
gso: use rte_pktmbuf_free_bulk
ip_frag: use rte_pktmbuf_free_bulk
pipeline: use rte_pktmbuf_free_bulk
port: use rte_pktmbuf_free_bulk
net/af_xdp: use rte_pktmbuf_free_bulk net/cnxk: use rte_pktmbuf_free_bulk
net/pfe: use rte_pktmbuf_free_bulk
net/virtio: use rte_pktmbuf_free_bulk net/zxdh: use rte_pktmbuf_free_bulk app/compress-perf: use rte_pktmbuf_free_bulk
mbuf: allow NULL array in rte_pktmbuf_free_bulk net/zxdh: remove unnecessary null check net/ice: remove unnecessary null check net/bnxt: remove unnecessary null check
test: use rte_pktmbuf_free_bulk app/test-dma-perf: remove unnecessary null check app/test-compress-perf: remove unnecessary null check
examples: use rte_pktmbuf_free_bulk

 .../comp_perf_test_common.c                   |  8 +--
 app/test-compress-perf/main.c                 |  6 +-
 app/test-dma-perf/benchmark.c                 |  6 +-
 app/test/sample_packet_forward.c              |  5 +-
 app/test/test_distributor.c                   |  4 +-
 app/test/test_dmadev.c                        |  6 +-
 app/test/test_ipfrag.c                        |  4 +-
 app/test/test_link_bonding.c                  | 13 ++---
 app/test/test_pmd_perf.c                      |  3 +-
 app/test/test_pmd_tap.c                       |  3 +-
 app/test/test_reorder.c                       | 12 ++--
 app/test/test_table_ports.c                   | 12 ++--
 app/test/test_table_tables.c                  | 21 +++----
 devtools/cocci/free_bulk.cocci                | 57 +++++++++++++++++++
 devtools/cocci/nullfree.cocci                 |  5 +-
 doc/guides/rel_notes/release_26_07.rst        |  5 ++
 drivers/net/af_xdp/rte_eth_af_xdp.c           |  3 +-
 drivers/net/bnxt/tf_core/v3/tfo.c             |  6 +-
 drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c          |  6 +-
 drivers/net/cnxk/cnxk_ethdev.c                |  5 +-
 drivers/net/intel/ice/ice_dcf_sched.c         |  6 +-
 drivers/net/pfe/pfe_ethdev.c                  |  4 +-
 drivers/net/virtio/virtio_rxtx.c              | 20 +++----
 drivers/net/zxdh/zxdh_np.c                    |  3 +-
 drivers/net/zxdh/zxdh_queue.c                 |  7 +--
 drivers/net/zxdh/zxdh_rxtx.c                  |  3 +-
 examples/bbdev_app/main.c                     |  4 +-
 examples/l2fwd-crypto/main.c                  |  4 +-
 .../client_server_mp/mp_client/client.c       |  7 +--
 .../client_server_mp/mp_server/main.c         |  5 +-
 examples/ntb/ntb_fwd.c                        | 12 ++--
 examples/packet_ordering/main.c               |  5 +-
 examples/server_node_efd/efd_node/node.c      |  7 +--
 examples/server_node_efd/efd_server/main.c    |  5 +-
 examples/vhost/main.c                         |  3 +-
 lib/eventdev/rte_event_eth_tx_adapter.c       |  4 +-
 lib/gso/gso_common.c                          |  5 +-
 lib/ip_frag/rte_ipv6_fragmentation.c          |  4 +-
 lib/mbuf/rte_mbuf.c                           |  3 +
 lib/mbuf/rte_mbuf.h                           |  1 +
 lib/pipeline/rte_pipeline.c                   |  4 +-
 lib/port/rte_port_fd.c                        |  6 +-
 lib/port/rte_swx_port_fd.c                    |  8 +--
 lib/port/rte_swx_port_source_sink.c           |  6 +-
 44 files changed, 152 insertions(+), 174 deletions(-)
 create mode 100644 devtools/cocci/free_bulk.cocci
Signature · 1 line
2.53.0
#1 lore raw

PATCH 1/20 devtools/cocci: add transform for rte_pktmbuf_free_bulk

Convert simple loops freeing mbufs one at a time into a single rte_pktmbuf_free_bulk() call.

---
 devtools/cocci/free_bulk.cocci | 57 ++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)
 create mode 100644 devtools/cocci/free_bulk.cocci
devtools/cocci/free_bulk.cocci new file +57 -0
new file mode 100644
index 0000000000..51ce58400a
@@ -0,0 +1,57 @@
+//
+// Replace simple loops freeing mbufs one-by-one with rte_pktmbuf_free_bulk().
+//
+// rte_pktmbuf_free_bulk() handles NULL entries internally, so per-element
+// NULL guards are folded in as well.  Loops whose body does more than the
+// free (clearing the slot, bookkeeping, etc.) are not matched.
+//
+@@
+expression A, N;
+identifier i;
+@@
+
+(
+- for (i = 0; i < N; i++)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; ++i)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; i++)
+-     if (A[i] != NULL)
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (i = 0; i < N; i++)
+-     if (A[i])
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+)
+
+@@
+expression A, N;
+identifier i;
+type T;
+@@
+
+(
+- for (T i = 0; i < N; i++)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; ++i)
+-     rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; i++)
+-     if (A[i] != NULL)
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+|
+- for (T i = 0; i < N; i++)
+-     if (A[i])
+-         rte_pktmbuf_free(A[i]);
++ rte_pktmbuf_free_bulk(A, N);
+)
Signature · 1 line
2.53.0
#2 lore raw

PATCH 2/20 eventdev: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 lib/eventdev/rte_event_eth_tx_adapter.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
lib/eventdev/rte_event_eth_tx_adapter.c +1 -3
index 91c7be55c7..2de96a02c2 100644
@@ -914,12 +914,10 @@ static inline void
 txa_txq_buffer_drain(struct txa_service_queue_info *tqi)
 {
 	struct rte_eth_dev_tx_buffer *b;
-	uint16_t i;
 
 	b = tqi->tx_buf;
 
-	for (i = 0; i < b->length; i++)
-		rte_pktmbuf_free(b->pkts[i]);
+	rte_pktmbuf_free_bulk(b->pkts, b->length);
 
 	b->length = 0;
 }
Signature · 1 line
2.53.0
#3 lore raw

PATCH 3/20 gso: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 lib/gso/gso_common.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
lib/gso/gso_common.c +1 -4
index 378bf2c6aa..6ccaa7103a 100644
@@ -31,10 +31,7 @@ hdr_segment_init(struct rte_mbuf *hdr_segment, struct rte_mbuf *pkt,
 static inline void
 free_gso_segment(struct rte_mbuf **pkts, uint16_t nb_pkts)
 {
-	uint16_t i;
-
-	for (i = 0; i < nb_pkts; i++)
-		rte_pktmbuf_free(pkts[i]);
+	rte_pktmbuf_free_bulk(pkts, nb_pkts);
 }
 
 int
Signature · 1 line
2.53.0
#4 lore raw

PATCH 4/20 ip_frag: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 lib/ip_frag/rte_ipv6_fragmentation.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
lib/ip_frag/rte_ipv6_fragmentation.c +1 -3
index c81f2402e3..4d8fb05233 100644
@@ -38,9 +38,7 @@ __fill_ipv6hdr_frag(struct rte_ipv6_hdr *dst,
 static inline void
 __free_fragments(struct rte_mbuf *mb[], uint32_t num)
 {
-	uint32_t i;
-	for (i = 0; i < num; i++)
-		rte_pktmbuf_free(mb[i]);
+	rte_pktmbuf_free_bulk(mb, num);
 }
 
 /**
Signature · 1 line
2.53.0
#5 lore raw

PATCH 5/20 pipeline: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 lib/pipeline/rte_pipeline.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
lib/pipeline/rte_pipeline.c +1 -3
index fa3c8b77ee..1fadae01d8 100644
@@ -1305,10 +1305,8 @@ rte_pipeline_action_handler_drop(struct rte_pipeline *p, uint64_t pkts_mask)
 {
 	if ((pkts_mask & (pkts_mask + 1)) == 0) {
 		uint64_t n_pkts = rte_popcount64(pkts_mask);
-		uint32_t i;
 
-		for (i = 0; i < n_pkts; i++)
-			rte_pktmbuf_free(p->pkts[i]);
+		rte_pktmbuf_free_bulk(p->pkts, n_pkts);
 	} else {
 		uint32_t i;
 
Signature · 1 line
2.53.0
#6 lore raw

PATCH 6/20 port: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 lib/port/rte_port_fd.c              | 6 ++----
 lib/port/rte_swx_port_fd.c          | 8 ++------
 lib/port/rte_swx_port_source_sink.c | 6 +-----
 3 files changed, 5 insertions(+), 15 deletions(-)
lib/port/rte_port_fd.c +2 -4
index dbc9efef1b..2b021710d4 100644
@@ -212,8 +212,7 @@ send_burst(struct rte_port_fd_writer *p)
 
 	RTE_PORT_FD_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - i);
 
-	for (i = 0; i < p->tx_buf_count; i++)
-		rte_pktmbuf_free(p->tx_buf[i]);
+	rte_pktmbuf_free_bulk(p->tx_buf, p->tx_buf_count);
 
 	p->tx_buf_count = 0;
 }
@@ -397,8 +396,7 @@ send_burst_nodrop(struct rte_port_fd_writer_nodrop *p)
 
 	RTE_PORT_FD_WRITER_NODROP_STATS_PKTS_DROP_ADD(p, p->tx_buf_count - i);
 
-	for (i = 0; i < p->tx_buf_count; i++)
-		rte_pktmbuf_free(p->tx_buf[i]);
+	rte_pktmbuf_free_bulk(p->tx_buf, p->tx_buf_count);
 
 	p->tx_buf_count = 0;
 }
lib/port/rte_swx_port_fd.c +2 -6
index 72783d2b0f..937b1e0945 100644
@@ -73,14 +73,11 @@ static void
 reader_free(void *port)
 {
 	struct reader *p = port;
-	uint32_t i;
 
 	if (!p)
 		return;
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
-
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 	free(p->pkts);
 	free(p);
 }
@@ -218,8 +215,7 @@ __writer_flush(struct writer *p)
 		(uint32_t)p->params.fd,
 		p->n_pkts);
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 
 	p->n_pkts = 0;
 }
lib/port/rte_swx_port_source_sink.c +1 -5
index af8b9ec68d..f651d5b5ad 100644
@@ -52,16 +52,12 @@ static void
 source_free(void *port)
 {
 	struct source *p = port;
-	uint32_t i;
 
 	if (!p)
 		return;
 
-	for (i = 0; i < p->n_pkts; i++)
-		rte_pktmbuf_free(p->pkts[i]);
-
+	rte_pktmbuf_free_bulk(p->pkts, p->n_pkts);
 	free(p->pkts);
-
 	free(p);
 }
 
Signature · 1 line
2.53.0
#7 lore raw

PATCH 7/20 net/af_xdp: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 drivers/net/af_xdp/rte_eth_af_xdp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/af_xdp/rte_eth_af_xdp.c +1 -2
index 10dbcf1333..4f55887963 100644
@@ -263,8 +263,7 @@ reserve_fill_queue_zc(struct xsk_umem_info *umem, uint16_t reserve_size,
 	uint16_t i;
 
 	if (unlikely(!xsk_ring_prod__reserve(fq, reserve_size, &idx))) {
-		for (i = 0; i < reserve_size; i++)
-			rte_pktmbuf_free(bufs[i]);
+		rte_pktmbuf_free_bulk(bufs, reserve_size);
 		AF_XDP_LOG_LINE(DEBUG, "Failed to reserve enough fq descs.");
 		return -1;
 	}
Signature · 1 line
2.53.0
#8 lore raw

PATCH 8/20 net/cnxk: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 drivers/net/cnxk/cnxk_ethdev.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/net/cnxk/cnxk_ethdev.c +2 -3
index 06d1c9b362..3330dd5051 100644
@@ -1913,7 +1913,7 @@ cnxk_nix_dev_stop(struct rte_eth_dev *eth_dev)
 	const struct eth_dev_ops *dev_ops = eth_dev->dev_ops;
 	struct rte_mbuf *rx_pkts[32];
 	struct rte_eth_link link;
-	int count, i, j, rc;
+	int count, i, rc;
 	void *rxq;
 
 	/* In case of Inline IPSec, will need to avoid disabling the MCAM rules and NPC Rx
@@ -1951,8 +1951,7 @@ cnxk_nix_dev_stop(struct rte_eth_dev *eth_dev)
 		rxq = eth_dev->data->rx_queues[i];
 		count = dev->rx_pkt_burst_no_offload(rxq, rx_pkts, 32);
 		while (count) {
-			for (j = 0; j < count; j++)
-				rte_pktmbuf_free(rx_pkts[j]);
+			rte_pktmbuf_free_bulk(rx_pkts, count);
 			count = dev->rx_pkt_burst_no_offload(rxq, rx_pkts, 32);
 		}
 	}
Signature · 1 line
2.53.0
#9 lore raw

PATCH 9/20 net/pfe: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 drivers/net/pfe/pfe_ethdev.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/net/pfe/pfe_ethdev.c +1 -3
index 1efa17539e..4c0f9e63a0 100644
@@ -281,9 +281,7 @@ pfe_eth_open(struct rte_eth_dev *dev)
 			ret = hif_lib_receive_pkt(&client->rx_q[0],
 						  hif_shm->pool, rx_pkts, 32);
 			while (ret) {
-				int i;
-				for (i = 0; i < ret; i++)
-					rte_pktmbuf_free(rx_pkts[i]);
+				rte_pktmbuf_free_bulk(rx_pkts, ret);
 				ret = hif_lib_receive_pkt(&client->rx_q[0],
 							  hif_shm->pool,
 							  rx_pkts, 32);
Signature · 1 line
2.53.0
#10 lore raw

PATCH 10/20 net/virtio: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 drivers/net/virtio/virtio_rxtx.c | 20 +++++++-------------
 1 file changed, 7 insertions(+), 13 deletions(-)
drivers/net/virtio/virtio_rxtx.c +7 -13
index edecd2011f..a1fbdd9f34 100644
@@ -723,7 +723,7 @@ virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_idx)
 	struct virtnet_rx *rxvq = &vq->rxq;
 	struct rte_mbuf *m;
 	uint16_t desc_idx;
-	int error, nbufs, i;
+	int error, nbufs;
 	bool in_order = virtio_with_feature(hw, VIRTIO_F_IN_ORDER);
 
 	PMD_INIT_FUNC_TRACE();
@@ -764,8 +764,7 @@ virtio_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_idx)
 						pkts,
 						free_cnt);
 				if (unlikely(error)) {
-					for (i = 0; i < free_cnt; i++)
-						rte_pktmbuf_free(pkts[i]);
+					rte_pktmbuf_free_bulk(pkts, free_cnt);
 				} else {
 					nbufs += free_cnt;
 				}
@@ -1071,8 +1070,7 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
 			error = virtqueue_enqueue_recv_refill(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1176,8 +1174,7 @@ virtio_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
 			error = virtqueue_enqueue_recv_refill_packed(vq,
 					new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1358,8 +1355,7 @@ virtio_recv_pkts_inorder(void *rx_queue,
 			error = virtqueue_enqueue_refill_inorder(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1535,8 +1531,7 @@ virtio_recv_mergeable_pkts(void *rx_queue,
 			error = virtqueue_enqueue_recv_refill(vq, new_pkts,
 					free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
@@ -1707,8 +1702,7 @@ virtio_recv_mergeable_pkts_packed(void *rx_queue,
 			error = virtqueue_enqueue_recv_refill_packed(vq,
 					new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 			nb_enqueued += free_cnt;
 		} else {
Signature · 1 line
2.53.0
#11 lore raw

PATCH 11/20 net/zxdh: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 drivers/net/zxdh/zxdh_queue.c | 7 ++-----
 drivers/net/zxdh/zxdh_rxtx.c  | 3 +--
 2 files changed, 3 insertions(+), 7 deletions(-)
drivers/net/zxdh/zxdh_queue.c +2 -5
index 7162593b16..543f626e6f 100644
@@ -445,11 +445,8 @@ int32_t zxdh_dev_rx_queue_setup_finish(struct rte_eth_dev *dev, uint16_t queue_i
 
 		if (likely(rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt) == 0)) {
 			error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
-			if (unlikely(error)) {
-				int32_t i;
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
-			}
+			if (unlikely(error))
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 		} else {
 			PMD_DRV_LOG(ERR, "port %d rxq %d allocated bufs from %s failed",
 				hw->port_id, logic_qidx, rxvq->mpool->name);
drivers/net/zxdh/zxdh_rxtx.c +1 -2
index db86922aea..cb324336d0 100644
@@ -970,8 +970,7 @@ zxdh_recv_pkts_packed(void *rx_queue, struct rte_mbuf **rx_pkts,
 		if (!rte_pktmbuf_alloc_bulk(rxvq->mpool, new_pkts, free_cnt)) {
 			error = zxdh_enqueue_recv_refill_packed(vq, new_pkts, free_cnt);
 			if (unlikely(error)) {
-				for (i = 0; i < free_cnt; i++)
-					rte_pktmbuf_free(new_pkts[i]);
+				rte_pktmbuf_free_bulk(new_pkts, free_cnt);
 			}
 
 			if (unlikely(zxdh_queue_kick_prepare_packed(vq)))
Signature · 1 line
2.53.0
#12 lore raw

PATCH 12/20 app/compress-perf: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 app/test-compress-perf/comp_perf_test_common.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
app/test-compress-perf/comp_perf_test_common.c +2 -4
index 78487196ad..12c2a7bbd0 100644
@@ -84,12 +84,10 @@ comp_perf_free_memory(struct comp_test_data *test_data,
 	uint32_t i;
 
 	if (mem->decomp_bufs != NULL)
-		for (i = 0; i < mem->total_bufs; i++)
-			rte_pktmbuf_free(mem->decomp_bufs[i]);
+		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
 	if (mem->comp_bufs != NULL)
-		for (i = 0; i < mem->total_bufs; i++)
-			rte_pktmbuf_free(mem->comp_bufs[i]);
+		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 
 	rte_free(mem->decomp_bufs);
 	rte_free(mem->comp_bufs);
Signature · 1 line
2.53.0
#13 lore raw

PATCH 13/20 mbuf: allow NULL array in rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

This allows callers to avoid NULL checks and just call rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

---
 devtools/cocci/nullfree.cocci          | 5 ++++-
 doc/guides/rel_notes/release_26_07.rst | 5 +++++
 lib/mbuf/rte_mbuf.c                    | 3 +++
 lib/mbuf/rte_mbuf.h                    | 1 +
 4 files changed, 13 insertions(+), 1 deletion(-)
devtools/cocci/nullfree.cocci +4 -1
index e7417b69ff..78e30f730a 100644
@@ -4,7 +4,7 @@
 // free(NULL) as a no-op.
 //
 @@
-expression E;
+expression E, N;
 @@
 (
 - if (E != NULL) cmdline_free(E);
@@ -79,6 +79,9 @@ expression E;
 - if (E != NULL) rte_pktmbuf_free(E);
 + rte_pktmbuf_free(E);
 |
+- if (E != NULL) rte_pktmbuf_free_bulk(E, N);
++ rte_pktmbuf_free_bulk(E, N);
+|
 - if (E != NULL) rte_rib_free(E);
 + rte_rib_free(E);
 |
doc/guides/rel_notes/release_26_07.rst +5 -0
index f012d47a4b..6f2f7f849f 100644
@@ -63,6 +63,11 @@ New Features
     ``rte_eal_init`` and the application is responsible for probing each device,
   * ``--auto-probing`` enables the initial bus probing, which is the current default behavior.
 
+* **mbuf: rte_pktmbuf_free_bulk now accepts NULL array pointer.**
+
+  Calling ``rte_pktmbuf_free_bulk`` with a NULL ``mbufs`` argument  is a no-op,
+  matching the behavior of ``rte_pktmbuf_free()`` and ``rte_free()``.
+
 
 Removed Items
 -------------
lib/mbuf/rte_mbuf.c +3 -0
index c2476e7704..8ec3bb53bb 100644
@@ -562,6 +562,9 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int count)
 	struct rte_mbuf *m, *m_next, *pending[RTE_PKTMBUF_FREE_PENDING_SZ];
 	unsigned int idx, nb_pending = 0;
 
+	if (mbufs == NULL)
+		return;
+
 	rte_mbuf_history_mark_bulk(mbufs, count, RTE_MBUF_HISTORY_OP_LIB_FREE);
 
 	for (idx = 0; idx < count; idx++) {
lib/mbuf/rte_mbuf.h +1 -0
index e7c3bbadd4..e9f8932e80 100644
@@ -1534,6 +1534,7 @@ static inline void rte_pktmbuf_free(struct rte_mbuf *m)
  *  @param mbufs
  *    Array of pointers to packet mbufs.
  *    The array may contain NULL pointers.
+ *    The array pointer is NULL function does nothing.
  *  @param count
  *    Array size.
  */
Signature · 1 line
2.53.0
#14 lore raw

RE: [PATCH 13/20] mbuf: allow NULL array in rte_pktmbuf_free_bulk

Quoted 7 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Friday, 8 May 2026 22.34

This allows callers to avoid NULL checks and just call rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

I disagree with this patch.

The parameter is an array of (pointers to) mbufs.
We already accept that the array can contain NULL pointers (no mbuf present).
This is extremely forgiving, considering that other fast path functions don't allow NULL pointers in arrays; e.g. rte_eth_tx_burst(), rte_mempool_put_bulk().
But since it's a "free()" class of function, I don't object to it.

However, this patch changes the parameter type from "array" to "array or NULL (no array present)". And I don't think we should change the parameter type; it should remain "array" only.

If there are any scenarios where a non-present array (NULL) is passed to the function, the count should be zero too. And when the count is zero, the function does not dereference the array, so explicitly checking for NULL is superfluous.

We have a convention of not checking parameter validity in fast path functions. And I consider it invalid parameters passing NULL with a non-zero count.

You might argue that this is a "free()" class of function, which warrants checking for NULL; but since it already accepts NULL with zero count, it is already covered.

We could change the function declaration for clarity:

void rte_pktmbuf_free_bulk(

		unsigned int count;
		struct rte_mbuf *mbufs[count], unsigned int count);

Or add a debug assertion at the start of the function:
RTE_ASSERT(mbufs != NULL || count == 0);

Quoted 83 lines
---
 devtools/cocci/nullfree.cocci          | 5 ++++-
 doc/guides/rel_notes/release_26_07.rst | 5 +++++
 lib/mbuf/rte_mbuf.c                    | 3 +++
 lib/mbuf/rte_mbuf.h                    | 1 +
 4 files changed, 13 insertions(+), 1 deletion(-)
devtools/cocci/nullfree.cocci +4 -1
index e7417b69ff..78e30f730a 100644
@@ -4,7 +4,7 @@
 // free(NULL) as a no-op.
 //
 @@
-expression E;
+expression E, N;
 @@
 (
 - if (E != NULL) cmdline_free(E);
@@ -79,6 +79,9 @@ expression E;
 - if (E != NULL) rte_pktmbuf_free(E);
 + rte_pktmbuf_free(E);
 |
+- if (E != NULL) rte_pktmbuf_free_bulk(E, N);
++ rte_pktmbuf_free_bulk(E, N);
+|
 - if (E != NULL) rte_rib_free(E);
 + rte_rib_free(E);
 |
doc/guides/rel_notes/release_26_07.rst +0 -0
index f012d47a4b..6f2f7f849f 100644
@@ -63,6 +63,11 @@ New Features
     ``rte_eal_init`` and the application is responsible for probing
 each device,
   * ``--auto-probing`` enables the initial bus probing, which is the

current default behavior.

doc/guides/rel_notes/release_26_07.rst +3 -0
+* **mbuf: rte_pktmbuf_free_bulk now accepts NULL array pointer.**
+
+  Calling ``rte_pktmbuf_free_bulk`` with a NULL ``mbufs`` argument  is

a no-op,

doc/guides/rel_notes/release_26_07.rst +2 -0
+  matching the behavior of ``rte_pktmbuf_free()`` and ``rte_free()``.
+
 
 Removed Items
 -------------
lib/mbuf/rte_mbuf.c +3 -0
index c2476e7704..8ec3bb53bb 100644
@@ -562,6 +562,9 @@ void rte_pktmbuf_free_bulk(struct rte_mbuf **mbufs,
 unsigned int count)
 	struct rte_mbuf *m, *m_next,
 *pending[RTE_PKTMBUF_FREE_PENDING_SZ];
 	unsigned int idx, nb_pending = 0;
 
+	if (mbufs == NULL)
+		return;
+
 	rte_mbuf_history_mark_bulk(mbufs, count,

RTE_MBUF_HISTORY_OP_LIB_FREE);

lib/mbuf/rte_mbuf.c +0 -0
 	for (idx = 0; idx < count; idx++) {
lib/mbuf/rte_mbuf.h +1 -0
index e7c3bbadd4..e9f8932e80 100644
@@ -1534,6 +1534,7 @@ static inline void rte_pktmbuf_free(struct
 rte_mbuf *m)
  *  @param mbufs
  *    Array of pointers to packet mbufs.
  *    The array may contain NULL pointers.
+ *    The array pointer is NULL function does nothing.
  *  @param count
  *    Array size.

*/
--
2.53.0

#15 lore raw

Re: [PATCH 13/20] mbuf: allow NULL array in rte_pktmbuf_free_bulk

Quoted 27 lines · On Sat, 9 May 2026 10:47:53 +0200 Morten Brørup <[email protected]>…
Quoted 7 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Friday, 8 May 2026 22.34

This allows callers to avoid NULL checks and just call rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

I disagree with this patch.

The parameter is an array of (pointers to) mbufs.
We already accept that the array can contain NULL pointers (no mbuf present).
This is extremely forgiving, considering that other fast path functions don't allow NULL pointers in arrays; e.g. rte_eth_tx_burst(), rte_mempool_put_bulk().
But since it's a "free()" class of function, I don't object to it.

However, this patch changes the parameter type from "array" to "array or NULL (no array present)". And I don't think we should change the parameter type; it should remain "array" only.

If there are any scenarios where a non-present array (NULL) is passed to the function, the count should be zero too. And when the count is zero, the function does not dereference the array, so explicitly checking for NULL is superfluous.

We have a convention of not checking parameter validity in fast path functions. And I consider it invalid parameters passing NULL with a non-zero count.

You might argue that this is a "free()" class of function, which warrants checking for NULL; but since it already accepts NULL with zero count, it is already covered.

Quoted 8 lines

We could change the function declaration for clarity:

void rte_pktmbuf_free_bulk(

		unsigned int count;
		struct rte_mbuf *mbufs[count], unsigned int count);

Or add a debug assertion at the start of the function:
RTE_ASSERT(mbufs != NULL || count == 0);

Ok, it was more motivated by common pattern in driver cleanup paths like:

app/test-compress-perf/comp_perf_test_common.c +2 -4
@@ -83,11 +83,9 @@ comp_perf_free_memory(struct comp_test_data *test_data,
 {
 	uint32_t i;
 
-	if (mem->decomp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
-	if (mem->comp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 
#16 lore raw

RE: [PATCH 13/20] mbuf: allow NULL array in rte_pktmbuf_free_bulk

Quoted 60 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Saturday, 9 May 2026 17.47

Quoted 6 lines · On Sat, 9 May 2026 10:47:53 +0200 Morten Brørup <[email protected]>…
Quoted 6 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Friday, 8 May 2026 22.34

This allows callers to avoid NULL checks and just call rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

Quoted 6 lines
Quoted 1 line

I disagree with this patch.

The parameter is an array of (pointers to) mbufs.
We already accept that the array can contain NULL pointers (no mbuf

present).

Quoted 1 line

This is extremely forgiving, considering that other fast path

functions don't allow NULL pointers in arrays;

Quoted 4 lines

e.g. rte_eth_tx_burst(), rte_mempool_put_bulk().
But since it's a "free()" class of function, I don't object to it.

However, this patch changes the parameter type from "array" to "array

or NULL (no array present)".

Quoted 1 line

And I don't think we should change the parameter type; it should

remain "array" only.

Quoted 2 lines

If there are any scenarios where a non-present array (NULL) is passed

to the function, the count should be zero too.

Quoted 1 line

And when the count is zero, the function does not dereference the

array, so explicitly checking for NULL is superfluous.

Quoted 2 lines

We have a convention of not checking parameter validity in fast path

functions.

Quoted 1 line

And I consider it invalid parameters passing NULL with a non-zero

count.

Quoted 2 lines

You might argue that this is a "free()" class of function, which

warrants checking for NULL; but since it already accepts NULL with zero count, it is already covered.

Quoted 9 lines

We could change the function declaration for clarity:

void rte_pktmbuf_free_bulk(

		unsigned int count;
		struct rte_mbuf *mbufs[count], unsigned int count);

Or add a debug assertion at the start of the function:
RTE_ASSERT(mbufs != NULL || count == 0);

Ok, it was more motivated by common pattern in driver cleanup paths like:

app/test-compress-perf/comp_perf_test_common.c +0 -0
@@ -83,11 +83,9 @@ comp_perf_free_memory(struct comp_test_data
 *test_data,
 {

app/test-compress-perf/comp_perf_test_common.c comp_perf_free_memory(struct comp_test_data · line 90

Quoted 10 lines
app/test-compress-perf/comp_perf_test_common.c +2 -4
 	uint32_t i;
 
-	if (mem->decomp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
-	if (mem->comp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 

Skimming comp_perf_test_common.c, it looks like mem->total_bufs is initialized to the number of wanted buffers, and then mem->decomp_bufs is set up afterwards. In other words, total_bufs can be non-zero while comp_bufs is NULL.

IMO, removing the NULL comparison here would pass invalid parameters to rte_pktmbuf_free_bulk().

Train of thoughts...

On the other hand, it does provide a good example where considering rte_pktmbuf_free_bulk() a "free()" class function accepting a NULL pointer would be helpful. And the added performance cost of checking for a NULL pointer is per burst, not per packet.
I'm not as strongly opposed as I was initially.

However, looking at it in a broader scope gets me be back to being opposed:
This patch is for freeing mbufs.
If we consider freeing mempool objects, the cleanup function would call rte_mempool_put_bulk() to free the objects, which is the function for freeing previously allocated mempool objects. It just happens to not have "free" as part of its name.

The mempool single object "free()" function, rte_mempool_put(), doesn't accept a NULL pointer. Similarly, the mempool bulk free function, rte_mempool_put_bulk(), doesn't accept holes (NULL pointers) in the array. I certainly do not want to introduce holes into mempool object arrays.

Maybe it was a bad decision to allow holes in mbuf arrays being passed to rte_pktmbuf_free_bulk(). Such holes are not accepted in any other DPDK APIs.

At this point, I'm still not in favor of this patch.
It's defensive coding (with a performance cost, however small) in a fast path function.

#17 lore raw

Re: [PATCH 13/20] mbuf: allow NULL array in rte_pktmbuf_free_bulk

Quoted 85 lines · On Sun, 10 May 2026 14:31:57 +0200 Morten Brørup <[email protected]>…
Quoted 60 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Saturday, 9 May 2026 17.47

Quoted 6 lines · On Sat, 9 May 2026 10:47:53 +0200 Morten Brørup <[email protected]>…
Quoted 6 lines

From: Stephen Hemminger [mailto:[email protected]]
Sent: Friday, 8 May 2026 22.34

This allows callers to avoid NULL checks and just call rte_pktmbuf_free_bulk, similar to rte_pktmbuf_free.

Quoted 6 lines
Quoted 1 line

I disagree with this patch.

The parameter is an array of (pointers to) mbufs.
We already accept that the array can contain NULL pointers (no mbuf

present).

Quoted 1 line

This is extremely forgiving, considering that other fast path

functions don't allow NULL pointers in arrays;

Quoted 4 lines

e.g. rte_eth_tx_burst(), rte_mempool_put_bulk().
But since it's a "free()" class of function, I don't object to it.

However, this patch changes the parameter type from "array" to "array

or NULL (no array present)".

Quoted 1 line

And I don't think we should change the parameter type; it should

remain "array" only.

Quoted 2 lines

If there are any scenarios where a non-present array (NULL) is passed

to the function, the count should be zero too.

Quoted 1 line

And when the count is zero, the function does not dereference the

array, so explicitly checking for NULL is superfluous.

Quoted 2 lines

We have a convention of not checking parameter validity in fast path

functions.

Quoted 1 line

And I consider it invalid parameters passing NULL with a non-zero

count.

Quoted 2 lines

You might argue that this is a "free()" class of function, which

warrants checking for NULL; but since it already accepts NULL with zero count, it is already covered.

Quoted 9 lines

We could change the function declaration for clarity:

void rte_pktmbuf_free_bulk(

		unsigned int count;
		struct rte_mbuf *mbufs[count], unsigned int count);

Or add a debug assertion at the start of the function:
RTE_ASSERT(mbufs != NULL || count == 0);

Ok, it was more motivated by common pattern in driver cleanup paths like:

app/test-compress-perf/comp_perf_test_common.c +0 -0
@@ -83,11 +83,9 @@ comp_perf_free_memory(struct comp_test_data
 *test_data,
 {

app/test-compress-perf/comp_perf_test_common.c comp_perf_free_memory(struct comp_test_data · line 90

Quoted 10 lines
app/test-compress-perf/comp_perf_test_common.c +2 -4
 	uint32_t i;
 
-	if (mem->decomp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
-	if (mem->comp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 

Skimming comp_perf_test_common.c, it looks like mem->total_bufs is initialized to the number of wanted buffers, and then mem->decomp_bufs is set up afterwards. In other words, total_bufs can be non-zero while comp_bufs is NULL.

IMO, removing the NULL comparison here would pass invalid parameters to rte_pktmbuf_free_bulk().

Train of thoughts...

On the other hand, it does provide a good example where considering rte_pktmbuf_free_bulk() a "free()" class function accepting a NULL pointer would be helpful. And the added performance cost of checking for a NULL pointer is per burst, not per packet.
I'm not as strongly opposed as I was initially.

However, looking at it in a broader scope gets me be back to being opposed:
This patch is for freeing mbufs.
If we consider freeing mempool objects, the cleanup function would call rte_mempool_put_bulk() to free the objects, which is the function for freeing previously allocated mempool objects. It just happens to not have "free" as part of its name.

Quoted 9 lines

The mempool single object "free()" function, rte_mempool_put(), doesn't accept a NULL pointer. Similarly, the mempool bulk free function, rte_mempool_put_bulk(), doesn't accept holes (NULL pointers) in the array. I certainly do not want to introduce holes into mempool object arrays.

Maybe it was a bad decision to allow holes in mbuf arrays being passed to rte_pktmbuf_free_bulk(). Such holes are not accepted in any other DPDK APIs.

At this point, I'm still not in favor of this patch.
It's defensive coding (with a performance cost, however small) in a fast path function.

More thoughts.
- allowing NULL array is not worth it; not a big win, and only one place mattered

- allowing holes in array seems odd, and not that useful. Probably can't change now. Not sure why callers would need it.

- Probably should add RTE_ASSERT() into free bulk. Should allow rte_pktmbuf_free_bulk(NULL, 0) for consistency with some other API's that take array and count. But assert should trigger on rte_pktmbuf_free_bulk(NULL, 1)

#18 lore raw

PATCH 14/20 net/zxdh: remove unnecessary null check

In reply to Stephen Hemminger

Remove unnecessary if check before calling free.

Generated by devtools/cocci/null_free.cocci

---
 drivers/net/zxdh/zxdh_np.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/zxdh/zxdh_np.c +1 -2
index efb57e34f2..b078ec5b6c 100644
@@ -12383,8 +12383,7 @@ zxdh_np_dtb_acl_data_clear(uint32_t dev_id, uint32_t queue_id,
 				&element_id);
 	free(data_buff);
 	free(mask_buff);
-	if (eram_buff)
-		free(eram_buff);
+	free(eram_buff);
 
 	free(p_entry_arr);
 	ZXDH_COMM_CHECK_DEV_RC(dev_id, rc, "zxdh_np_dtb_acl_dma_insert");
Signature · 1 line
2.53.0
#19 lore raw

PATCH 15/20 net/ice: remove unnecessary null check

In reply to Stephen Hemminger

Remove unnecessary if check before calling free.

Generated by devtools/cocci/null_free.cocci

---
 drivers/net/intel/ice/ice_dcf_sched.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/net/intel/ice/ice_dcf_sched.c +2 -4
index 948774a282..14e902edbe 100644
@@ -877,10 +877,8 @@ static int ice_dcf_hierarchy_commit(struct rte_eth_dev *dev,
 	return ret_val;
 
 fail_clear:
-	if (vf_bw != NULL)
-		free(vf_bw);
-	if (tc_bw != NULL)
-		free(tc_bw);
+	free(vf_bw);
+	free(tc_bw);
 
 	/* clear all the traffic manager configuration */
 	if (clear_on_fail) {
Signature · 1 line
2.53.0
#20 lore raw

PATCH 16/20 net/bnxt: remove unnecessary null check

In reply to Stephen Hemminger

Remove unnecessary if check before calling rte_free.

Generated by devtools/cocci/null_free.cocci

---
 drivers/net/bnxt/tf_core/v3/tfo.c    | 6 ++----
 drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c | 6 ++----
 2 files changed, 4 insertions(+), 8 deletions(-)
drivers/net/bnxt/tf_core/v3/tfo.c +2 -4
index 4b1f545476..681d1dd8d3 100644
@@ -183,13 +183,11 @@ void tfo_close(void **tfo)
 				}
 			}
 		}
-		if (tim)
-			rte_free(tim);
+		rte_free(tim);
 		tfco->ts_tim = NULL;
 		tfco->tfgo = NULL;
 
-		if (*tfo)
-			rte_free(*tfo);
+		rte_free(*tfo);
 		*tfo = NULL;
 	}
 }
drivers/net/bnxt/tf_ulp/ulp_sc_mgr.c +2 -4
index 23e1b59ca4..3707cd1a2d 100644
@@ -169,11 +169,9 @@ ulp_sc_mgr_deinit(struct bnxt_ulp_context *ctxt)
 
 	ulp_sc_mgr_thread_cancel(ctxt);
 
-	if (ulp_sc_info->stats_cache_tbl)
-		rte_free(ulp_sc_info->stats_cache_tbl);
+	rte_free(ulp_sc_info->stats_cache_tbl);
 
-	if (ulp_sc_info->read_data)
-		rte_free(ulp_sc_info->read_data);
+	rte_free(ulp_sc_info->read_data);
 
 	rte_free(ulp_sc_info);
 
Signature · 1 line
2.53.0
#21 lore raw

PATCH 17/20 test: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 app/test/sample_packet_forward.c |  5 +----
 app/test/test_distributor.c      |  4 +---
 app/test/test_dmadev.c           |  6 ++----
 app/test/test_ipfrag.c           |  4 +---
 app/test/test_link_bonding.c     | 13 ++++---------
 app/test/test_pmd_perf.c         |  3 +--
 app/test/test_pmd_tap.c          |  3 +--
 app/test/test_reorder.c          | 12 ++++--------
 app/test/test_table_ports.c      | 12 ++++--------
 app/test/test_table_tables.c     | 21 +++++++--------------
 10 files changed, 26 insertions(+), 57 deletions(-)
app/test/sample_packet_forward.c +1 -4
index aa897274d8..70bb75e321 100644
@@ -115,10 +115,7 @@ test_get_mbuf_from_pool(struct rte_mempool **mp, struct rte_mbuf **pbuf,
 void
 test_put_mbuf_to_pool(struct rte_mempool *mp, struct rte_mbuf **pbuf)
 {
-	int itr = 0;
-
-	for (itr = 0; itr < NUM_PACKETS; itr++)
-		rte_pktmbuf_free(pbuf[itr]);
+	rte_pktmbuf_free_bulk(pbuf, NUM_PACKETS);
 	rte_mempool_free(mp);
 }
 
app/test/test_distributor.c +1 -3
index da0a21ea83..ed37ca80f1 100644
@@ -309,7 +309,6 @@ handle_work_with_free_mbufs(void *arg)
 	alignas(RTE_CACHE_LINE_SIZE) struct rte_mbuf *buf[8];
 	struct worker_params *wp = arg;
 	struct rte_distributor *d = wp->dist;
-	unsigned int i;
 	unsigned int num;
 	unsigned int id = rte_atomic_fetch_add_explicit(&worker_idx, 1, rte_memory_order_relaxed);
 
@@ -317,8 +316,7 @@ handle_work_with_free_mbufs(void *arg)
 	while (!quit) {
 		rte_atomic_fetch_add_explicit(&worker_stats[id].handled_packets, num,
 				rte_memory_order_relaxed);
-		for (i = 0; i < num; i++)
-			rte_pktmbuf_free(buf[i]);
+		rte_pktmbuf_free_bulk(buf, num);
 		num = rte_distributor_get_pkt(d, id, buf, NULL, 0);
 	}
 	rte_atomic_fetch_add_explicit(&worker_stats[id].handled_packets, num,
app/test/test_dmadev.c +2 -4
index 5488a1af33..a5772cc843 100644
@@ -499,10 +499,8 @@ test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
 				ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
 						id, 0);
 
-			for (i = 0; i < n_src; i++)
-				rte_pktmbuf_free(src[i]);
-			for (i = 0; i < n_dst; i++)
-				rte_pktmbuf_free(dst[i]);
+			rte_pktmbuf_free_bulk(src, n_src);
+			rte_pktmbuf_free_bulk(dst, n_dst);
 
 			/* Verify that completion returns nothing more */
 			if (rte_dma_completed(dev_id, 0, 1, NULL, NULL) != 0)
app/test/test_ipfrag.c +1 -3
index 247575d6c5..2c553222c2 100644
@@ -240,9 +240,7 @@ v6_allocate_packet_of(struct rte_mbuf *b, int fill, size_t s, uint8_t ttl,
 static inline void
 test_free_fragments(struct rte_mbuf *mb[], uint32_t num)
 {
-	uint32_t i;
-	for (i = 0; i < num; i++)
-		rte_pktmbuf_free(mb[i]);
+	rte_pktmbuf_free_bulk(mb, num);
 }
 
 static inline void
app/test/test_link_bonding.c +4 -9
index 19b064771a..eac785610a 100644
@@ -1476,10 +1476,7 @@ verify_mbufs_ref_count(struct rte_mbuf **mbufs, int nb_mbufs, int val)
 static void
 free_mbufs(struct rte_mbuf **mbufs, int nb_mbufs)
 {
-	int i;
-
-	for (i = 0; i < nb_mbufs; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, nb_mbufs);
 }
 
 #define TEST_RR_MEMBER_TX_FAIL_MEMBER_COUNT		(2)
@@ -4193,7 +4190,7 @@ testsuite_teardown(void)
 static void
 free_virtualpmd_tx_queue(void)
 {
-	int i, member_port, to_free_cnt;
+	int member_port, to_free_cnt;
 	struct rte_mbuf *pkts_to_free[MAX_PKT_BURST];
 
 	/* Free tx queue of virtual pmd */
@@ -4202,8 +4199,7 @@ free_virtualpmd_tx_queue(void)
 		to_free_cnt = virtual_ethdev_get_mbufs_from_tx_queue(
 				test_params->member_port_ids[member_port],
 				pkts_to_free, MAX_PKT_BURST);
-		for (i = 0; i < to_free_cnt; i++)
-			rte_pktmbuf_free(pkts_to_free[i]);
+		rte_pktmbuf_free_bulk(pkts_to_free, to_free_cnt);
 	}
 }
 
@@ -4381,8 +4377,7 @@ test_tlb_rx_burst(void)
 		}
 
 		/* free mbufs */
-		for (i = 0; i < burst_size; i++)
-			rte_pktmbuf_free(rx_pkt_burst[i]);
+		rte_pktmbuf_free_bulk(rx_pkt_burst, burst_size);
 
 		/* reset bonding device stats */
 		rte_eth_stats_reset(test_params->bonding_port_id);
app/test/test_pmd_perf.c +1 -2
index 995b0a6f20..dab1751b9a 100644
@@ -602,8 +602,7 @@ poll_burst(void *args)
 	       total, MAX_IDLE - timeout);
 	/* clean up */
 	total = pkt_per_port * conf->nb_ports - total;
-	for (i = 0; i < total; i++)
-		rte_pktmbuf_free(pkts_burst[i]);
+	rte_pktmbuf_free_bulk(pkts_burst, total);
 
 	rte_free(pkts_burst);
 
app/test/test_pmd_tap.c +1 -2
index 6d0e8b4f54..f48b69de3b 100644
@@ -192,8 +192,7 @@ test_tap_send_receive(void)
 	printf("Received %u packets on port %d\n", nb_rx, tap_port0);
 
 	/* Free received packets */
-	for (i = 0; i < nb_rx; i++)
-		rte_pktmbuf_free(rx_mbufs[i]);
+	rte_pktmbuf_free_bulk(rx_mbufs, nb_rx);
 
 	return TEST_SUCCESS;
 }
app/test/test_reorder.c +4 -8
index 8c68e00869..fc922650d6 100644
@@ -208,8 +208,7 @@ test_reorder_insert(void)
 	ret = 0;
 exit:
 	rte_reorder_free(b);
-	for (i = 0; i < INSERT_NUM_BUFS; i++)
-		rte_pktmbuf_free(bufs[i]);
+	rte_pktmbuf_free_bulk(bufs, INSERT_NUM_BUFS);
 
 	return ret;
 }
@@ -382,8 +381,7 @@ test_reorder_drain_up_to_seqn(void)
 		ret = -1;
 		goto exit;
 	}
-	for (i = 0; i < 2; i++)
-		rte_pktmbuf_free(robufs[i]);
+	rte_pktmbuf_free_bulk(robufs, 2);
 	memset(robufs, 0, sizeof(robufs));
 
 	/* Insert more packets
@@ -406,8 +404,7 @@ test_reorder_drain_up_to_seqn(void)
 		ret = -1;
 		goto exit;
 	}
-	for (i = 0; i < 2; i++)
-		rte_pktmbuf_free(robufs[i]);
+	rte_pktmbuf_free_bulk(robufs, 2);
 	memset(robufs, 0, sizeof(robufs));
 
 	ret = 0;
@@ -483,8 +480,7 @@ test_reorder_set_seqn(void)
 	ret = 0;
 exit:
 	rte_reorder_free(b);
-	for (i = 0; i < SET_SEQN_NUM_BUFS; i++)
-		rte_pktmbuf_free(bufs[i]);
+	rte_pktmbuf_free_bulk(bufs, SET_SEQN_NUM_BUFS);
 
 	return ret;
 }
app/test/test_table_ports.c +4 -8
index 282ec2a3d2..d617e73810 100644
@@ -73,8 +73,7 @@ test_port_ring_reader(void)
 	if (received_pkts < expected_pkts)
 		return -6;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
@@ -156,8 +155,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -8;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	/* TX Bulk */
 	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
@@ -171,8 +169,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -8;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
 		mbuf[i] = rte_pktmbuf_alloc(pool);
@@ -186,8 +183,7 @@ test_port_ring_writer(void)
 	if (received_pkts < expected_pkts)
 		return -9;
 
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(res_mbuf[i]);
+	rte_pktmbuf_free_bulk(res_mbuf, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
app/test/test_table_tables.c +7 -14
index 920aa555cb..d2c09c360f 100644
@@ -162,8 +162,7 @@ test_table_stub(void)
 		return -2;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	return 0;
 }
@@ -276,8 +275,7 @@ test_table_array(void)
 				return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_array_ops.f_free(table);
 
@@ -442,8 +440,7 @@ test_table_lpm(void)
 		return -23;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_lpm_ops.f_free(table);
 
@@ -620,8 +617,7 @@ test_table_lpm_ipv6(void)
 		return -24;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_lpm_ipv6_ops.f_free(table);
 
@@ -723,8 +719,7 @@ test_table_hash_lru_generic(struct rte_table_ops *ops, uint32_t key_size)
 		return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = ops->f_free(table);
 
@@ -833,8 +828,7 @@ test_table_hash_ext_generic(struct rte_table_ops *ops, uint32_t key_size)
 		return -13;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = ops->f_free(table);
 
@@ -1047,8 +1041,7 @@ test_table_hash_cuckoo(void)
 		return -20;
 
 	/* Free resources */
-	for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, RTE_PORT_IN_BURST_SIZE_MAX);
 
 	status = rte_table_hash_cuckoo_ops.f_free(table);
 
Signature · 1 line
2.53.0
#22 lore raw

PATCH 18/20 app/test-dma-perf: remove unnecessary null check

In reply to Stephen Hemminger

Remove unnecessary if check before calling rte_pktmbuf_free_bulk.

Generated by devtools/cocci/null_free.cocci

---
 app/test-dma-perf/benchmark.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
app/test-dma-perf/benchmark.c +2 -4
index c0ffc859bd..576c59faff 100644
@@ -690,10 +690,8 @@ teardown_memory_env(uint32_t nr_buf, struct rte_mbuf **srcs, struct rte_mbuf **d
 		    struct rte_dma_op **dma_ops)
 {
 	/* free mbufs used in the test */
-	if (srcs != NULL)
-		rte_pktmbuf_free_bulk(srcs, nr_buf);
-	if (dsts != NULL)
-		rte_pktmbuf_free_bulk(dsts, nr_buf);
+	rte_pktmbuf_free_bulk(srcs, nr_buf);
+	rte_pktmbuf_free_bulk(dsts, nr_buf);
 
 	/* free the points for the mbufs */
 	rte_free(srcs);
Signature · 1 line
2.53.0
#23 lore raw

Re: [PATCH 18/20] app/test-dma-perf: remove unnecessary null check

NACK
The srcs / dsts may be NULL if setup_memory_env() failed.

Quoted 26 lines · Stephen Hemminger

Remove unnecessary if check before calling rte_pktmbuf_free_bulk.

Generated by devtools/cocci/null_free.cocci

---
 app/test-dma-perf/benchmark.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
app/test-dma-perf/benchmark.c +2 -4
index c0ffc859bd..576c59faff 100644
@@ -690,10 +690,8 @@ teardown_memory_env(uint32_t nr_buf, struct rte_mbuf **srcs, struct rte_mbuf **d
 		    struct rte_dma_op **dma_ops)
 {
 	/* free mbufs used in the test */
-	if (srcs != NULL)
-		rte_pktmbuf_free_bulk(srcs, nr_buf);
-	if (dsts != NULL)
-		rte_pktmbuf_free_bulk(dsts, nr_buf);
+	rte_pktmbuf_free_bulk(srcs, nr_buf);
+	rte_pktmbuf_free_bulk(dsts, nr_buf);
 
 	/* free the points for the mbufs */
 	rte_free(srcs);
#24 lore raw

PATCH 19/20 app/test-compress-perf: remove unnecessary null check

In reply to Stephen Hemminger

Remove unnecessary if check before calling rte_free and rte_pktmbuf_free_bulk.

Generated by devtools/cocci/null_free.cocci

---
 app/test-compress-perf/comp_perf_test_common.c | 6 ++----
 app/test-compress-perf/main.c                  | 6 ++----
 2 files changed, 4 insertions(+), 8 deletions(-)
app/test-compress-perf/comp_perf_test_common.c +2 -4
index 12c2a7bbd0..90eb98166e 100644
@@ -83,11 +83,9 @@ comp_perf_free_memory(struct comp_test_data *test_data,
 {
 	uint32_t i;
 
-	if (mem->decomp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->decomp_bufs, mem->total_bufs);
 
-	if (mem->comp_bufs != NULL)
-		rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
+	rte_pktmbuf_free_bulk(mem->comp_bufs, mem->total_bufs);
 
 	rte_free(mem->decomp_bufs);
 	rte_free(mem->comp_bufs);
app/test-compress-perf/main.c +2 -4
index c9ead02cb4..bc2b185da4 100644
@@ -392,15 +392,13 @@ comp_perf_dump_dictionary_data(struct comp_test_data *td)
 
 		if (fread(data, data_to_read, 1, f) != 1) {
 			RTE_LOG(ERR, USER1, "Input file could not be read\n");
-			if (td->dictionary_data)
-				rte_free(td->dictionary_data);
+			rte_free(td->dictionary_data);
 			goto end;
 		}
 		if (fseek(f, 0, SEEK_SET) != 0) {
 			RTE_LOG(ERR, USER1,
 				"Size of input could not be calculated\n");
-			if (td->dictionary_data)
-				rte_free(td->dictionary_data);
+			rte_free(td->dictionary_data);
 			goto end;
 		}
 		remaining_data -= data_to_read;
Signature · 1 line
2.53.0
#25 lore raw

PATCH 20/20 examples: use rte_pktmbuf_free_bulk

In reply to Stephen Hemminger

Replace open-coded loop with rte_pktmbuf_free_bulk().

Generated by devtools/cocci/free_bulk.cocci.

---
 examples/bbdev_app/main.c                            |  4 +---
 examples/l2fwd-crypto/main.c                         |  4 ++--
 .../client_server_mp/mp_client/client.c              |  7 +++----
 .../multi_process/client_server_mp/mp_server/main.c  |  5 ++---
 examples/ntb/ntb_fwd.c                               | 12 +++++-------
 examples/packet_ordering/main.c                      |  5 +----
 examples/server_node_efd/efd_node/node.c             |  7 +++----
 examples/server_node_efd/efd_server/main.c           |  5 ++---
 examples/vhost/main.c                                |  3 +--
 9 files changed, 20 insertions(+), 32 deletions(-)
examples/bbdev_app/main.c +1 -3
index 03f15f91cc..4602f8012d 100644
@@ -291,9 +291,7 @@ print_mac(unsigned int portid, struct rte_ether_addr *bbdev_ports_eth_address)
 static inline void
 pktmbuf_free_bulk(struct rte_mbuf **mbufs, unsigned int nb_to_free)
 {
-	unsigned int i;
-	for (i = 0; i < nb_to_free; ++i)
-		rte_pktmbuf_free(mbufs[i]);
+	rte_pktmbuf_free_bulk(mbufs, nb_to_free);
 }
 
 static inline void
examples/l2fwd-crypto/main.c +2 -2
index a441312f55..3b2c23f29a 100644
@@ -931,8 +931,8 @@ l2fwd_main_loop(struct l2fwd_crypto_options *options)
 						RTE_CRYPTO_OP_TYPE_SYMMETRIC,
 						ops_burst, nb_rx) !=
 								nb_rx) {
-					for (j = 0; j < nb_rx; j++)
-						rte_pktmbuf_free(pkts_burst[j]);
+					rte_pktmbuf_free_bulk(pkts_burst,
+							      nb_rx);
 
 					nb_rx = 0;
 				}
examples/multi_process/client_server_mp/mp_client/client.c +3 -4
index 087c38ef73..9353ab7fda 100644
@@ -117,15 +117,14 @@ parse_app_args(int argc, char *argv[])
  */
 static void
 flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,
-		void *userdata) {
-	int i;
+		void *userdata)
+{
 	uint16_t port_id = (uintptr_t)userdata;
 
 	tx_stats->tx_drop[port_id] += count;
 
 	/* free the mbufs which failed from transmit */
-	for (i = 0; i < count; i++)
-		rte_pktmbuf_free(unsent[i]);
+	rte_pktmbuf_free_bulk(unsent, count);
 
 }
 
examples/multi_process/client_server_mp/mp_server/main.c +2 -3
index 691d453d0e..aa8b759aca 100644
@@ -195,7 +195,6 @@ clear_stats(void)
 static void
 flush_rx_queue(uint16_t client)
 {
-	uint16_t j;
 	struct client *cl;
 
 	if (cl_rx_buf[client].count == 0)
@@ -204,8 +203,8 @@ flush_rx_queue(uint16_t client)
 	cl = &clients[client];
 	if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[client].buffer,
 			cl_rx_buf[client].count, NULL) == 0){
-		for (j = 0; j < cl_rx_buf[client].count; j++)
-			rte_pktmbuf_free(cl_rx_buf[client].buffer[j]);
+		rte_pktmbuf_free_bulk(cl_rx_buf[client].buffer,
+				      cl_rx_buf[client].count);
 		cl->stats.rx_drop += cl_rx_buf[client].count;
 	}
 	else
examples/ntb/ntb_fwd.c +5 -7
index 33f3c1ef17..fe2b1e6b2b 100644
@@ -253,8 +253,7 @@ cmd_send_parsed(void *parsed_result,
 						(void *)queue_id);
 		if (ret < 0) {
 			printf("Enqueue failed with err %d\n", ret);
-			for (j = 0; j < nb_pkt; j++)
-				rte_pktmbuf_free(mbuf_send[j]);
+			rte_pktmbuf_free_bulk(mbuf_send, nb_pkt);
 			goto clean;
 		}
 		nb_tx = ret;
@@ -387,8 +386,8 @@ start_iofwd_per_lcore(void *param)
 				if (ret < 0) {
 					printf("Enqueue failed with err %d\n",
 						ret);
-					for (j = 0; j < nb_rx; j++)
-						rte_pktmbuf_free(pkts_burst[j]);
+					rte_pktmbuf_free_bulk(pkts_burst,
+							      nb_rx);
 					goto clean;
 				}
 				nb_tx = ret;
@@ -476,7 +475,7 @@ start_txonly_per_lcore(void *param)
 	struct ntb_fwd_lcore_conf *conf = param;
 	struct ntb_fwd_stream fs;
 	uint16_t nb_pkt, nb_tx;
-	int i, j, ret;
+	int i, ret;
 
 	for (i = 0; i < NTB_MAX_PKT_BURST; i++)
 		ntb_buf[i] = (struct rte_rawdev_buf *)
@@ -517,8 +516,7 @@ start_txonly_per_lcore(void *param)
 					nb_pkt, (void *)(size_t)fs.qp_id);
 			if (ret < 0) {
 				printf("Enqueue failed with err %d\n", ret);
-				for (j = 0; j < nb_pkt; j++)
-					rte_pktmbuf_free(pkts_burst[j]);
+				rte_pktmbuf_free_bulk(pkts_burst, nb_pkt);
 				goto clean;
 			}
 			nb_tx = ret;
examples/packet_ordering/main.c +1 -4
index 748fe0826a..f2097a90d4 100644
@@ -128,10 +128,7 @@ get_previous_lcore_id(unsigned int id)
 static inline void
 pktmbuf_free_bulk(struct rte_mbuf *mbuf_table[], unsigned n)
 {
-	unsigned int i;
-
-	for (i = 0; i < n; i++)
-		rte_pktmbuf_free(mbuf_table[i]);
+	rte_pktmbuf_free_bulk(mbuf_table, n);
 }
 
 /* display usage */
examples/server_node_efd/efd_node/node.c +3 -4
index fc2aa5ffef..5805e049b2 100644
@@ -121,15 +121,14 @@ parse_app_args(int argc, char *argv[])
  */
 static void
 flush_tx_error_callback(struct rte_mbuf **unsent, uint16_t count,
-		void *userdata) {
-	int i;
+		void *userdata)
+{
 	uint16_t port_id = (uintptr_t)userdata;
 
 	tx_stats->tx_drop[port_id] += count;
 
 	/* free the mbufs which failed from transmit */
-	for (i = 0; i < count; i++)
-		rte_pktmbuf_free(unsent[i]);
+	rte_pktmbuf_free_bulk(unsent, count);
 
 }
 
examples/server_node_efd/efd_server/main.c +2 -3
index 70a7372d4a..384bcfa780 100644
@@ -218,7 +218,6 @@ clear_stats(void)
 static void
 flush_rx_queue(uint16_t node)
 {
-	uint16_t j;
 	struct node *cl;
 
 	if (cl_rx_buf[node].count == 0)
@@ -227,8 +226,8 @@ flush_rx_queue(uint16_t node)
 	cl = &nodes[node];
 	if (rte_ring_enqueue_bulk(cl->rx_q, (void **)cl_rx_buf[node].buffer,
 			cl_rx_buf[node].count, NULL) != cl_rx_buf[node].count){
-		for (j = 0; j < cl_rx_buf[node].count; j++)
-			rte_pktmbuf_free(cl_rx_buf[node].buffer[j]);
+		rte_pktmbuf_free_bulk(cl_rx_buf[node].buffer,
+				      cl_rx_buf[node].count);
 		cl->stats.rx_drop += cl_rx_buf[node].count;
 	} else
 		cl->stats.rx += cl_rx_buf[node].count;
examples/vhost/main.c +1 -2
index ac888348d2..79561d6de0 100644
@@ -1006,8 +1006,7 @@ unlink_vmdq(struct vhost_dev *vdev)
 					(uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
 
 		while (rx_count) {
-			for (i = 0; i < rx_count; i++)
-				rte_pktmbuf_free(pkts_burst[i]);
+			rte_pktmbuf_free_bulk(pkts_burst, rx_count);
 
 			rx_count = rte_eth_rx_burst(ports[0],
 					(uint16_t)vdev->vmdq_rx_q, pkts_burst, MAX_PKT_BURST);
Signature · 1 line
2.53.0