From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from proxy.6wind.com (host.76.145.23.62.rev.coltfrance.com [62.23.145.76]) by dpdk.org (Postfix) with ESMTP id 3AC924CE6 for ; Thu, 24 Nov 2016 09:57:12 +0100 (CET) Received: from glumotte.dev.6wind.com (unknown [10.16.0.195]) by proxy.6wind.com (Postfix) with ESMTP id 76E0526D0F; Thu, 24 Nov 2016 09:56:52 +0100 (CET) From: Olivier Matz To: dev@dpdk.org, yuanhan.liu@linux.intel.com Cc: maxime.coquelin@redhat.com, huawei.xie@intel.com, stephen@networkplumber.org Date: Thu, 24 Nov 2016 09:56:35 +0100 Message-Id: <1479977798-13417-3-git-send-email-olivier.matz@6wind.com> X-Mailer: git-send-email 2.8.1 In-Reply-To: <1479977798-13417-1-git-send-email-olivier.matz@6wind.com> References: <1479977798-13417-1-git-send-email-olivier.matz@6wind.com> Subject: [dpdk-dev] [PATCH 2/5] mbuf: new helper to check if a mbuf is shared X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 24 Nov 2016 08:57:12 -0000 Introduce 2 new helpers rte_pktmbuf_seg_is_shared() and rte_pktmbuf_data_is_shared() to check if the packet data inside a mbuf is shared (and shall not be modified). To avoid a "discards const qualifier" error, add a const to the argument of rte_mbuf_from_indirect(). Signed-off-by: Olivier Matz --- app/test/test_mbuf.c | 34 +++++++++++++++++++--- lib/librte_mbuf/rte_mbuf.h | 71 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c index c0823ea..7656a4d 100644 --- a/app/test/test_mbuf.c +++ b/app/test/test_mbuf.c @@ -333,6 +333,7 @@ testclone_testupdate_testdetach(void) struct rte_mbuf *m = NULL; struct rte_mbuf *clone = NULL; struct rte_mbuf *clone2 = NULL; + struct rte_mbuf *m2 = NULL; unaligned_uint32_t *data; /* alloc a mbuf */ @@ -384,6 +385,11 @@ testclone_testupdate_testdetach(void) if (*data != MAGIC_DATA) GOTO_FAIL("invalid data in clone->next\n"); + if (rte_pktmbuf_seg_is_shared(m) == 0) + GOTO_FAIL("m should be marked as shared\n"); + if (rte_pktmbuf_seg_is_shared(clone) == 0) + GOTO_FAIL("clone should be marked as shared\n"); + if (rte_mbuf_refcnt_read(m) != 2) GOTO_FAIL("invalid refcnt in m\n"); @@ -410,14 +416,32 @@ testclone_testupdate_testdetach(void) if (rte_mbuf_refcnt_read(m->next) != 3) GOTO_FAIL("invalid refcnt in m->next\n"); + /* prepend data to one of the clone */ + m2 = rte_pktmbuf_alloc(pktmbuf_pool); + if (m2 == NULL) + GOTO_FAIL("cannot allocate m2"); + rte_pktmbuf_append(m2, sizeof(uint32_t)); + rte_pktmbuf_chain(m2, clone); + clone = NULL; + + if (rte_pktmbuf_data_is_shared(m2, 0, sizeof(uint32_t))) + GOTO_FAIL("m2 headers should not be marked as shared"); + if (rte_pktmbuf_data_is_shared(m2, sizeof(uint32_t), + rte_pktmbuf_pkt_len(m2) - sizeof(uint32_t)) == 0) + GOTO_FAIL("m2 data should be marked as shared"); + /* free mbuf */ rte_pktmbuf_free(m); - rte_pktmbuf_free(clone); - rte_pktmbuf_free(clone2); - m = NULL; - clone = NULL; + rte_pktmbuf_free(m2); + m2 = NULL; + + if (rte_pktmbuf_seg_is_shared(clone2)) + GOTO_FAIL("clone2 should not be marked as shared\n"); + + rte_pktmbuf_free(clone2); clone2 = NULL; + printf("%s ok\n", __func__); return 0; @@ -428,6 +452,8 @@ testclone_testupdate_testdetach(void) rte_pktmbuf_free(clone); if (clone2) rte_pktmbuf_free(clone2); + if (m2) + rte_pktmbuf_free(m2); return -1; } diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index 14956f6..cd77a56 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -576,7 +576,7 @@ rte_mbuf_data_dma_addr_default(const struct rte_mbuf *mb) * The address of the direct mbuf corresponding to buffer_addr. */ static inline struct rte_mbuf * -rte_mbuf_from_indirect(struct rte_mbuf *mi) +rte_mbuf_from_indirect(const struct rte_mbuf *mi) { return (struct rte_mbuf *)RTE_PTR_SUB(mi->buf_addr, sizeof(*mi) + mi->priv_size); } @@ -1574,6 +1574,75 @@ static inline int rte_pktmbuf_is_contiguous(const struct rte_mbuf *m) } /** + * Test if a mbuf segment is shared + * + * Return true if the data embedded in this segment is shared by several + * mbufs. In this case, the mbuf data should be considered as read-only. + * + * @param m + * The packet mbuf. + * @return + * - (1), the mbuf segment is shared (read-only) + * - (0), the mbuf segment is not shared (writable) + */ +static inline int rte_pktmbuf_seg_is_shared(const struct rte_mbuf *m) +{ + if (rte_mbuf_refcnt_read(m) > 1) + return 1; + + if (RTE_MBUF_INDIRECT(m) && + rte_mbuf_refcnt_read(rte_mbuf_from_indirect(m)) > 1) + return 1; + + return 0; +} + +/** + * Test if some data in an mbuf chain is shared + * + * Return true if the specified data area in the mbuf chain is shared by + * several mbufs. In this case, this data should be considered as + * read-only. + * + * If the area described by off and len exceeds the bounds of the mbuf + * chain (off + len <= rte_pktmbuf_pkt_len()), the exceeding part of the + * area is ignored. + * + * @param m + * The packet mbuf. + * @return + * - (1), the mbuf data is shared (read-only) + * - (0), the mbuf data is not shared (writable) + */ +static inline int rte_pktmbuf_data_is_shared(const struct rte_mbuf *m, + uint32_t off, uint32_t len) +{ + const struct rte_mbuf *seg = m; + + if (likely(off + len <= rte_pktmbuf_data_len(seg))) + return rte_pktmbuf_seg_is_shared(seg); + + while (seg->next && off >= rte_pktmbuf_data_len(seg)) { + off -= rte_pktmbuf_data_len(seg); + seg = seg->next; + } + + if (off + len <= rte_pktmbuf_data_len(seg)) + return rte_pktmbuf_seg_is_shared(seg); + + while (seg->next && len > 0) { + if (rte_pktmbuf_seg_is_shared(seg)) + return 1; + + len -= (rte_pktmbuf_data_len(seg) - off); + off = 0; + seg = seg->next; + } + + return 0; +} + +/** * @internal used by rte_pktmbuf_read(). */ void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, -- 2.8.1