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. ====================
This commit is contained in:
commit
dea6328b2e
@ -3,10 +3,23 @@
|
||||
#ifndef _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 *,
|
||||
struct sk_buff *));
|
||||
INDIRECT_CALLABLE_DECLARE(int ipv6_gro_complete(struct sk_buff *, int));
|
||||
INDIRECT_CALLABLE_DECLARE(struct sk_buff *inet_gro_receive(struct list_head *,
|
||||
struct sk_buff *));
|
||||
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 */
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/netpoll.h>
|
||||
#include <linux/export.h>
|
||||
#include <net/gro.h>
|
||||
#include "vlan.h"
|
||||
|
||||
bool vlan_do_receive(struct sk_buff **skbp)
|
||||
@ -495,7 +496,10 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
|
||||
|
||||
skb_gro_pull(skb, 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:
|
||||
rcu_read_unlock();
|
||||
@ -515,7 +519,9 @@ static int vlan_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
rcu_read_lock();
|
||||
ptype = gro_find_complete_by_type(type);
|
||||
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();
|
||||
return err;
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/flow_dissector.h>
|
||||
#include <net/gro.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <net/pkt_sched.h>
|
||||
|
||||
@ -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_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:
|
||||
rcu_read_unlock();
|
||||
@ -473,8 +477,9 @@ int eth_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
rcu_read_lock();
|
||||
ptype = gro_find_complete_by_type(type);
|
||||
if (ptype != NULL)
|
||||
err = ptype->callbacks.gro_complete(skb, nhoff +
|
||||
sizeof(struct ethhdr));
|
||||
err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
|
||||
ipv6_gro_complete, inet_gro_complete,
|
||||
skb, nhoff + sizeof(*eh));
|
||||
|
||||
rcu_read_unlock();
|
||||
return err;
|
||||
|
Loading…
x
Reference in New Issue
Block a user