OpenWrt – Blame information for rev 4
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From: Felix Fietkau <nbd@nbd.name> |
2 | Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses |
||
3 | |||
4 | Signed-off-by: Felix Fietkau <nbd@nbd.name> |
||
5 | --- |
||
6 | include/linux/netdevice.h | 2 ++ |
||
7 | include/linux/skbuff.h | 3 ++- |
||
8 | net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ |
||
9 | net/ethernet/eth.c | 18 +++++++++++++++++- |
||
10 | 4 files changed, 69 insertions(+), 2 deletions(-) |
||
11 | |||
12 | --- a/include/linux/netdevice.h |
||
13 | +++ b/include/linux/netdevice.h |
||
14 | @@ -1766,6 +1766,8 @@ struct net_device { |
||
15 | struct netdev_hw_addr_list mc; |
||
16 | struct netdev_hw_addr_list dev_addrs; |
||
17 | |||
18 | + unsigned char local_addr_mask[MAX_ADDR_LEN]; |
||
19 | + |
||
20 | #ifdef CONFIG_SYSFS |
||
21 | struct kset *queues_kset; |
||
22 | #endif |
||
23 | --- a/include/linux/skbuff.h |
||
24 | +++ b/include/linux/skbuff.h |
||
25 | @@ -782,6 +782,7 @@ struct sk_buff { |
||
26 | __u8 tc_redirected:1; |
||
27 | __u8 tc_from_ingress:1; |
||
28 | #endif |
||
29 | + __u8 gro_skip:1; |
||
30 | |||
31 | #ifdef CONFIG_NET_SCHED |
||
32 | __u16 tc_index; /* traffic control index */ |
||
33 | --- a/net/core/dev.c |
||
34 | +++ b/net/core/dev.c |
||
35 | @@ -4805,6 +4805,9 @@ static enum gro_result dev_gro_receive(s |
||
36 | enum gro_result ret; |
||
37 | int grow; |
||
38 | |||
39 | + if (skb->gro_skip) |
||
40 | + goto normal; |
||
41 | + |
||
42 | if (netif_elide_gro(skb->dev)) |
||
43 | goto normal; |
||
44 | |||
45 | @@ -6279,6 +6282,48 @@ static void __netdev_adjacent_dev_unlink |
||
46 | &upper_dev->adj_list.lower); |
||
47 | } |
||
48 | |||
49 | +static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr, |
||
50 | + struct net_device *dev) |
||
51 | +{ |
||
52 | + int i; |
||
53 | + |
||
54 | + for (i = 0; i < dev->addr_len; i++) |
||
55 | + mask[i] |= addr[i] ^ dev->dev_addr[i]; |
||
56 | +} |
||
57 | + |
||
58 | +static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev, |
||
59 | + struct net_device *lower) |
||
60 | +{ |
||
61 | + struct net_device *cur; |
||
62 | + struct list_head *iter; |
||
63 | + |
||
64 | + netdev_for_each_upper_dev_rcu(dev, cur, iter) { |
||
65 | + __netdev_addr_mask(mask, cur->dev_addr, lower); |
||
66 | + __netdev_upper_mask(mask, cur, lower); |
||
67 | + } |
||
68 | +} |
||
69 | + |
||
70 | +static void __netdev_update_addr_mask(struct net_device *dev) |
||
71 | +{ |
||
72 | + unsigned char mask[MAX_ADDR_LEN]; |
||
73 | + struct net_device *cur; |
||
74 | + struct list_head *iter; |
||
75 | + |
||
76 | + memset(mask, 0, sizeof(mask)); |
||
77 | + __netdev_upper_mask(mask, dev, dev); |
||
78 | + memcpy(dev->local_addr_mask, mask, dev->addr_len); |
||
79 | + |
||
80 | + netdev_for_each_lower_dev(dev, cur, iter) |
||
81 | + __netdev_update_addr_mask(cur); |
||
82 | +} |
||
83 | + |
||
84 | +static void netdev_update_addr_mask(struct net_device *dev) |
||
85 | +{ |
||
86 | + rcu_read_lock(); |
||
87 | + __netdev_update_addr_mask(dev); |
||
88 | + rcu_read_unlock(); |
||
89 | +} |
||
90 | + |
||
91 | static int __netdev_upper_dev_link(struct net_device *dev, |
||
92 | struct net_device *upper_dev, bool master, |
||
93 | void *upper_priv, void *upper_info) |
||
94 | @@ -6317,6 +6362,7 @@ static int __netdev_upper_dev_link(struc |
||
95 | if (ret) |
||
96 | return ret; |
||
97 | |||
98 | + netdev_update_addr_mask(dev); |
||
99 | ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, |
||
100 | &changeupper_info.info); |
||
101 | ret = notifier_to_errno(ret); |
||
102 | @@ -6394,6 +6440,7 @@ void netdev_upper_dev_unlink(struct net_ |
||
103 | |||
104 | __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev); |
||
105 | |||
106 | + netdev_update_addr_mask(dev); |
||
107 | call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, |
||
108 | &changeupper_info.info); |
||
109 | } |
||
110 | @@ -6966,6 +7013,7 @@ int dev_set_mac_address(struct net_devic |
||
111 | if (err) |
||
112 | return err; |
||
113 | dev->addr_assign_type = NET_ADDR_SET; |
||
114 | + netdev_update_addr_mask(dev); |
||
115 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); |
||
116 | add_device_randomness(dev->dev_addr, dev->addr_len); |
||
117 | return 0; |
||
118 | --- a/net/ethernet/eth.c |
||
119 | +++ b/net/ethernet/eth.c |
||
120 | @@ -144,6 +144,18 @@ u32 eth_get_headlen(void *data, unsigned |
||
121 | } |
||
122 | EXPORT_SYMBOL(eth_get_headlen); |
||
123 | |||
124 | +static inline bool |
||
125 | +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) |
||
126 | +{ |
||
127 | + const u16 *a1 = addr1; |
||
128 | + const u16 *a2 = addr2; |
||
129 | + const u16 *m = mask; |
||
130 | + |
||
131 | + return (((a1[0] ^ a2[0]) & ~m[0]) | |
||
132 | + ((a1[1] ^ a2[1]) & ~m[1]) | |
||
133 | + ((a1[2] ^ a2[2]) & ~m[2])); |
||
134 | +} |
||
135 | + |
||
136 | /** |
||
137 | * eth_type_trans - determine the packet's protocol ID. |
||
138 | * @skb: received socket data |
||
139 | @@ -172,8 +184,12 @@ __be16 eth_type_trans(struct sk_buff *sk |
||
140 | skb->pkt_type = PACKET_MULTICAST; |
||
141 | } |
||
142 | else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, |
||
143 | - dev->dev_addr))) |
||
144 | + dev->dev_addr))) { |
||
145 | skb->pkt_type = PACKET_OTHERHOST; |
||
146 | + if (eth_check_local_mask(eth->h_dest, dev->dev_addr, |
||
147 | + dev->local_addr_mask)) |
||
148 | + skb->gro_skip = 1; |
||
149 | + } |
||
150 | |||
151 | /* |
||
152 | * Some variants of DSA tagging don't have an ethertype field |