Skip to content

Commit dea6328

Browse files
committed
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. ====================
2 parents 1816bf1 + 5588796 commit dea6328

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

include/net/gro.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@
33
#ifndef _NET_IPV6_GRO_H
44
#define _NET_IPV6_GRO_H
55

6+
#include <linux/indirect_call_wrapper.h>
7+
8+
struct list_head;
9+
struct sk_buff;
10+
611
INDIRECT_CALLABLE_DECLARE(struct sk_buff *ipv6_gro_receive(struct list_head *,
712
struct sk_buff *));
813
INDIRECT_CALLABLE_DECLARE(int ipv6_gro_complete(struct sk_buff *, int));
914
INDIRECT_CALLABLE_DECLARE(struct sk_buff *inet_gro_receive(struct list_head *,
1015
struct sk_buff *));
1116
INDIRECT_CALLABLE_DECLARE(int inet_gro_complete(struct sk_buff *, int));
17+
18+
#define indirect_call_gro_receive_inet(cb, f2, f1, head, skb) \
19+
({ \
20+
unlikely(gro_recursion_inc_test(skb)) ? \
21+
NAPI_GRO_CB(skb)->flush |= 1, NULL : \
22+
INDIRECT_CALL_INET(cb, f2, f1, head, skb); \
23+
})
24+
1225
#endif /* _NET_IPV6_GRO_H */

net/8021q/vlan_core.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/if_vlan.h>
55
#include <linux/netpoll.h>
66
#include <linux/export.h>
7+
#include <net/gro.h>
78
#include "vlan.h"
89

910
bool vlan_do_receive(struct sk_buff **skbp)
@@ -495,7 +496,10 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
495496

496497
skb_gro_pull(skb, sizeof(*vhdr));
497498
skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
498-
pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
499+
500+
pp = indirect_call_gro_receive_inet(ptype->callbacks.gro_receive,
501+
ipv6_gro_receive, inet_gro_receive,
502+
head, skb);
499503

500504
out_unlock:
501505
rcu_read_unlock();
@@ -515,7 +519,9 @@ static int vlan_gro_complete(struct sk_buff *skb, int nhoff)
515519
rcu_read_lock();
516520
ptype = gro_find_complete_by_type(type);
517521
if (ptype)
518-
err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(*vhdr));
522+
err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
523+
ipv6_gro_complete, inet_gro_complete,
524+
skb, nhoff + sizeof(*vhdr));
519525

520526
rcu_read_unlock();
521527
return err;

net/ethernet/eth.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
#include <net/ip.h>
5959
#include <net/dsa.h>
6060
#include <net/flow_dissector.h>
61+
#include <net/gro.h>
6162
#include <linux/uaccess.h>
6263
#include <net/pkt_sched.h>
6364

@@ -449,7 +450,10 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
449450

450451
skb_gro_pull(skb, sizeof(*eh));
451452
skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
452-
pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
453+
454+
pp = indirect_call_gro_receive_inet(ptype->callbacks.gro_receive,
455+
ipv6_gro_receive, inet_gro_receive,
456+
head, skb);
453457

454458
out_unlock:
455459
rcu_read_unlock();
@@ -473,8 +477,9 @@ int eth_gro_complete(struct sk_buff *skb, int nhoff)
473477
rcu_read_lock();
474478
ptype = gro_find_complete_by_type(type);
475479
if (ptype != NULL)
476-
err = ptype->callbacks.gro_complete(skb, nhoff +
477-
sizeof(struct ethhdr));
480+
err = INDIRECT_CALL_INET(ptype->callbacks.gro_complete,
481+
ipv6_gro_complete, inet_gro_complete,
482+
skb, nhoff + sizeof(*eh));
478483

479484
rcu_read_unlock();
480485
return err;

0 commit comments

Comments
 (0)