get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/114689/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 114689,
    "url": "http://patches.dpdk.org/api/patches/114689/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1659923292-3378-1-git-send-email-chcchc88@163.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1659923292-3378-1-git-send-email-chcchc88@163.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1659923292-3378-1-git-send-email-chcchc88@163.com",
    "date": "2022-08-08T01:48:12",
    "name": "[v7] ip_frag: add IPv4 fragment copy packet API",
    "commit_ref": null,
    "pull_url": null,
    "state": "accepted",
    "archived": true,
    "hash": "125bb2014b3f3f2ac68b9c47b5808dd1009f460e",
    "submitter": {
        "id": 2371,
        "url": "http://patches.dpdk.org/api/people/2371/?format=api",
        "name": "Huichao Cai",
        "email": "chcchc88@163.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1659923292-3378-1-git-send-email-chcchc88@163.com/mbox/",
    "series": [
        {
            "id": 24218,
            "url": "http://patches.dpdk.org/api/series/24218/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=24218",
            "date": "2022-08-08T01:48:12",
            "name": "[v7] ip_frag: add IPv4 fragment copy packet API",
            "version": 7,
            "mbox": "http://patches.dpdk.org/series/24218/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/114689/comments/",
    "check": "fail",
    "checks": "http://patches.dpdk.org/api/patches/114689/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 94CE0A00C2;\n\tMon,  8 Aug 2022 03:48:34 +0200 (CEST)",
            "from [217.70.189.124] (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 2D00E4014F;\n\tMon,  8 Aug 2022 03:48:34 +0200 (CEST)",
            "from m12-13.163.com (m12-13.163.com [220.181.12.13])\n by mails.dpdk.org (Postfix) with ESMTP id A7905400D7\n for <dev@dpdk.org>; Mon,  8 Aug 2022 03:48:32 +0200 (CEST)",
            "from bogon.localdomain (unknown [36.111.88.33])\n by smtp9 (Coremail) with SMTP id DcCowAAnixBna_BiksyzWQ--.45261S2;\n Mon, 08 Aug 2022 09:48:27 +0800 (CST)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com;\n s=s110527; h=From:Subject:Date:Message-Id; bh=rpaiaWtMvvsRMvq8Ya\n +8gUhR3zIHCXYFpgfmsSXC3+0=; b=MYD9k4jxzIcB3ttrhYP22sdsJasYz35rDm\n 3POqvEsTxy+jWQPZmZThxd6aZLzbhCo0U2xNkh5GoUtY33TZI4SdeAK0PUfta5Zx\n OSIBr7zU3QlDs7X+BhIECyb3IKbwBY3mJiDKQf8u0Y3DZI0AXltjph2d94X0VBHC\n zS2v2xfl4=",
        "From": "Huichao Cai <chcchc88@163.com>",
        "To": "dev@dpdk.org",
        "Cc": "konstantin.v.ananyev@yandex.ru",
        "Subject": "[PATCH v7] ip_frag: add IPv4 fragment copy packet API",
        "Date": "Mon,  8 Aug 2022 09:48:12 +0800",
        "Message-Id": "<1659923292-3378-1-git-send-email-chcchc88@163.com>",
        "X-Mailer": "git-send-email 1.8.3.1",
        "In-Reply-To": "<1658650203-7831-1-git-send-email-chcchc88@163.com>",
        "References": "<1658650203-7831-1-git-send-email-chcchc88@163.com>",
        "X-CM-TRANSID": "DcCowAAnixBna_BiksyzWQ--.45261S2",
        "X-Coremail-Antispam": "1Uf129KBjvJXoW3GFy3JFy7Ww1rArW3tw45GFg_yoWfWr4xpa\n 13KrWkZrn5Jrn3Gwn7Xw45Zay3KasagrW2grZ3ur9Iyr47K3sYgFW7Kr1YkryaqrykAr9a\n vwsFvFn8Cw47Xa7anT9S1TB71UUUUUUqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2\n 9KBjDUYxBIdaVFxhVjvjDU0xZFpf9x07UpE_iUUUUU=",
        "X-Originating-IP": "[36.111.88.33]",
        "X-CM-SenderInfo": "pfkfuxrfyyqiywtou0bp/1tbiJgNWF1v2m3OnPAABs7",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Some NIC drivers support MBUF_FAST_FREE(Device supports optimization\nfor fast release of mbufs. When set application must guarantee that\nper-queue all mbufs comes from the same mempool,has refcnt = 1,direct\nand non-segmented.)offload. In order to adapt to this offload function,\nadd this API. Add some test data for this API.\n\nSigned-off-by: Huichao Cai <chcchc88@163.com>\n---\n app/test/test_ipfrag.c               |   9 +-\n lib/ip_frag/rte_ip_frag.h            |  34 +++++++\n lib/ip_frag/rte_ipv4_fragmentation.c | 174 +++++++++++++++++++++++++++++++++++\n lib/ip_frag/version.map              |   1 +\n 4 files changed, 217 insertions(+), 1 deletion(-)",
    "diff": "diff --git a/app/test/test_ipfrag.c b/app/test/test_ipfrag.c\nindex ba0ffd0..88cc4cd 100644\n--- a/app/test/test_ipfrag.c\n+++ b/app/test/test_ipfrag.c\n@@ -418,10 +418,17 @@ static void ut_teardown(void)\n \t\t}\n \n \t\tif (tests[i].ipv == 4)\n-\t\t\tlen = rte_ipv4_fragment_packet(b, pkts_out, BURST,\n+\t\t\tif (i % 2)\n+\t\t\t\tlen = rte_ipv4_fragment_packet(b, pkts_out, BURST,\n \t\t\t\t\t\t       tests[i].mtu_size,\n \t\t\t\t\t\t       direct_pool,\n \t\t\t\t\t\t       indirect_pool);\n+\t\t\telse\n+\t\t\t\tlen = rte_ipv4_fragment_copy_nonseg_packet(b,\n+\t\t\t\t\t\t       pkts_out,\n+\t\t\t\t\t\t       BURST,\n+\t\t\t\t\t\t       tests[i].mtu_size,\n+\t\t\t\t\t\t       direct_pool);\n \t\telse if (tests[i].ipv == 6)\n \t\t\tlen = rte_ipv6_fragment_packet(b, pkts_out, BURST,\n \t\t\t\t\t\t       tests[i].mtu_size,\ndiff --git a/lib/ip_frag/rte_ip_frag.h b/lib/ip_frag/rte_ip_frag.h\nindex 7d2abe1..4a2b150 100644\n--- a/lib/ip_frag/rte_ip_frag.h\n+++ b/lib/ip_frag/rte_ip_frag.h\n@@ -179,6 +179,40 @@ int32_t rte_ipv4_fragment_packet(struct rte_mbuf *pkt_in,\n \t\t\tstruct rte_mempool *pool_indirect);\n \n /**\n+ * IPv4 fragmentation by copy.\n+ *\n+ * This function implements the fragmentation of IPv4 packets by copy\n+ * non-segmented mbuf.\n+ * This function is mainly used to adapt TX MBUF_FAST_FREE offload.\n+ * MBUF_FAST_FREE: Device supports optimization for fast release of mbufs.\n+ * When set application must guarantee that per-queue all mbufs comes from\n+ * the same mempool,has refcnt = 1,direct and non-segmented.\n+ *\n+ * @param pkt_in\n+ *   The input packet.\n+ * @param pkts_out\n+ *   Array storing the output fragments.\n+ * @param nb_pkts_out\n+ *   Number of fragments.\n+ * @param mtu_size\n+ *   Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv4\n+ *   datagrams. This value includes the size of the IPv4 header.\n+ * @param pool_direct\n+ *   MBUF pool used for allocating direct buffers for the output fragments.\n+ * @return\n+ *   Upon successful completion - number of output fragments placed\n+ *   in the pkts_out array.\n+ *   Otherwise - (-1) * errno.\n+ */\n+__rte_experimental\n+int32_t\n+rte_ipv4_fragment_copy_nonseg_packet(struct rte_mbuf *pkt_in,\n+\tstruct rte_mbuf **pkts_out,\n+\tuint16_t nb_pkts_out,\n+\tuint16_t mtu_size,\n+\tstruct rte_mempool *pool_direct);\n+\n+/**\n  * This function implements reassembly of fragmented IPv4 packets.\n  * Incoming mbufs should have its l2_len/l3_len fields setup correctly.\n  *\ndiff --git a/lib/ip_frag/rte_ipv4_fragmentation.c b/lib/ip_frag/rte_ipv4_fragmentation.c\nindex 27a8ad2..ef5e1c5 100644\n--- a/lib/ip_frag/rte_ipv4_fragmentation.c\n+++ b/lib/ip_frag/rte_ipv4_fragmentation.c\n@@ -259,3 +259,177 @@ static inline uint16_t __create_ipopt_frag_hdr(uint8_t *iph,\n \n \treturn out_pkt_pos;\n }\n+\n+/**\n+ * IPv4 fragmentation by copy.\n+ *\n+ * This function implements the fragmentation of IPv4 packets by copy\n+ * non-segmented mbuf.\n+ * This function is mainly used to adapt TX MBUF_FAST_FREE offload.\n+ * MBUF_FAST_FREE: Device supports optimization for fast release of mbufs.\n+ * When set application must guarantee that per-queue all mbufs comes from\n+ * the same mempool,has refcnt = 1,direct and non-segmented.\n+ *\n+ * @param pkt_in\n+ *   The input packet.\n+ * @param pkts_out\n+ *   Array storing the output fragments.\n+ * @param nb_pkts_out\n+ *   Number of fragments.\n+ * @param mtu_size\n+ *   Size in bytes of the Maximum Transfer Unit (MTU) for the outgoing IPv4\n+ *   datagrams. This value includes the size of the IPv4 header.\n+ * @param pool_direct\n+ *   MBUF pool used for allocating direct buffers for the output fragments.\n+ * @return\n+ *   Upon successful completion - number of output fragments placed\n+ *   in the pkts_out array.\n+ *   Otherwise - (-1) * errno.\n+ */\n+int32_t\n+rte_ipv4_fragment_copy_nonseg_packet(struct rte_mbuf *pkt_in,\n+\tstruct rte_mbuf **pkts_out,\n+\tuint16_t nb_pkts_out,\n+\tuint16_t mtu_size,\n+\tstruct rte_mempool *pool_direct)\n+{\n+\tstruct rte_mbuf *in_seg = NULL;\n+\tstruct rte_ipv4_hdr *in_hdr;\n+\tuint32_t out_pkt_pos, in_seg_data_pos;\n+\tuint32_t more_in_segs;\n+\tuint16_t fragment_offset, flag_offset, frag_size, header_len;\n+\tuint16_t frag_bytes_remaining;\n+\tuint8_t ipopt_frag_hdr[IPV4_HDR_MAX_LEN];\n+\tuint16_t ipopt_len;\n+\n+\t/*\n+\t * Formal parameter checking.\n+\t */\n+\tif (unlikely(pkt_in == NULL) || unlikely(pkts_out == NULL) ||\n+\t    unlikely(nb_pkts_out == 0) || unlikely(pool_direct == NULL) ||\n+\t    unlikely(mtu_size < RTE_ETHER_MIN_MTU))\n+\t\treturn -EINVAL;\n+\n+\tin_hdr = rte_pktmbuf_mtod(pkt_in, struct rte_ipv4_hdr *);\n+\theader_len = (in_hdr->version_ihl & RTE_IPV4_HDR_IHL_MASK) *\n+\t    RTE_IPV4_IHL_MULTIPLIER;\n+\n+\t/* Check IP header length */\n+\tif (unlikely(pkt_in->data_len < header_len) ||\n+\t    unlikely(mtu_size < header_len))\n+\t\treturn -EINVAL;\n+\n+\t/*\n+\t * Ensure the IP payload length of all fragments is aligned to a\n+\t * multiple of 8 bytes as per RFC791 section 2.3.\n+\t */\n+\tfrag_size = RTE_ALIGN_FLOOR((mtu_size - header_len),\n+\t\t\t\t    IPV4_HDR_FO_ALIGN);\n+\n+\tflag_offset = rte_cpu_to_be_16(in_hdr->fragment_offset);\n+\n+\t/* If Don't Fragment flag is set */\n+\tif (unlikely((flag_offset & IPV4_HDR_DF_MASK) != 0))\n+\t\treturn -ENOTSUP;\n+\n+\t/* Check that pkts_out is big enough to hold all fragments */\n+\tif (unlikely(frag_size * nb_pkts_out <\n+\t    (uint16_t)(pkt_in->pkt_len - header_len)))\n+\t\treturn -EINVAL;\n+\n+\tin_seg = pkt_in;\n+\tin_seg_data_pos = header_len;\n+\tout_pkt_pos = 0;\n+\tfragment_offset = 0;\n+\n+\tipopt_len = header_len - sizeof(struct rte_ipv4_hdr);\n+\tif (unlikely(ipopt_len > RTE_IPV4_HDR_OPT_MAX_LEN))\n+\t\treturn -EINVAL;\n+\n+\tmore_in_segs = 1;\n+\twhile (likely(more_in_segs)) {\n+\t\tstruct rte_mbuf *out_pkt = NULL;\n+\t\tuint32_t more_out_segs;\n+\t\tstruct rte_ipv4_hdr *out_hdr;\n+\n+\t\t/* Allocate direct buffer */\n+\t\tout_pkt = rte_pktmbuf_alloc(pool_direct);\n+\t\tif (unlikely(out_pkt == NULL)) {\n+\t\t\t__free_fragments(pkts_out, out_pkt_pos);\n+\t\t\treturn -ENOMEM;\n+\t\t}\n+\t\tif (unlikely(rte_pktmbuf_tailroom(out_pkt) < frag_size)) {\n+\t\t\trte_pktmbuf_free(out_pkt);\n+\t\t\t__free_fragments(pkts_out, out_pkt_pos);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\t/* Reserve space for the IP header that will be built later */\n+\t\tout_pkt->data_len = header_len;\n+\t\tout_pkt->pkt_len = header_len;\n+\t\tfrag_bytes_remaining = frag_size;\n+\n+\t\tmore_out_segs = 1;\n+\t\twhile (likely(more_out_segs && more_in_segs)) {\n+\t\t\tuint32_t len;\n+\n+\t\t\tlen = frag_bytes_remaining;\n+\t\t\tif (len > (in_seg->data_len - in_seg_data_pos))\n+\t\t\t\tlen = in_seg->data_len - in_seg_data_pos;\n+\n+\t\t\tmemcpy(rte_pktmbuf_mtod_offset(out_pkt, char *,\n+\t\t\t\t\tout_pkt->data_len),\n+\t\t\t\trte_pktmbuf_mtod_offset(in_seg, char *,\n+\t\t\t\t\tin_seg_data_pos),\n+\t\t\t\tlen);\n+\n+\t\t\tin_seg_data_pos += len;\n+\t\t\tfrag_bytes_remaining -= len;\n+\t\t\tout_pkt->data_len += len;\n+\n+\t\t\t/* Current output packet (i.e. fragment) done ? */\n+\t\t\tif (unlikely(frag_bytes_remaining == 0))\n+\t\t\t\tmore_out_segs = 0;\n+\n+\t\t\t/* Current input segment done ? */\n+\t\t\tif (unlikely(in_seg_data_pos == in_seg->data_len)) {\n+\t\t\t\tin_seg = in_seg->next;\n+\t\t\t\tin_seg_data_pos = 0;\n+\n+\t\t\t\tif (unlikely(in_seg == NULL))\n+\t\t\t\t\tmore_in_segs = 0;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* Build the IP header */\n+\n+\t\tout_pkt->pkt_len = out_pkt->data_len;\n+\t\tout_hdr = rte_pktmbuf_mtod(out_pkt, struct rte_ipv4_hdr *);\n+\n+\t\t__fill_ipv4hdr_frag(out_hdr, in_hdr, header_len,\n+\t\t    (uint16_t)out_pkt->pkt_len,\n+\t\t    flag_offset, fragment_offset, more_in_segs);\n+\n+\t\tif (unlikely((fragment_offset == 0) && (ipopt_len) &&\n+\t\t\t    ((flag_offset & RTE_IPV4_HDR_OFFSET_MASK) == 0))) {\n+\t\t\tipopt_len = __create_ipopt_frag_hdr((uint8_t *)in_hdr,\n+\t\t\t\tipopt_len, ipopt_frag_hdr);\n+\t\t\tfragment_offset = (uint16_t)(fragment_offset +\n+\t\t\t\tout_pkt->pkt_len - header_len);\n+\t\t\tout_pkt->l3_len = header_len;\n+\n+\t\t\theader_len = sizeof(struct rte_ipv4_hdr) + ipopt_len;\n+\t\t\tin_hdr = (struct rte_ipv4_hdr *)ipopt_frag_hdr;\n+\t\t} else {\n+\t\t\tfragment_offset = (uint16_t)(fragment_offset +\n+\t\t\t\tout_pkt->pkt_len - header_len);\n+\t\t\tout_pkt->l3_len = header_len;\n+\t\t}\n+\n+\t\t/* Write the fragment to the output list */\n+\t\tpkts_out[out_pkt_pos] = out_pkt;\n+\t\tout_pkt_pos++;\n+\t}\n+\n+\treturn out_pkt_pos;\n+}\ndiff --git a/lib/ip_frag/version.map b/lib/ip_frag/version.map\nindex b9c1cca..8aad839 100644\n--- a/lib/ip_frag/version.map\n+++ b/lib/ip_frag/version.map\n@@ -17,4 +17,5 @@ EXPERIMENTAL {\n \tglobal:\n \n \trte_ip_frag_table_del_expired_entries;\n+\trte_ipv4_fragment_copy_nonseg_packet;\n };\n",
    "prefixes": [
        "v7"
    ]
}