[dpdk-dev] [PATCH 2/3] mbuf: add a non fatal sanity check helper
David Marchand
david.marchand at 6wind.com
Mon Sep 10 07:45:46 CEST 2018
Let's add a little helper that does the same as rte_mbuf_sanity_check but
without the panic.
Signed-off-by: David Marchand <david.marchand at 6wind.com>
---
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 e2b98a254..7d0c824a3 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 45ffb0db5..4d9bdf2ba 100644
--- a/lib/librte_mbuf/meson.build
+++ b/lib/librte_mbuf/meson.build
@@ -5,3 +5,5 @@ version = 3
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 137a320ed..4e65f0f82 100644
--- a/lib/librte_mbuf/rte_mbuf.c
+++ b/lib/librte_mbuf/rte_mbuf.c
@@ -170,49 +170,81 @@ 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->buf_len) {
+ *reason = "data offset too big in mbuf segment";
+ return -1;
+ }
if ((uint32_t)m->data_off + (uint32_t)m->data_len >
- (uint32_t)m->buf_len)
- rte_panic("data length too big in mbuf segment\n");
+ (uint32_t)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 a50b05c64..e12a4c765 100644
--- a/lib/librte_mbuf/rte_mbuf.h
+++ b/lib/librte_mbuf/rte_mbuf.h
@@ -977,6 +977,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 cae68db8d..2662a37bf 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.17.1
More information about the dev
mailing list