kernel: bump 4.14 to 4.14.18
[oweals/openwrt.git] / target / linux / generic / pending-4.14 / 680-NET-skip-GRO-for-foreign-MAC-addresses.patch
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 @@ -1739,6 +1739,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 @@ -780,6 +780,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 @@ -4768,6 +4768,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 @@ -6238,6 +6241,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 @@ -6353,6 +6398,8 @@ void netdev_upper_dev_unlink(struct net_
95  
96         __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
97  
98 +       netdev_update_addr_mask(dev);
99 +       netdev_update_addr_mask(dev);
100         call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
101                                       &changeupper_info.info);
102  }
103 @@ -6923,6 +6970,7 @@ int dev_set_mac_address(struct net_devic
104         if (err)
105                 return err;
106         dev->addr_assign_type = NET_ADDR_SET;
107 +       netdev_update_addr_mask(dev);
108         call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
109         add_device_randomness(dev->dev_addr, dev->addr_len);
110         return 0;
111 --- a/net/ethernet/eth.c
112 +++ b/net/ethernet/eth.c
113 @@ -144,6 +144,18 @@ u32 eth_get_headlen(void *data, unsigned
114  }
115  EXPORT_SYMBOL(eth_get_headlen);
116  
117 +static inline bool
118 +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
119 +{
120 +       const u16 *a1 = addr1;
121 +       const u16 *a2 = addr2;
122 +       const u16 *m = mask;
123 +
124 +       return (((a1[0] ^ a2[0]) & ~m[0]) |
125 +               ((a1[1] ^ a2[1]) & ~m[1]) |
126 +               ((a1[2] ^ a2[2]) & ~m[2]));
127 +}
128 +
129  /**
130   * eth_type_trans - determine the packet's protocol ID.
131   * @skb: received socket data
132 @@ -172,8 +184,12 @@ __be16 eth_type_trans(struct sk_buff *sk
133                         skb->pkt_type = PACKET_MULTICAST;
134         }
135         else if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
136 -                                                  dev->dev_addr)))
137 +                                                  dev->dev_addr))) {
138                 skb->pkt_type = PACKET_OTHERHOST;
139 +               if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
140 +                                        dev->local_addr_mask))
141 +                       skb->gro_skip = 1;
142 +       }
143  
144         /*
145          * Some variants of DSA tagging don't have an ethertype field