From patchwork Thu Nov 24 08:56:36 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Matz X-Patchwork-Id: 17226 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 48C424A59; Thu, 24 Nov 2016 09:56:59 +0100 (CET) Received: from proxy.6wind.com (host.76.145.23.62.rev.coltfrance.com [62.23.145.76]) by dpdk.org (Postfix) with ESMTP id 3BB942BA7 for ; Thu, 24 Nov 2016 09:56:57 +0100 (CET) Received: from glumotte.dev.6wind.com (unknown [10.16.0.195]) by proxy.6wind.com (Postfix) with ESMTP id 97B6C26D1C; 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:36 +0100 Message-Id: <1479977798-13417-4-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 3/5] mbuf: new helper to write data in a mbuf chain 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: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Introduce a new helper to write data in a chain of mbufs, spreading it in the segments. Signed-off-by: Olivier Matz --- app/test/test_mbuf.c | 21 +++++++++++++++ lib/librte_mbuf/rte_mbuf.c | 44 +++++++++++++++++++++++++++++++ lib/librte_mbuf/rte_mbuf.h | 50 ++++++++++++++++++++++++++++++++++++ lib/librte_mbuf/rte_mbuf_version.map | 6 +++++ 4 files changed, 121 insertions(+) diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c index 7656a4d..5f1bc5d 100644 --- a/app/test/test_mbuf.c +++ b/app/test/test_mbuf.c @@ -335,6 +335,10 @@ testclone_testupdate_testdetach(void) struct rte_mbuf *clone2 = NULL; struct rte_mbuf *m2 = NULL; unaligned_uint32_t *data; + uint32_t magic = MAGIC_DATA; + uint32_t check_data[2]; + + memset(check_data, 0, sizeof(check_data)); /* alloc a mbuf */ m = rte_pktmbuf_alloc(pktmbuf_pool); @@ -421,6 +425,8 @@ testclone_testupdate_testdetach(void) if (m2 == NULL) GOTO_FAIL("cannot allocate m2"); rte_pktmbuf_append(m2, sizeof(uint32_t)); + if (rte_pktmbuf_write(m2, 0, sizeof(uint32_t), &magic) < 0) + GOTO_FAIL("cannot write data in m2"); rte_pktmbuf_chain(m2, clone); clone = NULL; @@ -430,6 +436,21 @@ testclone_testupdate_testdetach(void) rte_pktmbuf_pkt_len(m2) - sizeof(uint32_t)) == 0) GOTO_FAIL("m2 data should be marked as shared"); + /* check data content */ + data = rte_pktmbuf_read(m2, 0, sizeof(uint32_t), check_data); + if (data == NULL) + GOTO_FAIL("cannot read data"); + if (*data != MAGIC_DATA) + GOTO_FAIL("invalid data"); + if (data == check_data) + GOTO_FAIL("data should not have been copied"); + data = rte_pktmbuf_read(m2, 0, sizeof(uint32_t) * 2, check_data); + if (data == NULL) + GOTO_FAIL("cannot read data"); + if (data[0] != MAGIC_DATA || data[1] != MAGIC_DATA) + GOTO_FAIL("invalid data"); + if (data != check_data) + GOTO_FAIL("data should have been copied"); /* free mbuf */ rte_pktmbuf_free(m); m = NULL; diff --git a/lib/librte_mbuf/rte_mbuf.c b/lib/librte_mbuf/rte_mbuf.c index b31958e..ed56193 100644 --- a/lib/librte_mbuf/rte_mbuf.c +++ b/lib/librte_mbuf/rte_mbuf.c @@ -298,6 +298,50 @@ void *__rte_pktmbuf_read(const struct rte_mbuf *m, uint32_t off, return buf; } +/* write len data bytes in a mbuf at specified offset (internal) */ +int +__rte_pktmbuf_write(const struct rte_mbuf *m, uint32_t off, + uint32_t len, const void *buf) +{ + const struct rte_mbuf *seg = m; + uint32_t buf_off = 0, copy_len; + char *dst; + + if (off + len > rte_pktmbuf_pkt_len(m)) + return -1; + + while (off >= rte_pktmbuf_data_len(seg)) { + off -= rte_pktmbuf_data_len(seg); + seg = seg->next; + } + + dst = rte_pktmbuf_mtod_offset(seg, char *, off); + if (buf == dst) + return 0; + + if (off + len <= rte_pktmbuf_data_len(seg)) { + RTE_ASSERT(!rte_pktmbuf_is_shared(seg)); + rte_memcpy(dst, buf, len); + return 0; + } + + /* copy data in several segments */ + while (len > 0) { + RTE_ASSERT(!rte_pktmbuf_is_shared(seg)); + copy_len = rte_pktmbuf_data_len(seg) - off; + if (copy_len > len) + copy_len = len; + dst = rte_pktmbuf_mtod_offset(seg, char *, off); + rte_memcpy(dst, (const char *)buf + buf_off, copy_len); + off = 0; + buf_off += copy_len; + len -= copy_len; + seg = seg->next; + } + + return 0; +} + /* * Get the name of a RX offload flag. Must be kept synchronized with flag * definitions in rte_mbuf.h. diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index cd77a56..e898d25 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -1678,6 +1678,56 @@ static inline void *rte_pktmbuf_read(const struct rte_mbuf *m, } /** + * @internal used by rte_pktmbuf_write(). + */ +int __rte_pktmbuf_write(const struct rte_mbuf *m, uint32_t off, + uint32_t len, const void *buf); + +/** + * Write len data bytes in a mbuf at specified offset. + * + * If the mbuf is contiguous between off and off+len, rte_memcpy() is + * called. Else, it will split the data in the segments. + * + * The caller must ensure that all destination segments are writable + * (not shared). + * + * If the destination pointer in the mbuf is the same than the source + * buffer, the function do nothing and is successful. + * + * If the mbuf is too small, the function fails. + * + * @param m + * The pointer to the mbuf. + * @param off + * The offset of the data in the mbuf. + * @param len + * The amount of bytes to read. + * @param buf + * The buffer where data is copied if it is not contiguous in mbuf + * data. Its length should be at least equal to the len parameter. + * @return + * - (0) on success (data is updated in the mbuf) + * - (-1) on error: mbuf is too small or not writable + */ +static inline int rte_pktmbuf_write(const struct rte_mbuf *m, + uint32_t off, uint32_t len, const void *buf) +{ + char *dst = rte_pktmbuf_mtod_offset(m, char *, off); + + if (buf == dst) + return 0; + + if (off + len <= rte_pktmbuf_data_len(m)) { + RTE_ASSERT(!rte_pktmbuf_is_shared(m)); + rte_memcpy(dst, buf, len); + return 0; + } + + return __rte_pktmbuf_write(m, off, len, buf); +} + +/** * Chain an mbuf to another, thereby creating a segmented packet. * * Note: The implementation will do a linear walk over the segments to find diff --git a/lib/librte_mbuf/rte_mbuf_version.map b/lib/librte_mbuf/rte_mbuf_version.map index 6e2ea84..b2c057e 100644 --- a/lib/librte_mbuf/rte_mbuf_version.map +++ b/lib/librte_mbuf/rte_mbuf_version.map @@ -35,3 +35,9 @@ DPDK_16.11 { rte_get_tx_ol_flag_list; } DPDK_2.1; + +DPDK_17.02 { + global: + + __rte_pktmbuf_write; +} DPDK_16.11;