kernel: backport upstream DSA GRO support
[openwrt/openwrt.git] / target / linux / generic / backport-5.4 / 755-v5.8-net-dsa-add-GRO-support-via-gro_cells.patch
1 From: Alexander Lobakin <bloodyreaper@yandex.ru>
2 Date: Tue, 21 Apr 2020 16:41:08 +0300
3 Subject: [PATCH] net: dsa: add GRO support via gro_cells
4
5 gro_cells lib is used by different encapsulating netdevices, such as
6 geneve, macsec, vxlan etc. to speed up decapsulated traffic processing.
7 CPU tag is a sort of "encapsulation", and we can use the same mechs to
8 greatly improve overall DSA performance.
9 skbs are passed to the GRO layer after removing CPU tags, so we don't
10 need any new packet offload types as it was firstly proposed by me in
11 the first GRO-over-DSA variant [1].
12
13 The size of struct gro_cells is sizeof(void *), so hot struct
14 dsa_slave_priv becomes only 4/8 bytes bigger, and all critical fields
15 remain in one 32-byte cacheline.
16 The other positive side effect is that drivers for network devices
17 that can be shipped as CPU ports of DSA-driven switches can now use
18 napi_gro_frags() to pass skbs to kernel. Packets built that way are
19 completely non-linear and are likely being dropped without GRO.
20
21 This was tested on to-be-mainlined-soon Ethernet driver that uses
22 napi_gro_frags(), and the overall performance was on par with the
23 variant from [1], sometimes even better due to minimal overhead.
24 net.core.gro_normal_batch tuning may help to push it to the limit
25 on particular setups and platforms.
26
27 iperf3 IPoE VLAN NAT TCP forwarding (port1.218 -> port0) setup
28 on 1.2 GHz MIPS board:
29
30 5.7-rc2 baseline:
31
32 [ID] Interval Transfer Bitrate Retr
33 [ 5] 0.00-120.01 sec 9.00 GBytes 644 Mbits/sec 413 sender
34 [ 5] 0.00-120.00 sec 8.99 GBytes 644 Mbits/sec receiver
35
36 Iface RX packets TX packets
37 eth0 7097731 7097702
38 port0 426050 6671829
39 port1 6671681 425862
40 port1.218 6671677 425851
41
42 With this patch:
43
44 [ID] Interval Transfer Bitrate Retr
45 [ 5] 0.00-120.01 sec 12.2 GBytes 870 Mbits/sec 122 sender
46 [ 5] 0.00-120.00 sec 12.2 GBytes 870 Mbits/sec receiver
47
48 Iface RX packets TX packets
49 eth0 9474792 9474777
50 port0 455200 353288
51 port1 9019592 455035
52 port1.218 353144 455024
53
54 v2:
55 - Add some performance examples in the commit message;
56 - No functional changes.
57
58 [1] https://lore.kernel.org/netdev/20191230143028.27313-1-alobakin@dlink.ru/
59
60 Signed-off-by: Alexander Lobakin <bloodyreaper@yandex.ru>
61 Signed-off-by: David S. Miller <davem@davemloft.net>
62 ---
63
64 --- a/net/dsa/Kconfig
65 +++ b/net/dsa/Kconfig
66 @@ -9,6 +9,7 @@ menuconfig NET_DSA
67 tristate "Distributed Switch Architecture"
68 depends on HAVE_NET_DSA
69 depends on BRIDGE || BRIDGE=n
70 + select GRO_CELLS
71 select NET_SWITCHDEV
72 select PHYLINK
73 select NET_DEVLINK
74 --- a/net/dsa/dsa.c
75 +++ b/net/dsa/dsa.c
76 @@ -238,7 +238,7 @@ static int dsa_switch_rcv(struct sk_buff
77 if (dsa_skb_defer_rx_timestamp(p, skb))
78 return 0;
79
80 - netif_receive_skb(skb);
81 + gro_cells_receive(&p->gcells, skb);
82
83 return 0;
84 }
85 --- a/net/dsa/dsa_priv.h
86 +++ b/net/dsa/dsa_priv.h
87 @@ -11,6 +11,7 @@
88 #include <linux/netdevice.h>
89 #include <linux/netpoll.h>
90 #include <net/dsa.h>
91 +#include <net/gro_cells.h>
92
93 enum {
94 DSA_NOTIFIER_AGEING_TIME,
95 @@ -68,6 +69,8 @@ struct dsa_slave_priv {
96
97 struct pcpu_sw_netstats *stats64;
98
99 + struct gro_cells gcells;
100 +
101 /* DSA port data, such as switch, port index, etc. */
102 struct dsa_port *dp;
103
104 --- a/net/dsa/slave.c
105 +++ b/net/dsa/slave.c
106 @@ -1431,6 +1431,11 @@ int dsa_slave_create(struct dsa_port *po
107 free_netdev(slave_dev);
108 return -ENOMEM;
109 }
110 +
111 + ret = gro_cells_init(&p->gcells, slave_dev);
112 + if (ret)
113 + goto out_free;
114 +
115 p->dp = port;
116 INIT_LIST_HEAD(&p->mall_tc_list);
117 INIT_WORK(&port->xmit_work, dsa_port_xmit_work);
118 @@ -1443,7 +1448,7 @@ int dsa_slave_create(struct dsa_port *po
119 ret = dsa_slave_phy_setup(slave_dev);
120 if (ret) {
121 netdev_err(master, "error %d setting up slave phy\n", ret);
122 - goto out_free;
123 + goto out_gcells;
124 }
125
126 dsa_slave_notify(slave_dev, DSA_PORT_REGISTER);
127 @@ -1462,6 +1467,8 @@ out_phy:
128 phylink_disconnect_phy(p->dp->pl);
129 rtnl_unlock();
130 phylink_destroy(p->dp->pl);
131 +out_gcells:
132 + gro_cells_destroy(&p->gcells);
133 out_free:
134 free_percpu(p->stats64);
135 free_netdev(slave_dev);
136 @@ -1482,6 +1489,7 @@ void dsa_slave_destroy(struct net_device
137 dsa_slave_notify(slave_dev, DSA_PORT_UNREGISTER);
138 unregister_netdev(slave_dev);
139 phylink_destroy(dp->pl);
140 + gro_cells_destroy(&p->gcells);
141 free_percpu(p->stats64);
142 free_netdev(slave_dev);
143 }