get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 807190,
    "url": "http://patchwork.ozlabs.org/api/patches/807190/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170829171942.8974-4-tom@quantonium.net/",
    "project": {
        "id": 7,
        "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api",
        "name": "Linux network development",
        "link_name": "netdev",
        "list_id": "netdev.vger.kernel.org",
        "list_email": "netdev@vger.kernel.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20170829171942.8974-4-tom@quantonium.net>",
    "list_archive_url": null,
    "date": "2017-08-29T17:19:39",
    "name": "[net-next,3/6] flow_dissector: Add protocol specific flow dissection offload",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "98ee713849437d287870c9b2ed1cec097db53ed7",
    "submitter": {
        "id": 72064,
        "url": "http://patchwork.ozlabs.org/api/people/72064/?format=api",
        "name": "Tom Herbert",
        "email": "tom@quantonium.net"
    },
    "delegate": {
        "id": 34,
        "url": "http://patchwork.ozlabs.org/api/users/34/?format=api",
        "username": "davem",
        "first_name": "David",
        "last_name": "Miller",
        "email": "davem@davemloft.net"
    },
    "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170829171942.8974-4-tom@quantonium.net/mbox/",
    "series": [
        {
            "id": 418,
            "url": "http://patchwork.ozlabs.org/api/series/418/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=418",
            "date": "2017-08-29T17:19:36",
            "name": "flow_dissector: Protocol specific flow dissector offload",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/418/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/807190/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/807190/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<netdev-owner@vger.kernel.org>",
        "X-Original-To": "patchwork-incoming@ozlabs.org",
        "Delivered-To": "patchwork-incoming@ozlabs.org",
        "Authentication-Results": [
            "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)",
            "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=quantonium-net.20150623.gappssmtp.com\n\theader.i=@quantonium-net.20150623.gappssmtp.com\n\theader.b=\"s9p7a69L\"; dkim-atps=neutral"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xhb4Q1d3cz9s76\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 03:20:22 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751330AbdH2RUU (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tTue, 29 Aug 2017 13:20:20 -0400",
            "from mail-pf0-f176.google.com ([209.85.192.176]:32892 \"EHLO\n\tmail-pf0-f176.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751242AbdH2RUR (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Tue, 29 Aug 2017 13:20:17 -0400",
            "by mail-pf0-f176.google.com with SMTP id r62so12050128pfj.0\n\tfor <netdev@vger.kernel.org>; Tue, 29 Aug 2017 10:20:16 -0700 (PDT)",
            "from localhost.localdomain (67-207-98-108.static.wiline.com.\n\t[67.207.98.108]) by smtp.gmail.com with ESMTPSA id\n\tg63sm5694902pfb.79.2017.08.29.10.20.14\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tTue, 29 Aug 2017 10:20:15 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=quantonium-net.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=b6k/ywtkCXDoSlqNAp9qatD0hwhSEqmFMXmMzbNuWy0=;\n\tb=s9p7a69LbW6n3jxdelg3ORnWgp9S8WCVup6HVOzfImc5itUj8JISxMsWYu8pbIfSft\n\tawFUOeHva0x9nhIYft61JunwRCPiv2BR7tzJlkZCiH3/BFEnNjVyYg/vpEU7ilepvL01\n\t2w8/o6AyJzd0QIZkryzNPR1IZ95zm+elKDaHwUiAGFXxKAfKX7F3kbatSOPP9Kkng2or\n\t9S61HJPnilbmmRVsoymH4v/5ceGWZb2e35PeTOjd9n/9UvrqHvGQk1/fyD2D2ra/GKxI\n\txjMXwy4jQ5MdVAeRUXNBfd3v6Eyjoek0nZxWJYN2VvQD81YZBN10uS9vB+dsub1S4+7y\n\tnwhQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=b6k/ywtkCXDoSlqNAp9qatD0hwhSEqmFMXmMzbNuWy0=;\n\tb=WuBn+3sCtIEq/m3Rz5DImP7jeSOYiiIN+ooPHx3mm3hL6vynbJmycD+1lpiKZbh2vV\n\t4xvV/aggnb7g5cxxMLRIQvmkLwGHdooZfVsFf/IEmnFp/GwnXeIywRQ582l2/SZXykVR\n\tL74X6/ZT6kXhpkKkPLjArnZBo0nx5kYUgSzQmYhYnBMz7POiouWVpYQkKgmRr7WOg/ms\n\tmJgToIB8YRcaP82bDcB5Rp6ZulI5fY6Xl6tZcwy7rzgqLrHW2bu6d4lAiuld4N6iwlgO\n\t7PjwHFm6R/Ooxwu+bJfQLmBAstT1EnK4rYnBqxoyXwPV8tslNEhj4EMelTNX+ZTjAacY\n\tdWFg==",
        "X-Gm-Message-State": "AHYfb5hLkrkSIKi8MVGqBKsF1FaQDPsnBV8s7GlybO5vd9Hc543IhW3S\n\tUazcCcv0G+212Qwj",
        "X-Received": "by 10.84.217.215 with SMTP id d23mr1331131plj.169.1504027216264; \n\tTue, 29 Aug 2017 10:20:16 -0700 (PDT)",
        "From": "Tom Herbert <tom@quantonium.net>",
        "To": "davem@davemloft.net",
        "Cc": "netdev@vger.kernel.org, Tom Herbert <tom@quantonium.net>",
        "Subject": "[PATCH net-next 3/6] flow_dissector: Add protocol specific flow\n\tdissection offload",
        "Date": "Tue, 29 Aug 2017 10:19:39 -0700",
        "Message-Id": "<20170829171942.8974-4-tom@quantonium.net>",
        "X-Mailer": "git-send-email 2.11.0",
        "In-Reply-To": "<20170829171942.8974-1-tom@quantonium.net>",
        "References": "<20170829171942.8974-1-tom@quantonium.net>",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "Add offload capability for performing protocol specific flow dissection\n(either by EtherType or IP protocol).\n\nSpecifically:\n\n- Add flow_dissect to offload callbacks\n- Move flow_dissect_ret enum to flow_dissector.h, cleanup names and add a\n  couple of values\n- Create GOTO_BY_RESULT macro to use in the main flow dissector switch to\n  simplify handling of functions that return flow_dissect_ret enum\n- In __skb_flow_dissect, add default case for switch(proto) as well as\n  switch(ip_proto) that looks up and calls protocol specific flow\n  dissection\n---\n include/linux/netdevice.h    |   7 +++\n include/net/flow_dissector.h |   9 +++\n net/core/dev.c               |  14 +++++\n net/core/flow_dissector.c    | 132 +++++++++++++++++++++++++++++++------------\n net/ipv4/route.c             |   4 +-\n 5 files changed, 128 insertions(+), 38 deletions(-)",
    "diff": "diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h\nindex c5475b37a631..90ccb434e127 100644\n--- a/include/linux/netdevice.h\n+++ b/include/linux/netdevice.h\n@@ -2208,6 +2208,12 @@ struct offload_callbacks {\n \tstruct sk_buff\t\t**(*gro_receive)(struct sk_buff **head,\n \t\t\t\t\t\t struct sk_buff *skb);\n \tint\t\t\t(*gro_complete)(struct sk_buff *skb, int nhoff);\n+\tenum flow_dissect_ret (*flow_dissect)(const struct sk_buff *skb,\n+\t\t\tstruct flow_dissector_key_control *key_control,\n+\t\t\tstruct flow_dissector *flow_dissector,\n+\t\t\tvoid *target_container, void *data,\n+\t\t\t__be16 *p_proto, u8 *p_ip_proto, int *p_nhoff,\n+\t\t\tint *p_hlen, unsigned int flags);\n };\n \n struct packet_offload {\n@@ -3253,6 +3259,7 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi);\n gro_result_t napi_gro_frags(struct napi_struct *napi);\n struct packet_offload *gro_find_receive_by_type(__be16 type);\n struct packet_offload *gro_find_complete_by_type(__be16 type);\n+struct packet_offload *flow_dissect_find_by_type(__be16 type);\n \n static inline void napi_free_frags(struct napi_struct *napi)\n {\ndiff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h\nindex e2663e900b0a..ad75bbfd1c9c 100644\n--- a/include/net/flow_dissector.h\n+++ b/include/net/flow_dissector.h\n@@ -19,6 +19,14 @@ struct flow_dissector_key_control {\n #define FLOW_DIS_FIRST_FRAG\tBIT(1)\n #define FLOW_DIS_ENCAPSULATION\tBIT(2)\n \n+enum flow_dissect_ret {\n+\tFLOW_DISSECT_RET_OUT_GOOD,\n+\tFLOW_DISSECT_RET_OUT_BAD,\n+\tFLOW_DISSECT_RET_PROTO_AGAIN,\n+\tFLOW_DISSECT_RET_IPPROTO_AGAIN,\n+\tFLOW_DISSECT_RET_CONTINUE,\n+};\n+\n /**\n  * struct flow_dissector_key_basic:\n  * @thoff: Transport header offset\n@@ -205,6 +213,7 @@ enum flow_dissector_key_id {\n #define FLOW_DISSECTOR_F_STOP_AT_L3\t\tBIT(1)\n #define FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL\tBIT(2)\n #define FLOW_DISSECTOR_F_STOP_AT_ENCAP\t\tBIT(3)\n+#define FLOW_DISSECTOR_F_STOP_AT_L4\t\tBIT(4)\n \n struct flow_dissector_key {\n \tenum flow_dissector_key_id key_id;\ndiff --git a/net/core/dev.c b/net/core/dev.c\nindex 270b54754821..22ea8daa930c 100644\n--- a/net/core/dev.c\n+++ b/net/core/dev.c\n@@ -4860,6 +4860,20 @@ struct packet_offload *gro_find_receive_by_type(__be16 type)\n }\n EXPORT_SYMBOL(gro_find_receive_by_type);\n \n+struct packet_offload *flow_dissect_find_by_type(__be16 type)\n+{\n+\tstruct list_head *offload_head = &offload_base;\n+\tstruct packet_offload *ptype;\n+\n+\tlist_for_each_entry_rcu(ptype, offload_head, list) {\n+\t\tif (ptype->type != type || !ptype->callbacks.flow_dissect)\n+\t\t\tcontinue;\n+\t\treturn ptype;\n+\t}\n+\treturn NULL;\n+}\n+EXPORT_SYMBOL(flow_dissect_find_by_type);\n+\n struct packet_offload *gro_find_complete_by_type(__be16 type)\n {\n \tstruct list_head *offload_head = &offload_base;\ndiff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c\nindex 12302acdb073..6a2cf240069a 100644\n--- a/net/core/flow_dissector.c\n+++ b/net/core/flow_dissector.c\n@@ -9,6 +9,7 @@\n #include <net/ipv6.h>\n #include <net/gre.h>\n #include <net/pptp.h>\n+#include <net/protocol.h>\n #include <linux/igmp.h>\n #include <linux/icmp.h>\n #include <linux/sctp.h>\n@@ -115,12 +116,6 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,\n }\n EXPORT_SYMBOL(__skb_flow_get_ports);\n \n-enum flow_dissect_ret {\n-\tFLOW_DISSECT_RET_OUT_GOOD,\n-\tFLOW_DISSECT_RET_OUT_BAD,\n-\tFLOW_DISSECT_RET_OUT_PROTO_AGAIN,\n-};\n-\n static enum flow_dissect_ret\n __skb_flow_dissect_mpls(const struct sk_buff *skb,\n \t\t\tstruct flow_dissector *flow_dissector,\n@@ -322,7 +317,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,\n \tif (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)\n \t\treturn FLOW_DISSECT_RET_OUT_GOOD;\n \n-\treturn FLOW_DISSECT_RET_OUT_PROTO_AGAIN;\n+\treturn FLOW_DISSECT_RET_PROTO_AGAIN;\n }\n \n static void\n@@ -383,6 +378,27 @@ __skb_flow_dissect_ipv6(const struct sk_buff *skb,\n \tkey_ip->ttl = iph->hop_limit;\n }\n \n+#define GOTO_BY_RESULT(ret) do {\t\t\t\t\\\n+\tswitch (ret) {\t\t\t\t\t\t\\\n+\tcase FLOW_DISSECT_RET_OUT_GOOD:\t\t\t\t\\\n+\t\tgoto out_good;\t\t\t\t\t\\\n+\tcase FLOW_DISSECT_RET_PROTO_AGAIN:\t\t\t\\\n+\t\tgoto proto_again;\t\t\t\t\\\n+\tcase FLOW_DISSECT_RET_IPPROTO_AGAIN:\t\t\t\\\n+\t\tgoto ip_proto_again;\t\t\t\t\\\n+\tcase FLOW_DISSECT_RET_OUT_BAD:\t\t\t\t\\\n+\tdefault:\t\t\t\t\t\t\\\n+\t\tgoto out_bad;\t\t\t\t\t\\\n+\t}\t\t\t\t\t\t\t\\\n+} while (0)\n+\n+#define GOTO_OR_CONT_BY_RESULT(ret) do {\t\t\t\\\n+\tenum flow_dissect_ret __ret = (ret);\t\t\t\\\n+\t\t\t\t\t\t\t\t\\\n+\tif (__ret != FLOW_DISSECT_RET_CONTINUE)\t\t\t\\\n+\t\tGOTO_BY_RESULT(__ret);\t\t\t\t\\\n+} while (0)\n+\n /**\n  * __skb_flow_dissect - extract the flow_keys struct and return it\n  * @skb: sk_buff to extract the flow from, can be NULL if the rest are specified\n@@ -659,15 +675,10 @@ bool __skb_flow_dissect(const struct sk_buff *skb,\n \tcase htons(ETH_P_MPLS_UC):\n \tcase htons(ETH_P_MPLS_MC):\n mpls:\n-\t\tswitch (__skb_flow_dissect_mpls(skb, flow_dissector,\n-\t\t\t\t\t\ttarget_container, data,\n-\t\t\t\t\t\tnhoff, hlen)) {\n-\t\tcase FLOW_DISSECT_RET_OUT_GOOD:\n-\t\t\tgoto out_good;\n-\t\tcase FLOW_DISSECT_RET_OUT_BAD:\n-\t\tdefault:\n-\t\t\tgoto out_bad;\n-\t\t}\n+\t\tGOTO_BY_RESULT(__skb_flow_dissect_mpls(skb, flow_dissector,\n+\t\t\t\t\t\t       target_container, data,\n+\t\t\t\t\t\t       nhoff, hlen));\n+\n \tcase htons(ETH_P_FCOE):\n \t\tif ((hlen - nhoff) < FCOE_HEADER_LEN)\n \t\t\tgoto out_bad;\n@@ -677,32 +688,44 @@ bool __skb_flow_dissect(const struct sk_buff *skb,\n \n \tcase htons(ETH_P_ARP):\n \tcase htons(ETH_P_RARP):\n-\t\tswitch (__skb_flow_dissect_arp(skb, flow_dissector,\n-\t\t\t\t\t       target_container, data,\n-\t\t\t\t\t       nhoff, hlen)) {\n-\t\tcase FLOW_DISSECT_RET_OUT_GOOD:\n-\t\t\tgoto out_good;\n-\t\tcase FLOW_DISSECT_RET_OUT_BAD:\n-\t\tdefault:\n-\t\t\tgoto out_bad;\n+\t\tGOTO_BY_RESULT(__skb_flow_dissect_arp(skb, flow_dissector,\n+\t\t\t\t\t\t      target_container, data,\n+\t\t\t\t\t\t      nhoff, hlen));\n+\n+\tdefault: {\n+\t\tstruct packet_offload *ptype;\n+\t\tenum flow_dissect_ret ret;\n+\n+\t\trcu_read_lock();\n+\n+\t\tptype = flow_dissect_find_by_type(proto);\n+\n+\t\tif (ptype) {\n+\t\t\tret = ptype->callbacks.flow_dissect(skb, key_control,\n+\t\t\t\t\t\tflow_dissector,\n+\t\t\t\t\t\ttarget_container,\n+\t\t\t\t\t\tdata, &proto, &ip_proto, &nhoff,\n+\t\t\t\t\t\t&hlen, flags);\n+\t\t\trcu_read_unlock();\n+\n+\t\t\tGOTO_BY_RESULT(ret);\n+\t\t} else {\n+\t\t\trcu_read_unlock();\n \t\t}\n-\tdefault:\n+\n \t\tgoto out_bad;\n \t}\n+\t}\n \n ip_proto_again:\n \tswitch (ip_proto) {\n \tcase IPPROTO_GRE:\n-\t\tswitch (__skb_flow_dissect_gre(skb, key_control, flow_dissector,\n-\t\t\t\t\t       target_container, data,\n-\t\t\t\t\t       &proto, &nhoff, &hlen, flags)) {\n-\t\tcase FLOW_DISSECT_RET_OUT_GOOD:\n-\t\t\tgoto out_good;\n-\t\tcase FLOW_DISSECT_RET_OUT_BAD:\n-\t\t\tgoto out_bad;\n-\t\tcase FLOW_DISSECT_RET_OUT_PROTO_AGAIN:\n-\t\t\tgoto proto_again;\n-\t\t}\n+\t\tGOTO_BY_RESULT(__skb_flow_dissect_gre(skb, key_control,\n+\t\t\t\t\t\t      flow_dissector,\n+\t\t\t\t\t\t      target_container, data,\n+\t\t\t\t\t\t      &proto, &nhoff, &hlen,\n+\t\t\t\t\t\t      flags));\n+\n \tcase NEXTHDR_HOP:\n \tcase NEXTHDR_ROUTING:\n \tcase NEXTHDR_DEST: {\n@@ -768,9 +791,43 @@ bool __skb_flow_dissect(const struct sk_buff *skb,\n \t\t__skb_flow_dissect_tcp(skb, flow_dissector, target_container,\n \t\t\t\t       data, nhoff, hlen);\n \t\tbreak;\n-\tdefault:\n+\tdefault: {\n+\t\tconst struct net_offload *ops = NULL;\n+\n+\t\tif (flags & FLOW_DISSECTOR_F_STOP_AT_L4)\n+\t\t\tbreak;\n+\n+\t\trcu_read_lock();\n+\n+\t\tswitch (proto) {\n+\t\tcase htons(ETH_P_IP):\n+\t\t\tops = rcu_dereference(inet_offloads[ip_proto]);\n+\t\t\tbreak;\n+\t\tcase htons(ETH_P_IPV6):\n+\t\t\tops = rcu_dereference(inet6_offloads[ip_proto]);\n+\t\t\tbreak;\n+\t\tdefault:\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tif (ops && ops->callbacks.flow_dissect) {\n+\t\t\tenum flow_dissect_ret ret;\n+\n+\t\t\tret = ops->callbacks.flow_dissect(skb, key_control,\n+\t\t\t\t\t\tflow_dissector,\n+\t\t\t\t\t\ttarget_container,\n+\t\t\t\t\t\tdata, &proto, &ip_proto, &nhoff,\n+\t\t\t\t\t\t&hlen, flags);\n+\t\t\trcu_read_unlock();\n+\n+\t\t\tGOTO_OR_CONT_BY_RESULT(ret);\n+\t\t} else {\n+\t\t\trcu_read_unlock();\n+\t\t}\n+\n \t\tbreak;\n \t}\n+\t}\n \n \tif (dissector_uses_key(flow_dissector,\n \t\t\t       FLOW_DISSECTOR_KEY_PORTS)) {\n@@ -935,7 +992,8 @@ static inline u32 ___skb_get_hash(const struct sk_buff *skb,\n \t\t\t\t  struct flow_keys *keys, u32 keyval)\n {\n \tskb_flow_dissect_flow_keys(skb, keys,\n-\t\t\t\t   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL);\n+\t\t\t\t   FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL |\n+\t\t\t\t   FLOW_DISSECTOR_F_STOP_AT_L4);\n \n \treturn __flow_hash_from_keys(keys, keyval);\n }\ndiff --git a/net/ipv4/route.c b/net/ipv4/route.c\nindex 94d4cd2d5ea4..85f12b8e0b7f 100644\n--- a/net/ipv4/route.c\n+++ b/net/ipv4/route.c\n@@ -1811,7 +1811,9 @@ int fib_multipath_hash(const struct fib_info *fi, const struct flowi4 *fl4,\n \tcase 1:\n \t\t/* skb is currently provided only when forwarding */\n \t\tif (skb) {\n-\t\t\tunsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;\n+\t\t\tunsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP |\n+\t\t\t\t\t    FLOW_DISSECTOR_F_STOP_AT_L4;\n+;\n \t\t\tstruct flow_keys keys;\n \n \t\t\t/* short-circuit if we already have L4 hash present */\n",
    "prefixes": [
        "net-next",
        "3/6"
    ]
}