From d4dca8fe437760ff866cf2aa35a612d7a099862b Mon Sep 17 00:00:00 2001 From: David Marchand Date: Mon, 7 Jan 2019 09:57:11 +0100 Subject: [PATCH] mbuf: add a non fatal sanity check helper Let's add a little helper that does the same as rte_mbuf_sanity_check but without the panic. Signed-off-by: David Marchand Signed-off-by: David Marchand Acked-by: Olivier Matz --- lib/librte_mbuf/Makefile | 2 + lib/librte_mbuf/meson.build | 2 + lib/librte_mbuf/rte_mbuf.c | 74 ++++++++++++++++++++-------- lib/librte_mbuf/rte_mbuf.h | 23 +++++++++ lib/librte_mbuf/rte_mbuf_version.map | 6 +++ 5 files changed, 86 insertions(+), 21 deletions(-) diff --git a/lib/librte_mbuf/Makefile b/lib/librte_mbuf/Makefile index 8c4c7d7905..c8f6d26895 100644 --- a/lib/librte_mbuf/Makefile +++ b/lib/librte_mbuf/Makefile @@ -7,6 +7,8 @@ include $(RTE_SDK)/mk/rte.vars.mk LIB = librte_mbuf.a CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +CFLAGS += -DALLOW_EXPERIMENTAL_API + LDLIBS += -lrte_eal -lrte_mempool EXPORT_MAP := rte_mbuf_version.map diff --git a/lib/librte_mbuf/meson.build b/lib/librte_mbuf/meson.build index e37da02509..6cc11ebb40 100644 --- a/lib/librte_mbuf/meson.build +++ b/lib/librte_mbuf/meson.build @@ -5,3 +5,5 @@ version = 5 sources = files('rte_mbuf.c', 'rte_mbuf_ptype.c', 'rte_mbuf_pool_ops.c') headers = files('rte_mbuf.h', 'rte_mbuf_ptype.h', 'rte_mbuf_pool_ops.h') deps += ['mempool'] + +allow_experimental_apis = true diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c index 3bbd3f5d28..21f6f74046 100644 --- a/lib/librte_mbuf/rte_mbuf.c +++ b/lib/librte_mbuf/rte_mbuf.c @@ -170,48 +170,80 @@ rte_pktmbuf_pool_create(const char *name, unsigned int n, /* do some sanity checks on a mbuf: panic if it fails */ void rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header) +{ + const char *reason; + + if (rte_mbuf_check(m, is_header, &reason)) + rte_panic("%s\n", reason); +} + +__rte_experimental +int rte_mbuf_check(const struct rte_mbuf *m, int is_header, + const char **reason) { unsigned int nb_segs, pkt_len; - if (m == NULL) - rte_panic("mbuf is NULL\n"); + if (m == NULL) { + *reason = "mbuf is NULL"; + return -1; + } /* generic checks */ - if (m->pool == NULL) - rte_panic("bad mbuf pool\n"); - if (m->buf_iova == 0) - rte_panic("bad IO addr\n"); - if (m->buf_addr == NULL) - rte_panic("bad virt addr\n"); + if (m->pool == NULL) { + *reason = "bad mbuf pool"; + return -1; + } + if (m->buf_iova == 0) { + *reason = "bad IO addr"; + return -1; + } + if (m->buf_addr == NULL) { + *reason = "bad virt addr"; + return -1; + } uint16_t cnt = rte_mbuf_refcnt_read(m); - if ((cnt == 0) || (cnt == UINT16_MAX)) - rte_panic("bad ref cnt\n"); + if ((cnt == 0) || (cnt == UINT16_MAX)) { + *reason = "bad ref cnt"; + return -1; + } /* nothing to check for sub-segments */ if (is_header == 0) - return; + return 0; /* data_len is supposed to be not more than pkt_len */ - if (m->data_len > m->pkt_len) - rte_panic("bad data_len\n"); + if (m->data_len > m->pkt_len) { + *reason = "bad data_len"; + return -1; + } nb_segs = m->nb_segs; pkt_len = m->pkt_len; do { - if (m->data_off > m->buf_len) - rte_panic("data offset too big in mbuf segment\n"); - if (m->data_off + m->data_len > m->buf_len) - rte_panic("data length too big in mbuf segment\n"); + if (m->data_off > m->buf_len) { + *reason = "data offset too big in mbuf segment"; + return -1; + } + if (m->data_off + m->data_len > m->buf_len) { + *reason = "data length too big in mbuf segment"; + return -1; + } nb_segs -= 1; pkt_len -= m->data_len; } while ((m = m->next) != NULL); - if (nb_segs) - rte_panic("bad nb_segs\n"); - if (pkt_len) - rte_panic("bad pkt_len\n"); + if (nb_segs) { + *reason = "bad nb_segs"; + return -1; + } + if (pkt_len) { + *reason = "bad pkt_len"; + return -1; + } + + return 0; } /* dump a mbuf on console */ diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index de9c6562f2..b0a5a38211 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -1049,6 +1049,29 @@ rte_mbuf_ext_refcnt_update(struct rte_mbuf_ext_shared_info *shinfo, void rte_mbuf_sanity_check(const struct rte_mbuf *m, int is_header); +/** + * Sanity checks on a mbuf. + * + * Almost like rte_mbuf_sanity_check(), but this function gives the reason + * if corruption is detected rather than panic. + * + * @param m + * The mbuf to be checked. + * @param is_header + * True if the mbuf is a packet header, false if it is a sub-segment + * of a packet (in this case, some fields like nb_segs are not 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. + */ +__rte_experimental +int rte_mbuf_check(const struct rte_mbuf *m, int is_header, + const char **reason); + #define MBUF_RAW_ALLOC_CHECK(m) do { \ RTE_ASSERT(rte_mbuf_refcnt_read(m) == 1); \ RTE_ASSERT((m)->next == NULL); \ diff --git a/lib/librte_mbuf/rte_mbuf_version.map b/lib/librte_mbuf/rte_mbuf_version.map index cae68db8d1..2662a37bf6 100644 --- a/lib/librte_mbuf/rte_mbuf_version.map +++ b/lib/librte_mbuf/rte_mbuf_version.map @@ -45,3 +45,9 @@ DPDK_18.08 { rte_mbuf_user_mempool_ops; rte_pktmbuf_pool_create_by_ops; } DPDK_16.11; + +EXPERIMENTAL { + global: + + rte_mbuf_check; +} DPDK_18.08; -- 2.20.1