get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 816376,
    "url": "http://patchwork.ozlabs.org/api/patches/816376/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/e9a773d791688d398acff2c6235a217fb402c469.1505926196.git.pabeni@redhat.com/",
    "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": "<e9a773d791688d398acff2c6235a217fb402c469.1505926196.git.pabeni@redhat.com>",
    "list_archive_url": null,
    "date": "2017-09-20T16:54:05",
    "name": "[net-next,5/5] udp: perform full socket lookup in early demux",
    "commit_ref": null,
    "pull_url": null,
    "state": "changes-requested",
    "archived": true,
    "hash": "79bdcd9bf2f586edec28d04a74597c4b0288a33a",
    "submitter": {
        "id": 67312,
        "url": "http://patchwork.ozlabs.org/api/people/67312/?format=api",
        "name": "Paolo Abeni",
        "email": "pabeni@redhat.com"
    },
    "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/e9a773d791688d398acff2c6235a217fb402c469.1505926196.git.pabeni@redhat.com/mbox/",
    "series": [
        {
            "id": 4180,
            "url": "http://patchwork.ozlabs.org/api/series/4180/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=4180",
            "date": "2017-09-20T16:54:00",
            "name": "net: introduce noref sk",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/4180/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/816376/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/816376/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>)",
            "ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tdmarc=none (p=none dis=none) header.from=redhat.com",
            "ext-mx03.extmail.prod.ext.phx2.redhat.com;\n\tspf=fail smtp.mailfrom=pabeni@redhat.com"
        ],
        "Received": [
            "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xy5Y54YDKz9sP1\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 21 Sep 2017 02:58:33 +1000 (AEST)",
            "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1751634AbdITQ6W (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tWed, 20 Sep 2017 12:58:22 -0400",
            "from mx1.redhat.com ([209.132.183.28]:37238 \"EHLO mx1.redhat.com\"\n\trhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP\n\tid S1751378AbdITQ6R (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tWed, 20 Sep 2017 12:58:17 -0400",
            "from smtp.corp.redhat.com\n\t(int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12])\n\t(using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby mx1.redhat.com (Postfix) with ESMTPS id F1AC17C83A;\n\tWed, 20 Sep 2017 16:58:16 +0000 (UTC)",
            "from localhost.mxp.redhat.com (unknown [10.32.181.195])\n\tby smtp.corp.redhat.com (Postfix) with ESMTP id AFA5A60241;\n\tWed, 20 Sep 2017 16:58:15 +0000 (UTC)"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.3.2 mx1.redhat.com F1AC17C83A",
        "From": "Paolo Abeni <pabeni@redhat.com>",
        "To": "netdev@vger.kernel.org",
        "Cc": "\"David S. Miller\" <davem@davemloft.net>,\n\tPablo Neira Ayuso <pablo@netfilter.org>, Florian Westphal <fw@strlen.de>,\n\tEric Dumazet <edumazet@google.com>,\n\tHannes Frederic Sowa <hannes@stressinduktion.org>",
        "Subject": "[PATCH net-next 5/5] udp: perform full socket lookup in early demux",
        "Date": "Wed, 20 Sep 2017 18:54:05 +0200",
        "Message-Id": "<e9a773d791688d398acff2c6235a217fb402c469.1505926196.git.pabeni@redhat.com>",
        "In-Reply-To": "<cover.1505926196.git.pabeni@redhat.com>",
        "References": "<cover.1505926196.git.pabeni@redhat.com>",
        "X-Scanned-By": "MIMEDefang 2.79 on 10.5.11.12",
        "X-Greylist": "Sender IP whitelisted, not delayed by milter-greylist-4.5.16\n\t(mx1.redhat.com [10.5.110.27]);\n\tWed, 20 Sep 2017 16:58:17 +0000 (UTC)",
        "Sender": "netdev-owner@vger.kernel.org",
        "Precedence": "bulk",
        "List-ID": "<netdev.vger.kernel.org>",
        "X-Mailing-List": "netdev@vger.kernel.org"
    },
    "content": "Since UDP early demux lookup fetches noref socket references,\nwe can safely be optimistic about it and set the sk reference\neven if the skb is not going to land on such socket, avoiding\nthe rx dst cache usage for unconnected unicast sockets.\n\nThis avoids a second lookup for unconnected sockets, and clean\nup a bit the whole udp early demux code.\n\nAfter this change, on hosts not acting as routers, the UDP\nearly demux never affect negatively the receive performances,\nwhile before this change UDP early demux caused measurable\nperformance impact for unconnected sockets.\n\nSigned-off-by: Paolo Abeni <pabeni@redhat.com>\n---\n include/linux/udp.h |  2 ++\n net/ipv4/udp.c      | 62 +++++++++++++++++++----------------------------------\n net/ipv6/udp.c      | 57 ++++++++++++------------------------------------\n 3 files changed, 38 insertions(+), 83 deletions(-)",
    "diff": "diff --git a/include/linux/udp.h b/include/linux/udp.h\nindex eaea63bc79bb..9c68b57543cc 100644\n--- a/include/linux/udp.h\n+++ b/include/linux/udp.h\n@@ -92,6 +92,8 @@ static inline struct udp_sock *udp_sk(const struct sock *sk)\n \treturn (struct udp_sock *)sk;\n }\n \n+void udp_set_skb_rx_dst(struct sock *sk, struct sk_buff *skb, u32 cookie);\n+\n static inline void udp_set_no_check6_tx(struct sock *sk, bool val)\n {\n \tudp_sk(sk)->no_check6_tx = val;\ndiff --git a/net/ipv4/udp.c b/net/ipv4/udp.c\nindex ba49d5aa9f09..5cbbd78024dc 100644\n--- a/net/ipv4/udp.c\n+++ b/net/ipv4/udp.c\n@@ -2043,6 +2043,11 @@ static inline int udp4_csum_init(struct sk_buff *skb, struct udphdr *uh,\n \t\t\t\t\t\t\t inet_compute_pseudo);\n }\n \n+static bool udp_use_rx_dst_cache(struct sock *sk, struct sk_buff *skb)\n+{\n+\treturn sk->sk_state == TCP_ESTABLISHED || skb->pkt_type != PACKET_HOST;\n+}\n+\n /*\n  *\tAll we need to do is get the socket, and then do a checksum.\n  */\n@@ -2088,8 +2093,8 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,\n \t\tstruct dst_entry *dst = skb_dst(skb);\n \t\tint ret;\n \n-\t\tif (unlikely(sk->sk_rx_dst != dst))\n-\t\t\tudp_sk_rx_dst_set(sk, dst);\n+\t\tif (udp_use_rx_dst_cache(sk, skb))\n+\t\t\tdst_update(&sk->sk_rx_dst, dst);\n \n \t\tret = udp_queue_rcv_skb(sk, skb);\n \t\tif (!noref_sk)\n@@ -2196,42 +2201,28 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net,\n \treturn result;\n }\n \n-/* For unicast we should only early demux connected sockets or we can\n- * break forwarding setups.  The chains here can be long so only check\n- * if the first socket is an exact match and if not move on.\n- */\n-static struct sock *__udp4_lib_demux_lookup(struct net *net,\n-\t\t\t\t\t    __be16 loc_port, __be32 loc_addr,\n-\t\t\t\t\t    __be16 rmt_port, __be32 rmt_addr,\n-\t\t\t\t\t    int dif, int sdif)\n+void udp_set_skb_rx_dst(struct sock *sk, struct sk_buff *skb, u32 cookie)\n {\n-\tunsigned short hnum = ntohs(loc_port);\n-\tunsigned int hash2 = udp4_portaddr_hash(net, loc_addr, hnum);\n-\tunsigned int slot2 = hash2 & udp_table.mask;\n-\tstruct udp_hslot *hslot2 = &udp_table.hash2[slot2];\n-\tINET_ADDR_COOKIE(acookie, rmt_addr, loc_addr);\n-\tconst __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum);\n-\tstruct sock *sk;\n+\tstruct dst_entry *dst = dst_access(&sk->sk_rx_dst, cookie);\n \n-\tudp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {\n-\t\tif (INET_MATCH(sk, net, acookie, rmt_addr,\n-\t\t\t       loc_addr, ports, dif, sdif))\n-\t\t\treturn sk;\n-\t\t/* Only check first socket in chain */\n-\t\tbreak;\n+\tif (dst) {\n+\t\t/* set noref for now.\n+\t\t * any place which wants to hold dst has to call\n+\t\t * dst_hold_safe()\n+\t\t */\n+\t\tskb_dst_set_noref(skb, dst);\n \t}\n-\treturn NULL;\n }\n+EXPORT_SYMBOL_GPL(udp_set_skb_rx_dst);\n \n void udp_v4_early_demux(struct sk_buff *skb)\n {\n \tstruct net *net = dev_net(skb->dev);\n+\tint dif = skb->dev->ifindex;\n+\tint sdif = inet_sdif(skb);\n \tconst struct iphdr *iph;\n \tconst struct udphdr *uh;\n \tstruct sock *sk = NULL;\n-\tstruct dst_entry *dst;\n-\tint dif = skb->dev->ifindex;\n-\tint sdif = inet_sdif(skb);\n \tint ours;\n \n \t/* validate the packet */\n@@ -2260,25 +2251,16 @@ void udp_v4_early_demux(struct sk_buff *skb)\n \t\t\t\t\t\t   uh->source, iph->saddr,\n \t\t\t\t\t\t   dif, sdif);\n \t} else if (skb->pkt_type == PACKET_HOST) {\n-\t\tsk = __udp4_lib_demux_lookup(net, uh->dest, iph->daddr,\n-\t\t\t\t\t     uh->source, iph->saddr, dif, sdif);\n+\t\tsk = __udp4_lib_lookup(net, iph->saddr, uh->source, iph->daddr,\n+\t\t\t\t       uh->dest, dif, sdif, &udp_table, skb);\n \t}\n \n \tif (!sk)\n \t\treturn;\n \n \tskb_set_noref_sk(skb, sk);\n-\tdst = READ_ONCE(sk->sk_rx_dst);\n-\n-\tif (dst)\n-\t\tdst = dst_check(dst, 0);\n-\tif (dst) {\n-\t\t/* set noref for now.\n-\t\t * any place which wants to hold dst has to call\n-\t\t * dst_hold_safe()\n-\t\t */\n-\t\tskb_dst_set_noref(skb, dst);\n-\t}\n+\tif (udp_use_rx_dst_cache(sk, skb))\n+\t\tudp_set_skb_rx_dst(sk, skb, 0);\n }\n \n int udp_rcv(struct sk_buff *skb)\ndiff --git a/net/ipv6/udp.c b/net/ipv6/udp.c\nindex 8f62392c4c35..67d340679c3a 100644\n--- a/net/ipv6/udp.c\n+++ b/net/ipv6/udp.c\n@@ -773,13 +773,18 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb,\n \n static void udp6_sk_rx_dst_set(struct sock *sk, struct dst_entry *dst)\n {\n-\tif (udp_sk_rx_dst_set(sk, dst)) {\n+\tif (unlikely(dst_update(&sk->sk_rx_dst, dst))) {\n \t\tconst struct rt6_info *rt = (const struct rt6_info *)dst;\n \n \t\tinet6_sk(sk)->rx_dst_cookie = rt6_get_cookie(rt);\n \t}\n }\n \n+static bool udp6_use_rx_dst_cache(struct sock *sk)\n+{\n+\treturn sk->sk_state == TCP_ESTABLISHED;\n+}\n+\n int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,\n \t\t   int proto)\n {\n@@ -830,7 +835,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,\n \t\tstruct dst_entry *dst = skb_dst(skb);\n \t\tint ret;\n \n-\t\tif (unlikely(sk->sk_rx_dst != dst))\n+\t\tif (udp6_use_rx_dst_cache(sk))\n \t\t\tudp6_sk_rx_dst_set(sk, dst);\n \n \t\tret = udpv6_queue_rcv_skb(sk, skb);\n@@ -905,37 +910,13 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,\n \treturn 0;\n }\n \n-\n-static struct sock *__udp6_lib_demux_lookup(struct net *net,\n-\t\t\t__be16 loc_port, const struct in6_addr *loc_addr,\n-\t\t\t__be16 rmt_port, const struct in6_addr *rmt_addr,\n-\t\t\tint dif, int sdif)\n-{\n-\tunsigned short hnum = ntohs(loc_port);\n-\tunsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum);\n-\tunsigned int slot2 = hash2 & udp_table.mask;\n-\tstruct udp_hslot *hslot2 = &udp_table.hash2[slot2];\n-\tconst __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum);\n-\tstruct sock *sk;\n-\n-\tudp_portaddr_for_each_entry_rcu(sk, &hslot2->head) {\n-\t\tif (sk->sk_state == TCP_ESTABLISHED &&\n-\t\t    INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif, sdif))\n-\t\t\treturn sk;\n-\t\t/* Only check first socket in chain */\n-\t\tbreak;\n-\t}\n-\treturn NULL;\n-}\n-\n static void udp_v6_early_demux(struct sk_buff *skb)\n {\n \tstruct net *net = dev_net(skb->dev);\n-\tconst struct udphdr *uh;\n-\tstruct sock *sk;\n-\tstruct dst_entry *dst;\n \tint dif = skb->dev->ifindex;\n \tint sdif = inet6_sdif(skb);\n+\tconst struct udphdr *uh;\n+\tstruct sock *sk;\n \n \tif (!pskb_may_pull(skb, skb_transport_offset(skb) +\n \t    sizeof(struct udphdr)))\n@@ -944,10 +925,9 @@ static void udp_v6_early_demux(struct sk_buff *skb)\n \tuh = udp_hdr(skb);\n \n \tif (skb->pkt_type == PACKET_HOST)\n-\t\tsk = __udp6_lib_demux_lookup(net, uh->dest,\n-\t\t\t\t\t     &ipv6_hdr(skb)->daddr,\n-\t\t\t\t\t     uh->source, &ipv6_hdr(skb)->saddr,\n-\t\t\t\t\t     dif, sdif);\n+\t\tsk = __udp6_lib_lookup(net, &ipv6_hdr(skb)->saddr, uh->source,\n+\t\t\t\t       &ipv6_hdr(skb)->daddr, uh->dest, dif,\n+\t\t\t\t       sdif, &udp_table, skb);\n \telse\n \t\treturn;\n \n@@ -955,17 +935,8 @@ static void udp_v6_early_demux(struct sk_buff *skb)\n \t\treturn;\n \n \tskb_set_noref_sk(skb, sk);\n-\tdst = READ_ONCE(sk->sk_rx_dst);\n-\n-\tif (dst)\n-\t\tdst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie);\n-\tif (dst) {\n-\t\t/* set noref for now.\n-\t\t * any place which wants to hold dst has to call\n-\t\t * dst_hold_safe()\n-\t\t */\n-\t\tskb_dst_set_noref(skb, dst);\n-\t}\n+\tif (udp6_use_rx_dst_cache(sk))\n+\t\tudp_set_skb_rx_dst(sk, skb, inet6_sk(sk)->rx_dst_cookie);\n }\n \n static __inline__ int udpv6_rcv(struct sk_buff *skb)\n",
    "prefixes": [
        "net-next",
        "5/5"
    ]
}