All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Morten Brørup" <mb@smartsharesystems.com>
To: <dev@dpdk.org>, "Thomas Monjalon" <thomas@monjalon.net>,
	"Stephen Hemminger" <stephen@networkplumber.org>,
	"Bruce Richardson" <bruce.richardson@intel.com>,
	"Konstantin Ananyev" <konstantin.ananyev@huawei.com>,
	"Andrew Rybchenko" <andrew.rybchenko@oktetlabs.ru>,
	"Ivan Malov" <ivan.malov@arknetworks.am>,
	"Chengwen Feng" <fengchengwen@huawei.com>
Subject: RE: [PATCH v3] mbuf: de-inline sanity checking a reinitialized mbuf
Date: Thu, 21 Aug 2025 16:30:08 +0200	[thread overview]
Message-ID: <98CBD80474FA8B44BF855DF32C47DC35E9FE5B@smartserver.smartshare.dk> (raw)
In-Reply-To: <20250722093431.555214-1-mb@smartsharesystems.com>

This patch has been superseded by this series:
https://inbox.dpdk.org/dev/20250821142544.16211-1-mb@smartsharesystems.com/


Med venlig hilsen / Kind regards,
-Morten Brørup

> -----Original Message-----
> From: Morten Brørup [mailto:mb@smartsharesystems.com]
> Sent: Tuesday, 22 July 2025 11.35
> To: dev@dpdk.org; Thomas Monjalon; Stephen Hemminger; Bruce Richardson;
> Konstantin Ananyev; Andrew Rybchenko; Ivan Malov
> Cc: Morten Brørup
> Subject: [PATCH v3] mbuf: de-inline sanity checking a reinitialized mbuf
> 
> Sanity checking a reinitialized mbuf (a.k.a. raw mbuf) has been refactored
> to follow the same design pattern as sanity checking a normal mbuf, and
> now depends on RTE_LIBRTE_MBUF_DEBUG instead of RTE_ENABLE_ASSERT.
> 
> The details of the changes are as follows:
> 
> Non-inlined functions rte_mbuf_raw_sanity_check() and rte_mbuf_raw_check()
> have been added.
> They do for a reinitialized mbuf what rte_mbuf_sanity_check() and
> rte_mbuf_check() do for a normal mbuf.
> They basically check the same conditions as __rte_mbuf_raw_sanity_check()
> previously did, but use "if (!condition) rte_panic(message)" instead of
> RTE_ASSERT(), so they don't depend on RTE_ENABLE_ASSERT.
> 
> The inline function __rte_mbuf_raw_sanity_check() has been replaced
> by the new macro __rte_mbuf_raw_sanity_check_mp(), which either calls
> rte_mbuf_raw_sanity_check() or does nothing, depending on
> RTE_LIBRTE_MBUF_DEBUG, just like the __rte_mbuf_sanity_check() macro does
> for a normal mbuf.
> 
> Note that the new macro __rte_mbuf_raw_sanity_check_mp() takes an optional
> mempool parameter to verify that the mbuf belongs to the expected mbuf
> pool.
> This addition is mainly relevant for sanity checking reinitialized mbufs
> freed directly into a given mempool by a PMD when using
> RTE_ETH_TX_OFFLOAD_MBUF_FAST_FREE.
> 
> The macro __rte_mbuf_raw_sanity_check() has been kept for backwards API
> compatibility.
> It simply calls __rte_mbuf_raw_sanity_check_mp() without specifying a
> mempool.
> 
> Signed-off-by: Morten Brørup <mb@smartsharesystems.com>
> ---
> v3:
> * Removed experimental status for the new functions.
>   Experimental is optional for new symbols, to allow for future API
>   changes. But this has been around for a long time. (Stephen Hemminger)
> * Consequentially, the added build check for ALLOW_EXPERIMENTAL_API with
>   RTE_LIBRTE_MBUF_DEBUG is no longer needed, and was removed.
> v2:
> * Added explicit build check for ALLOW_EXPERIMENTAL_API being enabled when
>   RTE_LIBRTE_MBUF_DEBUG is enabled, with descriptive error message if not
>   so. (Ivan Malov)
> * Fixed typo in patch description.
> ---
>  lib/mbuf/rte_mbuf.c | 61 ++++++++++++++++++++++++++++
>  lib/mbuf/rte_mbuf.h | 96 +++++++++++++++++++++++++++------------------
>  2 files changed, 119 insertions(+), 38 deletions(-)
> 
> diff --git a/lib/mbuf/rte_mbuf.c b/lib/mbuf/rte_mbuf.c
> index 9e7731a8a2..af39c13cf7 100644
> --- a/lib/mbuf/rte_mbuf.c
> +++ b/lib/mbuf/rte_mbuf.c
> @@ -373,6 +373,67 @@ rte_pktmbuf_pool_create_extbuf(const char *name, unsigned
> int n,
>  	return mp;
>  }
> 
> +/* do some sanity checks on a reinitialized mbuf: panic if it fails */
> +RTE_EXPORT_SYMBOL(rte_mbuf_raw_sanity_check)
> +void
> +rte_mbuf_raw_sanity_check(const struct rte_mbuf *m, const struct rte_mempool
> *mp)
> +{
> +	const char *reason;
> +
> +	if (rte_mbuf_raw_check(m, mp, &reason))
> +		rte_panic("%s\n", reason);
> +}
> +
> +RTE_EXPORT_SYMBOL(rte_mbuf_raw_check)
> +int rte_mbuf_raw_check(const struct rte_mbuf *m, const struct rte_mempool
> *mp,
> +		   const char **reason)
> +{
> +	/* check sanity */
> +	if (rte_mbuf_check(m, 0, reason) == -1)
> +		return -1;
> +
> +	/* check initialized */
> +	if (rte_mbuf_refcnt_read(m) != 1) {
> +		*reason = "uninitialized ref cnt";
> +		return -1;
> +	}
> +	if (m->next != NULL) {
> +		*reason = "uninitialized next ptr";
> +		return -1;
> +	}
> +	if (m->nb_segs != 1) {
> +		*reason = "uninitialized nb_segs";
> +		return -1;
> +	}
> +	if (RTE_MBUF_CLONED(m)) {
> +		*reason = "cloned";
> +		return -1;
> +	}
> +	if (RTE_MBUF_HAS_EXTBUF(m)) {
> +		if (!RTE_MBUF_HAS_PINNED_EXTBUF(m)) {
> +			*reason = "external buffer not pinned";
> +			return -1;
> +		}
> +
> +		uint16_t cnt = rte_mbuf_ext_refcnt_read(m->shinfo);
> +		if ((cnt == 0) || (cnt == UINT16_MAX)) {
> +			*reason = "pinned external buffer bad ref cnt";
> +			return -1;
> +		}
> +		if (cnt != 1) {
> +			*reason = "pinned external buffer uninitialized ref cnt";
> +			return -1;
> +		}
> +	}
> +
> +	if (mp != NULL && m->pool != mp) {
> +		*reason = "wrong mbuf pool";
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
>  /* do some sanity checks on a mbuf: panic if it fails */
>  RTE_EXPORT_SYMBOL(rte_mbuf_sanity_check)
>  void
> diff --git a/lib/mbuf/rte_mbuf.h b/lib/mbuf/rte_mbuf.h
> index 06ab7502a5..552cda1ae5 100644
> --- a/lib/mbuf/rte_mbuf.h
> +++ b/lib/mbuf/rte_mbuf.h
> @@ -339,11 +339,17 @@ rte_pktmbuf_priv_flags(struct rte_mempool *mp)
> 
>  #ifdef RTE_LIBRTE_MBUF_DEBUG
> 
> +/**  check reinitialized mbuf type in debug mode */
> +#define __rte_mbuf_raw_sanity_check_mp(m, mp) rte_mbuf_raw_sanity_check(m,
> mp)
> +
>  /**  check mbuf type in debug mode */
>  #define __rte_mbuf_sanity_check(m, is_h) rte_mbuf_sanity_check(m, is_h)
> 
>  #else /*  RTE_LIBRTE_MBUF_DEBUG */
> 
> +/**  check reinitialized mbuf type in debug mode */
> +#define __rte_mbuf_raw_sanity_check_mp(m, mp) do { } while (0)
> +
>  /**  check mbuf type in debug mode */
>  #define __rte_mbuf_sanity_check(m, is_h) do { } while (0)
> 
> @@ -513,6 +519,46 @@ rte_mbuf_ext_refcnt_update(struct
> rte_mbuf_ext_shared_info *shinfo,
>  } while (0)
> 
> 
> +/**
> + * Sanity checks on a reinitialized mbuf.
> + *
> + * Check the consistency of the given reinitialized mbuf.
> + * The function will cause a panic if corruption is detected.
> + *
> + * Check that the mbuf is properly reinitialized (refcnt=1, next=NULL,
> + * nb_segs=1), as done by rte_pktmbuf_prefree_seg().
> + *
> + * @param m
> + *   The mbuf to be checked.
> + * @param mp
> + *   The mempool to which the mbuf belongs.
> + *   NULL if unknown, not to be checked.
> + */
> +void
> +rte_mbuf_raw_sanity_check(const struct rte_mbuf *m, const struct rte_mempool
> *mp);
> +
> +/**
> + * Sanity checks on a reinitialized mbuf.
> + *
> + * Almost like rte_mbuf_raw_sanity_check(), but this function gives the
> reason
> + * if corruption is detected rather than panic.
> + *
> + * @param m
> + *   The mbuf to be checked.
> + * @param mp
> + *   The mempool to which the mbuf belongs.
> + *   NULL if unknown, not to be checked.
> + * @param reason
> + *   A reference to a string pointer where to store the reason why a mbuf is
> + *   considered invalid.
> + * @return
> + *   - 0 if no issue has been found, reason is left untouched.
> + *   - -1 if a problem is detected, reason then points to a string describing
> + *     the reason why the mbuf is deemed invalid.
> + */
> +int rte_mbuf_raw_check(const struct rte_mbuf *m, const struct rte_mempool
> *mp,
> +		   const char **reason);
> +
>  /**
>   * Sanity checks on an mbuf.
>   *
> @@ -550,33 +596,11 @@ rte_mbuf_sanity_check(const struct rte_mbuf *m, int
> is_header);
>  int rte_mbuf_check(const struct rte_mbuf *m, int is_header,
>  		   const char **reason);
> 
> -/**
> - * Sanity checks on a reinitialized mbuf in debug mode.
> - *
> - * Check the consistency of the given reinitialized mbuf.
> - * The function will cause a panic if corruption is detected.
> - *
> - * Check that the mbuf is properly reinitialized (refcnt=1, next=NULL,
> - * nb_segs=1), as done by rte_pktmbuf_prefree_seg().
> - *
> - * @param m
> - *   The mbuf to be checked.
> - */
> -static __rte_always_inline void
> -__rte_mbuf_raw_sanity_check(__rte_unused const struct rte_mbuf *m)
> -{
> -	RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1);
> -	RTE_ASSERT(m->next == NULL);
> -	RTE_ASSERT(m->nb_segs == 1);
> -	RTE_ASSERT(!RTE_MBUF_CLONED(m));
> -	RTE_ASSERT(!RTE_MBUF_HAS_EXTBUF(m) ||
> -			(RTE_MBUF_HAS_PINNED_EXTBUF(m) &&
> -			rte_mbuf_ext_refcnt_read(m->shinfo) == 1));
> -	__rte_mbuf_sanity_check(m, 0);
> -}
> +/** For backwards compatibility. */
> +#define __rte_mbuf_raw_sanity_check(m) __rte_mbuf_raw_sanity_check_mp(m,
> NULL)
> 
>  /** For backwards compatibility. */
> -#define MBUF_RAW_ALLOC_CHECK(m) __rte_mbuf_raw_sanity_check(m)
> +#define MBUF_RAW_ALLOC_CHECK(m) __rte_mbuf_raw_sanity_check_mp(m, NULL)
> 
>  /**
>   * Allocate an uninitialized mbuf from mempool *mp*.
> @@ -606,7 +630,7 @@ static inline struct rte_mbuf *rte_mbuf_raw_alloc(struct
> rte_mempool *mp)
> 
>  	if (rte_mempool_get(mp, &ret.ptr) < 0)
>  		return NULL;
> -	__rte_mbuf_raw_sanity_check(ret.m);
> +	__rte_mbuf_raw_sanity_check_mp(ret.m, mp);
>  	return ret.m;
>  }
> 
> @@ -644,7 +668,7 @@ rte_mbuf_raw_alloc_bulk(struct rte_mempool *mp, struct
> rte_mbuf **mbufs, unsigne
>  	int rc = rte_mempool_get_bulk(mp, (void **)mbufs, count);
>  	if (likely(rc == 0))
>  		for (unsigned int idx = 0; idx < count; idx++)
> -			__rte_mbuf_raw_sanity_check(mbufs[idx]);
> +			__rte_mbuf_raw_sanity_check_mp(mbufs[idx], mp);
>  	return rc;
>  }
> 
> @@ -665,7 +689,7 @@ rte_mbuf_raw_alloc_bulk(struct rte_mempool *mp, struct
> rte_mbuf **mbufs, unsigne
>  static __rte_always_inline void
>  rte_mbuf_raw_free(struct rte_mbuf *m)
>  {
> -	__rte_mbuf_raw_sanity_check(m);
> +	__rte_mbuf_raw_sanity_check_mp(m, NULL);
>  	rte_mempool_put(m->pool, m);
>  }
> 
> @@ -696,12 +720,8 @@ __rte_experimental
>  static __rte_always_inline void
>  rte_mbuf_raw_free_bulk(struct rte_mempool *mp, struct rte_mbuf **mbufs,
> unsigned int count)
>  {
> -	for (unsigned int idx = 0; idx < count; idx++) {
> -		const struct rte_mbuf *m = mbufs[idx];
> -		RTE_ASSERT(m != NULL);
> -		RTE_ASSERT(m->pool == mp);
> -		__rte_mbuf_raw_sanity_check(m);
> -	}
> +	for (unsigned int idx = 0; idx < count; idx++)
> +		__rte_mbuf_raw_sanity_check_mp(mbufs[idx], mp);
> 
>  	rte_mempool_put_bulk(mp, (void **)mbufs, count);
>  }
> @@ -1021,22 +1041,22 @@ static inline int rte_pktmbuf_alloc_bulk(struct
> rte_mempool *pool,
>  	switch (count % 4) {
>  	case 0:
>  		while (idx != count) {
> -			__rte_mbuf_raw_sanity_check(mbufs[idx]);
> +			__rte_mbuf_raw_sanity_check_mp(mbufs[idx], pool);
>  			rte_pktmbuf_reset(mbufs[idx]);
>  			idx++;
>  			/* fall-through */
>  	case 3:
> -			__rte_mbuf_raw_sanity_check(mbufs[idx]);
> +			__rte_mbuf_raw_sanity_check_mp(mbufs[idx], pool);
>  			rte_pktmbuf_reset(mbufs[idx]);
>  			idx++;
>  			/* fall-through */
>  	case 2:
> -			__rte_mbuf_raw_sanity_check(mbufs[idx]);
> +			__rte_mbuf_raw_sanity_check_mp(mbufs[idx], pool);
>  			rte_pktmbuf_reset(mbufs[idx]);
>  			idx++;
>  			/* fall-through */
>  	case 1:
> -			__rte_mbuf_raw_sanity_check(mbufs[idx]);
> +			__rte_mbuf_raw_sanity_check_mp(mbufs[idx], pool);
>  			rte_pktmbuf_reset(mbufs[idx]);
>  			idx++;
>  			/* fall-through */
> --
> 2.43.0


      parent reply	other threads:[~2025-08-21 14:30 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-19 10:23 [PATCH] mbuf: de-inline sanity checking a reinitialized mbuf Morten Brørup
2025-07-19 14:14 ` Morten Brørup
2025-07-19 22:30   ` Ivan Malov
2025-07-20  9:25     ` Morten Brørup
2025-07-20 13:09       ` Ivan Malov
2025-07-21 15:00   ` Stephen Hemminger
2025-07-20 20:49 ` [PATCH v2] " Morten Brørup
2025-07-22  9:34 ` [PATCH v3] " Morten Brørup
2025-07-26 12:01   ` Andrew Rybchenko
2025-08-11 10:06   ` Morten Brørup
2025-08-11 15:38     ` Stephen Hemminger
2025-08-15 14:52   ` Konstantin Ananyev
2025-08-21 14:30   ` Morten Brørup [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=98CBD80474FA8B44BF855DF32C47DC35E9FE5B@smartserver.smartshare.dk \
    --to=mb@smartsharesystems.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=fengchengwen@huawei.com \
    --cc=ivan.malov@arknetworks.am \
    --cc=konstantin.ananyev@huawei.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.