Home Home > GIT Browse > SLE12-SP4-AZURE
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2019-06-06 10:45:08 +0200
committerMichal Kubecek <mkubecek@suse.cz>2019-06-06 10:45:15 +0200
commit321456772b9c5461e022fce8d2ae8aadebfd8432 (patch)
treeaaceed3d1575ea28587fb1b5ccd2bc8cd7f64cb8
parent32bf9e7f9c8f0b79bfc3bf65fcc329f5c7c8c9d0 (diff)
net: use indirect call wrappers at GRO transport layer
(bsc#1124503).
-rw-r--r--patches.fixes/net-use-indirect-call-wrappers-at-GRO-transport-laye.patch275
-rw-r--r--series.conf1
2 files changed, 276 insertions, 0 deletions
diff --git a/patches.fixes/net-use-indirect-call-wrappers-at-GRO-transport-laye.patch b/patches.fixes/net-use-indirect-call-wrappers-at-GRO-transport-laye.patch
new file mode 100644
index 0000000000..e3b3a0833e
--- /dev/null
+++ b/patches.fixes/net-use-indirect-call-wrappers-at-GRO-transport-laye.patch
@@ -0,0 +1,275 @@
+From: Paolo Abeni <pabeni@redhat.com>
+Date: Fri, 14 Dec 2018 11:51:59 +0100
+Subject: net: use indirect call wrappers at GRO transport layer
+Patch-mainline: v5.0-rc1
+Git-commit: 028e0a4766844e7eeb31b93479ea6dd40cfc2895
+References: bsc#1124503
+
+This avoids an indirect call in the receive path for TCP and UDP
+packets. TCP takes precedence on UDP, so that we have a single
+additional conditional in the common case.
+
+When IPV6 is build as module, all gro symbols except UDPv6 are
+builtin, while the latter belong to the ipv6 module, so we
+need some special care.
+
+v1 -> v2:
+ - adapted to INDIRECT_CALL_ changes
+v2 -> v3:
+ - fix build issue with CONFIG_IPV6=m
+
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Acked-by: Michal Kubecek <mkubecek@suse.cz>
+
+---
+ include/net/inet_common.h | 7 +++++++
+ net/ipv4/af_inet.c | 13 +++++++++++--
+ net/ipv4/tcp_offload.c | 6 ++++--
+ net/ipv4/udp_offload.c | 7 ++++---
+ net/ipv6/ip6_offload.c | 29 +++++++++++++++++++++++++++--
+ net/ipv6/tcpv6_offload.c | 7 ++++---
+ net/ipv6/udp_offload.c | 7 ++++---
+ 7 files changed, 61 insertions(+), 15 deletions(-)
+
+--- a/include/net/inet_common.h
++++ b/include/net/inet_common.h
+@@ -53,4 +53,11 @@ static inline void inet_ctl_sock_destroy(struct sock *sk)
+ sock_release(sk->sk_socket);
+ }
+
++#define indirect_call_gro_receive(f2, f1, cb, head, skb) \
++({ \
++ unlikely(gro_recursion_inc_test(skb)) ? \
++ NAPI_GRO_CB(skb)->flush |= 1, NULL : \
++ INDIRECT_CALL_2(cb, f2, f1, head, skb); \
++})
++
+ #endif
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -1313,6 +1313,10 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL(inet_gso_segment);
+
++INDIRECT_CALLABLE_DECLARE(struct sk_buff **tcp4_gro_receive(struct sk_buff **,
++ struct sk_buff *));
++INDIRECT_CALLABLE_DECLARE(struct sk_buff **udp4_gro_receive(struct sk_buff **,
++ struct sk_buff *));
+ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+ const struct net_offload *ops;
+@@ -1422,7 +1426,8 @@ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ skb_gro_pull(skb, sizeof(*iph));
+ skb_set_transport_header(skb, skb_gro_offset(skb));
+
+- pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
++ pp = indirect_call_gro_receive(tcp4_gro_receive, udp4_gro_receive,
++ ops->callbacks.gro_receive, head, skb);
+
+ out_unlock:
+ rcu_read_unlock();
+@@ -1484,6 +1489,8 @@ int inet_recv_error(struct sock *sk, struct msghdr *msg, int len, int *addr_len)
+ return -EINVAL;
+ }
+
++INDIRECT_CALLABLE_DECLARE(int tcp4_gro_complete(struct sk_buff *, int));
++INDIRECT_CALLABLE_DECLARE(int udp4_gro_complete(struct sk_buff *, int));
+ int inet_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+ __be16 newlen = htons(skb->len - nhoff);
+@@ -1509,7 +1516,9 @@ int inet_gro_complete(struct sk_buff *skb, int nhoff)
+ * because any hdr with option will have been flushed in
+ * inet_gro_receive().
+ */
+- err = ops->callbacks.gro_complete(skb, nhoff + sizeof(*iph));
++ err = INDIRECT_CALL_2(ops->callbacks.gro_complete,
++ tcp4_gro_complete, udp4_gro_complete,
++ skb, nhoff + sizeof(*iph));
+
+ out_unlock:
+ rcu_read_unlock();
+--- a/net/ipv4/tcp_offload.c
++++ b/net/ipv4/tcp_offload.c
+@@ -10,6 +10,7 @@
+ * TCPv4 GSO/GRO support
+ */
+
++#include <linux/indirect_call_wrapper.h>
+ #include <linux/skbuff.h>
+ #include <net/tcp.h>
+ #include <net/protocol.h>
+@@ -296,7 +297,8 @@ int tcp_gro_complete(struct sk_buff *skb)
+ }
+ EXPORT_SYMBOL(tcp_gro_complete);
+
+-static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
++INDIRECT_CALLABLE_SCOPE
++struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+ /* Don't bother verifying checksum if we're going to flush anyway. */
+ if (!NAPI_GRO_CB(skb)->flush &&
+@@ -309,7 +311,7 @@ static struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *
+ return tcp_gro_receive(head, skb);
+ }
+
+-static int tcp4_gro_complete(struct sk_buff *skb, int thoff)
++INDIRECT_CALLABLE_SCOPE int tcp4_gro_complete(struct sk_buff *skb, int thoff)
+ {
+ const struct iphdr *iph = ip_hdr(skb);
+ struct tcphdr *th = tcp_hdr(skb);
+--- a/net/ipv4/udp_offload.c
++++ b/net/ipv4/udp_offload.c
+@@ -13,6 +13,7 @@
+ #include <linux/skbuff.h>
+ #include <net/udp.h>
+ #include <net/protocol.h>
++#include <net/inet_common.h>
+
+ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
+ netdev_features_t features,
+@@ -300,8 +301,8 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
+ }
+ EXPORT_SYMBOL(udp_gro_receive);
+
+-static struct sk_buff **udp4_gro_receive(struct sk_buff **head,
+- struct sk_buff *skb)
++INDIRECT_CALLABLE_SCOPE
++struct sk_buff **udp4_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+ struct udphdr *uh = udp_gro_udphdr(skb);
+
+@@ -356,7 +357,7 @@ int udp_gro_complete(struct sk_buff *skb, int nhoff,
+ }
+ EXPORT_SYMBOL(udp_gro_complete);
+
+-static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
++INDIRECT_CALLABLE_SCOPE int udp4_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+ const struct iphdr *iph = ip_hdr(skb);
+ struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
+--- a/net/ipv6/ip6_offload.c
++++ b/net/ipv6/ip6_offload.c
+@@ -20,6 +20,23 @@
+
+ #include "ip6_offload.h"
+
++/* All GRO functions are always builtin, except UDP over ipv6, which lays in
++ * ipv6 module, as it depends on UDPv6 lookup function, so we need special care
++ * when ipv6 is built as a module
++ */
++#if IS_BUILTIN(CONFIG_IPV6)
++#define INDIRECT_CALL_L4(f, f2, f1, ...) INDIRECT_CALL_2(f, f2, f1, __VA_ARGS__)
++#else
++#define INDIRECT_CALL_L4(f, f2, f1, ...) INDIRECT_CALL_1(f, f2, __VA_ARGS__)
++#endif
++
++#define indirect_call_gro_receive_l4(f2, f1, cb, head, skb) \
++({ \
++ unlikely(gro_recursion_inc_test(skb)) ? \
++ NAPI_GRO_CB(skb)->flush |= 1, NULL : \
++ INDIRECT_CALL_L4(cb, f2, f1, head, skb); \
++})
++
+ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto)
+ {
+ const struct net_offload *ops = NULL;
+@@ -162,6 +179,10 @@ static int ipv6_exthdrs_len(struct ipv6hdr *iph,
+ return len;
+ }
+
++INDIRECT_CALLABLE_DECLARE(struct sk_buff **tcp6_gro_receive(struct sk_buff **,
++ struct sk_buff *));
++INDIRECT_CALLABLE_DECLARE(struct sk_buff **udp6_gro_receive(struct sk_buff **,
++ struct sk_buff *));
+ INDIRECT_CALLABLE_SCOPE
+ struct sk_buff **ipv6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+@@ -251,7 +272,8 @@ struct sk_buff **ipv6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+
+ skb_gro_postpull_rcsum(skb, iph, nlen);
+
+- pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
++ pp = indirect_call_gro_receive_l4(tcp6_gro_receive, udp6_gro_receive,
++ ops->callbacks.gro_receive, head, skb);
+
+ out_unlock:
+ rcu_read_unlock();
+@@ -292,6 +314,8 @@ static struct sk_buff **ip4ip6_gro_receive(struct sk_buff **head,
+ return inet_gro_receive(head, skb);
+ }
+
++INDIRECT_CALLABLE_DECLARE(int tcp6_gro_complete(struct sk_buff *, int));
++INDIRECT_CALLABLE_DECLARE(int udp6_gro_complete(struct sk_buff *, int));
+ INDIRECT_CALLABLE_SCOPE int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+ const struct net_offload *ops;
+@@ -311,7 +335,8 @@ INDIRECT_CALLABLE_SCOPE int ipv6_gro_complete(struct sk_buff *skb, int nhoff)
+ if (WARN_ON(!ops || !ops->callbacks.gro_complete))
+ goto out_unlock;
+
+- err = ops->callbacks.gro_complete(skb, nhoff);
++ err = INDIRECT_CALL_L4(ops->callbacks.gro_complete, tcp6_gro_complete,
++ udp6_gro_complete, skb, nhoff);
+
+ out_unlock:
+ rcu_read_unlock();
+--- a/net/ipv6/tcpv6_offload.c
++++ b/net/ipv6/tcpv6_offload.c
+@@ -9,14 +9,15 @@
+ *
+ * TCPv6 GSO/GRO support
+ */
++#include <linux/indirect_call_wrapper.h>
+ #include <linux/skbuff.h>
+ #include <net/protocol.h>
+ #include <net/tcp.h>
+ #include <net/ip6_checksum.h>
+ #include "ip6_offload.h"
+
+-static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
+- struct sk_buff *skb)
++INDIRECT_CALLABLE_SCOPE
++struct sk_buff **tcp6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+ /* Don't bother verifying checksum if we're going to flush anyway. */
+ if (!NAPI_GRO_CB(skb)->flush &&
+@@ -29,7 +30,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head,
+ return tcp_gro_receive(head, skb);
+ }
+
+-static int tcp6_gro_complete(struct sk_buff *skb, int thoff)
++INDIRECT_CALLABLE_SCOPE int tcp6_gro_complete(struct sk_buff *skb, int thoff)
+ {
+ const struct ipv6hdr *iph = ipv6_hdr(skb);
+ struct tcphdr *th = tcp_hdr(skb);
+--- a/net/ipv6/udp_offload.c
++++ b/net/ipv6/udp_offload.c
+@@ -11,6 +11,7 @@
+ */
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
++#include <linux/indirect_call_wrapper.h>
+ #include <net/protocol.h>
+ #include <net/ipv6.h>
+ #include <net/udp.h>
+@@ -111,8 +112,8 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
+ return segs;
+ }
+
+-static struct sk_buff **udp6_gro_receive(struct sk_buff **head,
+- struct sk_buff *skb)
++INDIRECT_CALLABLE_SCOPE
++struct sk_buff **udp6_gro_receive(struct sk_buff **head, struct sk_buff *skb)
+ {
+ struct udphdr *uh = udp_gro_udphdr(skb);
+
+@@ -139,7 +140,7 @@ static struct sk_buff **udp6_gro_receive(struct sk_buff **head,
+ return NULL;
+ }
+
+-static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
++INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
+ {
+ const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
diff --git a/series.conf b/series.conf
index 61c9d4ffeb..b863c779e9 100644
--- a/series.conf
+++ b/series.conf
@@ -20617,6 +20617,7 @@
patches.fixes/0001-net-mlx5-Use-multi-threaded-workqueue-for-page-fault.patch
patches.fixes/indirect-call-wrappers-helpers-to-speed-up-indirect-.patch
patches.fixes/net-use-indirect-call-wrappers-at-GRO-network-layer.patch
+ patches.fixes/net-use-indirect-call-wrappers-at-GRO-transport-laye.patch
patches.fixes/mac80211-fix-radiotap-vendor-presence-bitmap-handlin.patch
patches.drivers/Bluetooth-Fix-unnecessary-error-message-for-HCI-requ.patch
patches.fixes/igb-Fix-an-issue-that-PME-is-not-enabled-during-runt.patch