Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/807351/?format=api
{ "id": 807351, "url": "http://patchwork.ozlabs.org/api/patches/807351/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170829232711.1465-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": "<20170829232711.1465-4-tom@quantonium.net>", "list_archive_url": null, "date": "2017-08-29T23:27:08", "name": "[v2,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/20170829232711.1465-4-tom@quantonium.net/mbox/", "series": [ { "id": 503, "url": "http://patchwork.ozlabs.org/api/series/503/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=503", "date": "2017-08-29T23:27:05", "name": "flow_dissector: Protocol specific flow dissector offload", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/503/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/807351/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/807351/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=\"Ct8ul4XW\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xhlDG68X1z9s9Y\n\tfor <patchwork-incoming@ozlabs.org>;\n\tWed, 30 Aug 2017 09:27:42 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751791AbdH2X1k (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tTue, 29 Aug 2017 19:27:40 -0400", "from mail-pf0-f180.google.com ([209.85.192.180]:33519 \"EHLO\n\tmail-pf0-f180.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S1751757AbdH2X1i (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Tue, 29 Aug 2017 19:27:38 -0400", "by mail-pf0-f180.google.com with SMTP id r62so14372597pfj.0\n\tfor <netdev@vger.kernel.org>; Tue, 29 Aug 2017 16:27:38 -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\tr73sm6445593pfa.143.2017.08.29.16.27.36\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tTue, 29 Aug 2017 16:27:37 -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=3f3hmdpJli1jAXzGm7NtR7ggAuEx0JeybBG9viZivNs=;\n\tb=Ct8ul4XWG+oChx5NDM13eysEJ9XcNWGcEjSDaDtKPqxptpflsm8RhccXmuMmP5XBBf\n\tgE7cnBJDplbiVFSD4EbLiu13osc/ouBhPqs1sF4IZ2g1ajyEDRjDX2SdG7+/Vkdek0sz\n\tyYN/wGvm9vnal5u6PwwHt5z4L1Cjxz4PPEde9gINgBamTt3Fz8AY5SfB5nUyO23HbKW5\n\tmOwuTCckd6VLrPA1G9MfiMY86RNNRdBVvPJSENRXlz/vI5llIdjICl/0yN8jmsr63y10\n\treQpeCJXsKiPA5MTVJqG/JKRwIk5gu7JXzWve7Xf+SRYtdZuP0Q4kRwWteKIHMQD5Vr3\n\tVUiA==", "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=3f3hmdpJli1jAXzGm7NtR7ggAuEx0JeybBG9viZivNs=;\n\tb=hB3YPwqrcVN9UG5UrctPGqGKLFuDhLaSUVm57eU2LQpj9Ngy2f8BZFU2EJOLtsxTAo\n\tmdfprC9fIm47knN18uzX8iGlRczysatUkfftH9jMumX2KlbLmGCE97RpIHtDtJGpcr9S\n\tqF7Q7n2u5ecTHd2lLxFwQNe+q7vMdSErHKqHLOXzAbXngTmst6UkJgDuPo0MLSR6VxtP\n\tPW2p0nBQgehvJsUe+eBn5E43iDEYneXCyM6qXhw3DWGe0Dpi5XBOefiH8uOFIHsU2zYn\n\t8qPSdYAcbqlwfasf4bEhbfuTe4GptFy7t73pYJPZXrTtTCP1MtCsG3nPqywSxvHlCemI\n\t0nYw==", "X-Gm-Message-State": "AHYfb5hc+m7/hATA3CTOO6rkJt3fbB/ItVuyTK8ssEb8xHWxlsW/kz36\n\t1MuZhhWRbma5e1A/pOA=", "X-Received": "by 10.84.254.66 with SMTP id a2mr2491124pln.33.1504049258387;\n\tTue, 29 Aug 2017 16:27:38 -0700 (PDT)", "From": "Tom Herbert <tom@quantonium.net>", "To": "davem@davemloft.net", "Cc": "netdev@vger.kernel.org, Tom Herbert <tom@quantonium.net>", "Subject": "[PATCH v2 net-next 3/6] flow_dissector: Add protocol specific flow\n\tdissection offload", "Date": "Tue, 29 Aug 2017 16:27:08 -0700", "Message-Id": "<20170829232711.1465-4-tom@quantonium.net>", "X-Mailer": "git-send-email 2.11.0", "In-Reply-To": "<20170829232711.1465-1-tom@quantonium.net>", "References": "<20170829232711.1465-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\nSigned-off-by: Tom Herbert <tom@quantonium.net>\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": [ "v2", "net-next", "3/6" ] }