get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 41614,
    "url": "http://patchwork.dpdk.org/api/patches/41614/?format=api",
    "web_url": "http://patchwork.dpdk.org/project/dpdk/patch/20180627014417.84133-1-doucette@bu.edu/",
    "project": {
        "id": 1,
        "url": "http://patchwork.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": "<20180627014417.84133-1-doucette@bu.edu>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20180627014417.84133-1-doucette@bu.edu",
    "date": "2018-06-27T01:44:16",
    "name": "ip_frag: extend rte_ipv6_frag_get_ipv6_fragment_header()",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "abe34645d3cd671e3ad6ef77e5df3c8750c2f14c",
    "submitter": {
        "id": 1059,
        "url": "http://patchwork.dpdk.org/api/people/1059/?format=api",
        "name": "Cody Doucette",
        "email": "doucette@bu.edu"
    },
    "delegate": {
        "id": 1,
        "url": "http://patchwork.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patchwork.dpdk.org/project/dpdk/patch/20180627014417.84133-1-doucette@bu.edu/mbox/",
    "series": [
        {
            "id": 251,
            "url": "http://patchwork.dpdk.org/api/series/251/?format=api",
            "web_url": "http://patchwork.dpdk.org/project/dpdk/list/?series=251",
            "date": "2018-06-27T01:44:16",
            "name": "ip_frag: extend rte_ipv6_frag_get_ipv6_fragment_header()",
            "version": 1,
            "mbox": "http://patchwork.dpdk.org/series/251/mbox/"
        }
    ],
    "comments": "http://patchwork.dpdk.org/api/patches/41614/comments/",
    "check": "success",
    "checks": "http://patchwork.dpdk.org/api/patches/41614/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id 06EBD1B8F9;\n\tWed, 27 Jun 2018 03:46:05 +0200 (CEST)",
            "from relay64.bu.edu (relay64.bu.edu [128.197.228.104])\n\tby dpdk.org (Postfix) with ESMTP id DE16A1B8F8\n\tfor <dev@dpdk.org>; Wed, 27 Jun 2018 03:46:03 +0200 (CEST)",
            "from BU-AUTH (localhost.localdomain [127.0.0.1]) (authenticated\n\tbits=0)\n\tby relay64.bu.edu (8.14.3/8.14.3) with ESMTP id w5R1ioTW004441\n\t(version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO);\n\tTue, 26 Jun 2018 21:44:55 -0400"
        ],
        "X-Envelope-From": "doucette@bu.edu",
        "X-BU-AUTH": "xia1.bu.edu [128.197.41.97]",
        "From": "Cody Doucette <doucette@bu.edu>",
        "To": "Konstantin Ananyev <konstantin.ananyev@intel.com>,\n\tCristian Dumitrescu <cristian.dumitrescu@intel.com>",
        "Cc": "dev@dpdk.org, michel@digirati.com.br, Cody Doucette <doucette@bu.edu>,\n\tQiaobin Fu <qiaobinf@bu.edu>",
        "Date": "Tue, 26 Jun 2018 21:44:16 -0400",
        "Message-Id": "<20180627014417.84133-1-doucette@bu.edu>",
        "X-Mailer": "git-send-email 2.17.1",
        "Subject": "[dpdk-dev] [PATCH] ip_frag: extend\n\trte_ipv6_frag_get_ipv6_fragment_header()",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<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\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Extend rte_ipv6_frag_get_ipv6_fragment_header() to skip over any\nother IPv6 extension headers when finding the fragment header.\n\nAccording to RFC 8200, there is no guarantee that the IPv6\nFragment extension header will come before any other extension\nheader, even though it is recommended.\n\nSigned-off-by: Cody Doucette <doucette@bu.edu>\nSigned-off-by: Qiaobin Fu <qiaobinf@bu.edu>\nReviewed-by: Michel Machado <michel@digirati.com.br>\n---\n examples/ip_reassembly/main.c               |  6 ++-\n lib/librte_ip_frag/rte_ip_frag.h            | 41 ++++++++++++++-------\n lib/librte_ip_frag/rte_ip_frag_version.map  |  1 +\n lib/librte_ip_frag/rte_ipv6_fragmentation.c | 38 +++++++++++++++++++\n lib/librte_ip_frag/rte_ipv6_reassembly.c    |  4 +-\n lib/librte_port/rte_port_ras.c              |  6 ++-\n 6 files changed, 77 insertions(+), 19 deletions(-)",
    "diff": "diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c\nindex 3e8e79c21..13f2b04f1 100644\n--- a/examples/ip_reassembly/main.c\n+++ b/examples/ip_reassembly/main.c\n@@ -367,12 +367,14 @@ reassemble(struct rte_mbuf *m, uint16_t portid, uint32_t queue,\n \t\teth_hdr->ether_type = rte_be_to_cpu_16(ETHER_TYPE_IPv4);\n \t} else if (RTE_ETH_IS_IPV6_HDR(m->packet_type)) {\n \t\t/* if packet is IPv6 */\n-\t\tstruct ipv6_extension_fragment *frag_hdr;\n+\t\tconst struct ipv6_extension_fragment *frag_hdr;\n+\t\tstruct ipv6_extension_fragment frag_hdr_buf;\n \t\tstruct ipv6_hdr *ip_hdr;\n \n \t\tip_hdr = (struct ipv6_hdr *)(eth_hdr + 1);\n \n-\t\tfrag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(ip_hdr);\n+\t\tfrag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(m,\n+\t\t\tip_hdr, &frag_hdr_buf);\n \n \t\tif (frag_hdr != NULL) {\n \t\t\tstruct rte_mbuf *mo;\ndiff --git a/lib/librte_ip_frag/rte_ip_frag.h b/lib/librte_ip_frag/rte_ip_frag.h\nindex b3f3f78df..8884c8b31 100644\n--- a/lib/librte_ip_frag/rte_ip_frag.h\n+++ b/lib/librte_ip_frag/rte_ip_frag.h\n@@ -99,6 +99,12 @@ struct rte_ip_frag_tbl {\n \t__extension__ struct ip_frag_pkt pkt[0]; /**< hash table. */\n };\n \n+/** IPv6 extension header */\n+struct ipv6_opt_hdr {\n+\tuint8_t nexthdr;\n+\tuint8_t hdrlen;\n+} __attribute__((packed));\n+\n /** IPv6 fragment extension header */\n #define\tRTE_IPV6_EHDR_MF_SHIFT\t\t\t0\n #define\tRTE_IPV6_EHDR_MF_MASK\t\t\t1\n@@ -208,28 +214,37 @@ rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in,\n struct rte_mbuf *rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,\n \t\tstruct rte_ip_frag_death_row *dr,\n \t\tstruct rte_mbuf *mb, uint64_t tms, struct ipv6_hdr *ip_hdr,\n-\t\tstruct ipv6_extension_fragment *frag_hdr);\n+\t\tconst struct ipv6_extension_fragment *frag_hdr);\n+\n+static inline int\n+ipv6_ext_hdr(uint8_t nexthdr)\n+{\n+\t/* Find out if nexthdr is an extension header or a protocol. */\n+\treturn (nexthdr == IPPROTO_HOPOPTS) ||\n+\t\t(nexthdr == IPPROTO_ROUTING) ||\n+\t\t(nexthdr == IPPROTO_FRAGMENT) ||\n+\t\t(nexthdr == IPPROTO_AH) ||\n+\t\t(nexthdr == IPPROTO_NONE) ||\n+\t\t(nexthdr == IPPROTO_DSTOPTS);\n+}\n \n /**\n  * Return a pointer to the packet's fragment header, if found.\n- * It only looks at the extension header that's right after the fixed IPv6\n- * header, and doesn't follow the whole chain of extension headers.\n  *\n- * @param hdr\n+ * @param pkt\n+ *   Pointer to the mbuf of the packet.\n+ * @param ip_hdr\n  *   Pointer to the IPv6 header.\n+ * @param frag_hdr\n+ *   A pointer to the buffer where the fragment header\n+ *   will be copied if it is not contiguous in mbuf data.\n  * @return\n  *   Pointer to the IPv6 fragment extension header, or NULL if it's not\n  *   present.\n  */\n-static inline struct ipv6_extension_fragment *\n-rte_ipv6_frag_get_ipv6_fragment_header(struct ipv6_hdr *hdr)\n-{\n-\tif (hdr->proto == IPPROTO_FRAGMENT) {\n-\t\treturn (struct ipv6_extension_fragment *) ++hdr;\n-\t}\n-\telse\n-\t\treturn NULL;\n-}\n+const struct ipv6_extension_fragment *rte_ipv6_frag_get_ipv6_fragment_header(\n+\t\tstruct rte_mbuf *pkt, const struct ipv6_hdr *ip_hdr,\n+\t\tstruct ipv6_extension_fragment *frag_hdr);\n \n /**\n  * IPv4 fragmentation.\ndiff --git a/lib/librte_ip_frag/rte_ip_frag_version.map b/lib/librte_ip_frag/rte_ip_frag_version.map\nindex d1acf07cb..98fe4f2d4 100644\n--- a/lib/librte_ip_frag/rte_ip_frag_version.map\n+++ b/lib/librte_ip_frag/rte_ip_frag_version.map\n@@ -8,6 +8,7 @@ DPDK_2.0 {\n \trte_ipv4_fragment_packet;\n \trte_ipv6_frag_reassemble_packet;\n \trte_ipv6_fragment_packet;\n+\trte_ipv6_frag_get_ipv6_fragment_header;\n \n \tlocal: *;\n };\ndiff --git a/lib/librte_ip_frag/rte_ipv6_fragmentation.c b/lib/librte_ip_frag/rte_ipv6_fragmentation.c\nindex 62a7e4e83..bd847dd3d 100644\n--- a/lib/librte_ip_frag/rte_ipv6_fragmentation.c\n+++ b/lib/librte_ip_frag/rte_ipv6_fragmentation.c\n@@ -176,3 +176,41 @@ rte_ipv6_fragment_packet(struct rte_mbuf *pkt_in,\n \n \treturn out_pkt_pos;\n }\n+\n+const struct ipv6_extension_fragment *\n+rte_ipv6_frag_get_ipv6_fragment_header(struct rte_mbuf *pkt,\n+\tconst struct ipv6_hdr *ip_hdr,\n+\tstruct ipv6_extension_fragment *frag_hdr)\n+{\n+\tsize_t offset = sizeof(struct ipv6_hdr);\n+\tuint8_t nexthdr = ip_hdr->proto;\n+\n+\twhile (ipv6_ext_hdr(nexthdr)) {\n+\t\tstruct ipv6_opt_hdr opt;\n+\t\tconst struct ipv6_opt_hdr *popt = rte_pktmbuf_read(pkt,\n+\t\t\toffset, sizeof(opt), &opt);\n+\t\tif (popt == NULL)\n+\t\t\treturn NULL;\n+\n+\t\tswitch (nexthdr) {\n+\t\tcase IPPROTO_NONE:\n+\t\t\treturn NULL;\n+\n+\t\tcase IPPROTO_FRAGMENT:\n+\t\t\treturn rte_pktmbuf_read(pkt, offset,\n+\t\t\t\tsizeof(*frag_hdr), frag_hdr);\n+\n+\t\tcase IPPROTO_AH:\n+\t\t\toffset += (popt->hdrlen + 2) << 2;\n+\t\t\tbreak;\n+\n+\t\tdefault:\n+\t\t\toffset += (popt->hdrlen + 1) << 3;\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tnexthdr = popt->nexthdr;\n+\t}\n+\n+\treturn NULL;\n+}\ndiff --git a/lib/librte_ip_frag/rte_ipv6_reassembly.c b/lib/librte_ip_frag/rte_ipv6_reassembly.c\nindex db249fe60..b2d67a3f0 100644\n--- a/lib/librte_ip_frag/rte_ipv6_reassembly.c\n+++ b/lib/librte_ip_frag/rte_ipv6_reassembly.c\n@@ -135,8 +135,8 @@ ipv6_frag_reassemble(struct ip_frag_pkt *fp)\n #define FRAG_OFFSET(x) (rte_cpu_to_be_16(x) >> 3)\n struct rte_mbuf *\n rte_ipv6_frag_reassemble_packet(struct rte_ip_frag_tbl *tbl,\n-\t\tstruct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms,\n-\t\tstruct ipv6_hdr *ip_hdr, struct ipv6_extension_fragment *frag_hdr)\n+\tstruct rte_ip_frag_death_row *dr, struct rte_mbuf *mb, uint64_t tms,\n+\tstruct ipv6_hdr *ip_hdr, const struct ipv6_extension_fragment *frag_hdr)\n {\n \tstruct ip_frag_pkt *fp;\n \tstruct ip_frag_key key;\ndiff --git a/lib/librte_port/rte_port_ras.c b/lib/librte_port/rte_port_ras.c\nindex c8b2e19bf..28764f744 100644\n--- a/lib/librte_port/rte_port_ras.c\n+++ b/lib/librte_port/rte_port_ras.c\n@@ -184,9 +184,11 @@ process_ipv6(struct rte_port_ring_writer_ras *p, struct rte_mbuf *pkt)\n \t/* Assume there is no ethernet header */\n \tstruct ipv6_hdr *pkt_hdr = rte_pktmbuf_mtod(pkt, struct ipv6_hdr *);\n \n-\tstruct ipv6_extension_fragment *frag_hdr;\n+\tconst struct ipv6_extension_fragment *frag_hdr;\n+\tstruct ipv6_extension_fragment frag_hdr_buf;\n \tuint16_t frag_data = 0;\n-\tfrag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt_hdr);\n+\tfrag_hdr = rte_ipv6_frag_get_ipv6_fragment_header(pkt, pkt_hdr,\n+\t\t&frag_hdr_buf);\n \tif (frag_hdr != NULL)\n \t\tfrag_data = rte_be_to_cpu_16(frag_hdr->frag_data);\n \n",
    "prefixes": []
}