This avoids an indirect calls for L3 GRO receive path, both for ipv4 and ipv6, if the latter is not compiled as a module.
Note that when IPv6 is compiled as buildin, it will be checked first, so we have a single additional compare for the more common path. Signed-off-by: Paolo Abeni <pab...@redhat.com> --- include/net/inet_common.h | 2 ++ net/core/dev.c | 10 ++++++++-- net/ipv4/af_inet.c | 4 ++++ net/ipv6/ip6_offload.c | 4 ++++ 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/net/inet_common.h b/include/net/inet_common.h index 3ca969cbd161..56e7592811ea 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -2,6 +2,8 @@ #ifndef _INET_COMMON_H #define _INET_COMMON_H +#include <linux/indirect_call_wrapper.h> + extern const struct proto_ops inet_stream_ops; extern const struct proto_ops inet_dgram_ops; diff --git a/net/core/dev.c b/net/core/dev.c index f69b2fcdee40..619f5902600f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -145,6 +145,7 @@ #include <linux/sctp.h> #include <net/udp_tunnel.h> #include <linux/net_namespace.h> +#include <linux/indirect_call_wrapper.h> #include "net-sysfs.h" @@ -5306,6 +5307,7 @@ static void flush_all_backlogs(void) put_online_cpus(); } +INDIRECT_CALLABLE_DECLARE_2(int, network_gro_complete, struct sk_buff *, int); static int napi_gro_complete(struct sk_buff *skb) { struct packet_offload *ptype; @@ -5325,7 +5327,8 @@ static int napi_gro_complete(struct sk_buff *skb) if (ptype->type != type || !ptype->callbacks.gro_complete) continue; - err = ptype->callbacks.gro_complete(skb, 0); + err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete, + network_gro_complete, skb, 0); break; } rcu_read_unlock(); @@ -5472,6 +5475,8 @@ static void gro_flush_oldest(struct list_head *head) napi_gro_complete(oldest); } +INDIRECT_CALLABLE_DECLARE_2(struct sk_buff *, network_gro_receive, + struct list_head *, struct sk_buff *); static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) { u32 hash = skb_get_hash_raw(skb) & (GRO_HASH_BUCKETS - 1); @@ -5521,7 +5526,8 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff NAPI_GRO_CB(skb)->csum_valid = 0; } - pp = ptype->callbacks.gro_receive(gro_head, skb); + pp = INDIRECT_CALL_INET(ptype->callbacks.gro_receive, + network_gro_receive, gro_head, skb); break; } rcu_read_unlock(); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 326c422c22f8..04ab7ebd6e9b 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1505,6 +1505,8 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb) return pp; } EXPORT_SYMBOL(inet_gro_receive); +INDIRECT_CALLABLE(inet_gro_receive, 1, struct sk_buff *, network_gro_receive, + struct list_head *, struct sk_buff *); static struct sk_buff *ipip_gro_receive(struct list_head *head, struct sk_buff *skb) @@ -1589,6 +1591,8 @@ int inet_gro_complete(struct sk_buff *skb, int nhoff) return err; } EXPORT_SYMBOL(inet_gro_complete); +INDIRECT_CALLABLE(inet_gro_complete, 1, int, network_gro_complete, + struct sk_buff *, int); static int ipip_gro_complete(struct sk_buff *skb, int nhoff) { diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 70f525c33cb6..a1c2bfb2ce0d 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -270,6 +270,8 @@ static struct sk_buff *ipv6_gro_receive(struct list_head *head, return pp; } +INDIRECT_CALLABLE(ipv6_gro_receive, 2, struct sk_buff *, network_gro_receive, + struct list_head *, struct sk_buff *); static struct sk_buff *sit_ip6ip6_gro_receive(struct list_head *head, struct sk_buff *skb) @@ -327,6 +329,8 @@ static int ipv6_gro_complete(struct sk_buff *skb, int nhoff) return err; } +INDIRECT_CALLABLE(ipv6_gro_complete, 2, int, network_gro_complete, + struct sk_buff *, int); static int sit_gro_complete(struct sk_buff *skb, int nhoff) { -- 2.19.2