From patchwork Thu Jan 12 09:40:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tomasz Kulasek X-Patchwork-Id: 19259 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 09CE7F91B; Thu, 12 Jan 2017 10:43:08 +0100 (CET) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 0BBC1F8C0 for ; Thu, 12 Jan 2017 10:43:05 +0100 (CET) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP; 12 Jan 2017 01:43:05 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,349,1477983600"; d="scan'208";a="29419403" Received: from unknown (HELO Sent) ([10.103.102.79]) by orsmga002.jf.intel.com with SMTP; 12 Jan 2017 01:43:02 -0800 Received: by Sent (sSMTP sendmail emulation); Thu, 12 Jan 2017 10:40:55 +0100 From: Tomasz Kulasek To: dev@dpdk.org Cc: Pablo de Lara , Olivier Matz Date: Thu, 12 Jan 2017 10:40:44 +0100 Message-Id: <1484214044-9432-1-git-send-email-tomaszx.kulasek@intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1483634640-33892-1-git-send-email-tomaszx.kulasek@intel.com> References: <1483634640-33892-1-git-send-email-tomaszx.kulasek@intel.com> Subject: [dpdk-dev] [PATCH v5] mbuf: add a function to linearize a packet X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" This patch adds function rte_pktmbuf_linearize to let crypto PMD coalesce chained mbuf before crypto operation and extend their capabilities to support segmented mbufs when device cannot handle them natively. Included unit tests for rte_pktmbuf_linearize functionality: 1) Creates banch of segmented mbufs with different size and number of segments. 2) Fills noncontigouos mbuf with sequential values. 3) Uses rte_pktmbuf_linearize to coalesce segmented buffer into one contiguous. 4) Verifies data in linearized buffer. Dependencies: This patch is rebased to the dpdk-next-crypto and should be applied before "Chained Mbufs support in SW PMDs" patchset. changes in v5: - name of patch changed, - improved coding style, changes in v4: - separated from "Chained Mbufs support in SW PMDs" patch set for better reviewing, - merged "rte_pktmbuf_linearize" implementation with unit tests, changes in v3: - rebased to dpdk-next-crypto changes in v2: - rte_pktmbuf_coalesce replaced with rte_pktmbuf_linearize Cc: Pablo de Lara Cc: Olivier Matz Signed-off-by: Tomasz Kulasek Acked-by: Olivier Matz --- app/test/test_mbuf.c | 123 ++++++++++++++++++++++++++++++++++++++++++++ lib/librte_mbuf/rte_mbuf.h | 51 ++++++++++++++++++ 2 files changed, 174 insertions(+) diff --git a/app/test/test_mbuf.c b/app/test/test_mbuf.c index c0823ea..a2e9bc6 100644 --- a/app/test/test_mbuf.c +++ b/app/test/test_mbuf.c @@ -930,6 +930,124 @@ return 0; } +static int +test_mbuf_linearize(int pkt_len, int nb_segs) { + + struct rte_mbuf *m = NULL, *mbuf = NULL; + uint8_t *data; + int data_len = 0; + int remain; + int seg, seg_len; + int i; + + if (pkt_len < 1) { + printf("Packet size must be 1 or more (is %d)\n", pkt_len); + return -1; + } + + if (nb_segs < 1) { + printf("Number of segments must be 1 or more (is %d)\n", + nb_segs); + return -1; + } + + seg_len = pkt_len / nb_segs; + if (seg_len == 0) + seg_len = 1; + + remain = pkt_len; + + /* Create chained mbuf_src and fill it generated data */ + for (seg = 0; remain > 0; seg++) { + + m = rte_pktmbuf_alloc(pktmbuf_pool); + if (m == NULL) { + printf("Cannot create segment for source mbuf"); + goto fail; + } + + /* Make sure if tailroom is zeroed */ + memset(rte_pktmbuf_mtod(m, uint8_t *), 0, + rte_pktmbuf_tailroom(m)); + + data_len = remain; + if (data_len > seg_len) + data_len = seg_len; + + data = (uint8_t *)rte_pktmbuf_append(m, data_len); + if (data == NULL) { + printf("Cannot append %d bytes to the mbuf\n", + data_len); + goto fail; + } + + for (i = 0; i < data_len; i++) + data[i] = (seg * seg_len + i) % 0x0ff; + + if (seg == 0) + mbuf = m; + else + rte_pktmbuf_chain(mbuf, m); + + remain -= data_len; + } + + /* Create destination buffer to store coalesced data */ + if (rte_pktmbuf_linearize(mbuf)) { + printf("Mbuf linearization failed\n"); + goto fail; + } + + if (!rte_pktmbuf_is_contiguous(mbuf)) { + printf("Source buffer should be contiguous after " + "linearization\n"); + goto fail; + } + + data = rte_pktmbuf_mtod(mbuf, uint8_t *); + + for (i = 0; i < pkt_len; i++) + if (data[i] != (i % 0x0ff)) { + printf("Incorrect data in linearized mbuf\n"); + goto fail; + } + + rte_pktmbuf_free(mbuf); + return 0; + +fail: + if (mbuf) + rte_pktmbuf_free(mbuf); + return -1; +} + +static int +test_mbuf_linearize_check(void) +{ + struct test_mbuf_array { + int size; + int nb_segs; + } mbuf_array[] = { + { 128, 1 }, + { 64, 64 }, + { 512, 10 }, + { 250, 11 }, + { 123, 8 }, + }; + unsigned int i; + + printf("Test mbuf linearize API\n"); + + for (i = 0; i < RTE_DIM(mbuf_array); i++) + if (test_mbuf_linearize(mbuf_array[i].size, + mbuf_array[i].nb_segs)) { + printf("Test failed for %d, %d\n", mbuf_array[i].size, + mbuf_array[i].nb_segs); + return -1; + } + + return 0; +} static int test_mbuf(void) @@ -1023,6 +1141,11 @@ printf("test_failing_mbuf_sanity_check() failed\n"); return -1; } + + if (test_mbuf_linearize_check() < 0) { + printf("test_mbuf_linearize_check() failed\n"); + return -1; + } return 0; } diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index ead7c6e..8fd0766 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -1647,6 +1647,57 @@ static inline int rte_pktmbuf_chain(struct rte_mbuf *head, struct rte_mbuf *tail } /** + * Linearize data in mbuf. + * + * This function moves the mbuf data in the first segment if there is enough + * tailroom. The subsequent segments are unchained and freed. + * + * @param mbuf + * mbuf to linearize + * @return + * - 0, on success + * - -1, on error + */ +static inline int +rte_pktmbuf_linearize(struct rte_mbuf *mbuf) +{ + int seg_len, copy_len; + struct rte_mbuf *m; + struct rte_mbuf *m_next; + char *buffer; + + if (rte_pktmbuf_is_contiguous(mbuf)) + return 0; + + /* Extend first segment to the total packet length */ + copy_len = rte_pktmbuf_pkt_len(mbuf) - rte_pktmbuf_data_len(mbuf); + + if (unlikely(copy_len > rte_pktmbuf_tailroom(mbuf))) + return -1; + + buffer = rte_pktmbuf_mtod_offset(mbuf, char *, mbuf->data_len); + mbuf->data_len = (uint16_t)(mbuf->pkt_len); + + /* Append data from next segments to the first one */ + m = mbuf->next; + while (m != NULL) { + m_next = m->next; + + seg_len = rte_pktmbuf_data_len(m); + rte_memcpy(buffer, rte_pktmbuf_mtod(m, char *), seg_len); + buffer += seg_len; + + rte_pktmbuf_free_seg(m); + m = m_next; + } + + mbuf->next = NULL; + mbuf->nb_segs = 1; + + return 0; +} + +/** * Dump an mbuf structure to a file. * * Dump all fields for the given packet mbuf and all its associated