mbuf: add a non fatal sanity check helper
authorDavid Marchand <david.marchand@6wind.com>
Mon, 7 Jan 2019 08:57:11 +0000 (09:57 +0100)
committerThomas Monjalon <thomas@monjalon.net>
Tue, 15 Jan 2019 01:40:40 +0000 (02:40 +0100)
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@6wind.com>
Signed-off-by: David Marchand <david.marchand@redhat.com>
Acked-by: Olivier Matz <olivier.matz@6wind.com>
lib/librte_mbuf/Makefile
lib/librte_mbuf/meson.build
lib/librte_mbuf/rte_mbuf.c
lib/librte_mbuf/rte_mbuf.h
lib/librte_mbuf/rte_mbuf_version.map

index 8c4c7d7..c8f6d26 100644 (file)
@@ -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
index e37da02..6cc11eb 100644 (file)
@@ -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
index 3bbd3f5..21f6f74 100644 (file)
@@ -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 */
index de9c656..b0a5a38 100644 (file)
@@ -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);                          \
index cae68db..2662a37 100644 (file)
@@ -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;