Commit dea6328b authored by David S. Miller's avatar David S. Miller

Merge branch 'gro-retpoline'

Alexander Lobakin says:

====================
net: avoid retpoline overhead on VLAN and TEB GRO

dev_gro_receive() uses indirect calls for IP GRO functions, but
it works only for the outermost headers and untagged frames.
Simple VLAN tag before an IP header restores the performance hit.
This simple series straightens the GRO calls for IP headers going
after VLAN tag or inner Ethernet header (GENEVE, NvGRE, VxLAN)
for retpolined kernels.
====================
parents 1816bf1f 5588796e
...@@ -3,10 +3,23 @@ ...@@ -3,10 +3,23 @@
#ifndef _NET_IPV6_GRO_H #ifndef _NET_IPV6_GRO_H
#define _NET_IPV6_GRO_H #define _NET_IPV6_GRO_H
#include <linux/indirect_call_wrapper.h>
struct list_head;
struct sk_buff;
INDIRECT_CALLABLE_DECLARE(struct sk_buff *ipv6_gro_receive(struct list_head *, INDIRECT_CALLABLE_DECLARE(struct sk_buff *ipv6_gro_receive(struct list_head *,
struct sk_buff *)); struct sk_buff *));
INDIRECT_CALLABLE_DECLARE(int ipv6_gro_complete(struct sk_buff *, int)); INDIRECT_CALLABLE_DECLARE(int ipv6_gro_complete(struct sk_buff *, int));
INDIRECT_CALLABLE_DECLARE(struct sk_buff *inet_gro_receive(struct list_head *, INDIRECT_CALLABLE_DECLARE(struct sk_buff *inet_gro_receive(struct list_head *,
struct sk_buff *)); struct sk_buff *));
INDIRECT_CALLABLE_DECLARE(int inet_gro_complete(struct sk_buff *, int)); INDIRECT_CALLABLE_DECLARE(int inet_gro_complete(struct sk_buff *, int));
#define indirect_call_gro_receive_inet(cb, f2, f1, head, skb) \
({ \
unlikely(gro_recursion_inc_test(skb)) ? \
NAPI_GRO_CB(skb)->flush |= 1, NULL : \
INDIRECT_CALL_INET(cb, f2, f1, head, skb); \
})
#endif /* _NET_IPV6_GRO_H */ #endif /* _NET_IPV6_GRO_H */
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/netpoll.h> #include <linux/netpoll.h>
#include <linux/export.h> #include <linux/export.h>
#include <net/gro.h>
#include "vlan.h" #include "vlan.h"
bool vlan_do_receive(struct sk_buff **skbp) bool vlan_do_receive(struct sk_buff **skbp)
...@@ -495,7 +496,10 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head, ...@@ -495,7 +496,10 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
skb_gro_pull(skb, sizeof(*vhdr)); skb_gro_pull(skb, sizeof(*vhdr));
skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr)); skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
pp = indirect_call_gro_receive_inet(ptype->callbacks.gro_receive,
ipv6_gro_receive, inet_gro_receive,
head, skb);
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
...@@ -515,7 +519,9 @@ static int vlan_gro_complete(struct sk_buff *skb, int nhoff) ...@@ -515,7 +519,9 @@ static int vlan_gro_complete(struct sk_buff *skb, int nhoff)
rcu_read_lock(); rcu_read_lock();
ptype = gro_find_complete_by_type(type); ptype = gro_find_complete_by_type(type);
if (ptype) if (ptype)
err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(*vhdr)); err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
ipv6_gro_complete, inet_gro_complete,
skb, nhoff + sizeof(*vhdr));
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include <net/ip.h> #include <net/ip.h>
#include <net/dsa.h> #include <net/dsa.h>
#include <net/flow_dissector.h> #include <net/flow_dissector.h>
#include <net/gro.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <net/pkt_sched.h> #include <net/pkt_sched.h>
...@@ -449,7 +450,10 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb) ...@@ -449,7 +450,10 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
skb_gro_pull(skb, sizeof(*eh)); skb_gro_pull(skb, sizeof(*eh));
skb_gro_postpull_rcsum(skb, eh, sizeof(*eh)); skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
pp = indirect_call_gro_receive_inet(ptype->callbacks.gro_receive,
ipv6_gro_receive, inet_gro_receive,
head, skb);
out_unlock: out_unlock:
rcu_read_unlock(); rcu_read_unlock();
...@@ -473,8 +477,9 @@ int eth_gro_complete(struct sk_buff *skb, int nhoff) ...@@ -473,8 +477,9 @@ int eth_gro_complete(struct sk_buff *skb, int nhoff)
rcu_read_lock(); rcu_read_lock();
ptype = gro_find_complete_by_type(type); ptype = gro_find_complete_by_type(type);
if (ptype != NULL) if (ptype != NULL)
err = ptype->callbacks.gro_complete(skb, nhoff + err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
sizeof(struct ethhdr)); ipv6_gro_complete, inet_gro_complete,
skb, nhoff + sizeof(*eh));
rcu_read_unlock(); rcu_read_unlock();
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment