kernel: generic: add kernel 4.3
[openwrt.git] / target / linux / generic / patches-4.3 / 680-NET-skip-GRO-for-foreign-MAC-addresses.patch
1 Subject: NET: skip GRO for foreign MAC addresses
2
3 For network drivers using napi_gro_receive, packets are run through GRO,
4 even when the destination MAC address does not match, and they're supposed
5 to be delivered to another host behind a different bridge port.
6
7 This can be very expensive, because for drivers without TSO or scatter-
8 gather, this can only be undone by copying the skb and checksumming it
9 again.
10
11 To be able to track foreign MAC addresses in an inexpensive way, create
12 a mask of changed bits in MAC addresses of upper devices. This allows
13 handling VLANs and bridge devices with different addresses (as long as
14 they are not too different).
15
16 Signed-off-by: Felix Fietkau <nbd@openwrt.org>
17
18 --- a/net/core/dev.c
19 +++ b/net/core/dev.c
20 @@ -4158,6 +4158,9 @@ static enum gro_result dev_gro_receive(s
21         enum gro_result ret;
22         int grow;
23  
24 +       if (skb->gro_skip)
25 +               goto normal;
26 +
27         if (!(skb->dev->features & NETIF_F_GRO))
28                 goto normal;
29  
30 @@ -5309,6 +5312,48 @@ static void __netdev_adjacent_dev_unlink
31                                            &upper_dev->adj_list.lower);
32  }
33  
34 +static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr,
35 +                              struct net_device *dev)
36 +{
37 +       int i;
38 +
39 +       for (i = 0; i < dev->addr_len; i++)
40 +               mask[i] |= addr[i] ^ dev->dev_addr[i];
41 +}
42 +
43 +static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev,
44 +                               struct net_device *lower)
45 +{
46 +       struct net_device *cur;
47 +       struct list_head *iter;
48 +
49 +       netdev_for_each_upper_dev_rcu(dev, cur, iter) {
50 +               __netdev_addr_mask(mask, cur->dev_addr, lower);
51 +               __netdev_upper_mask(mask, cur, lower);
52 +       }
53 +}
54 +
55 +static void __netdev_update_addr_mask(struct net_device *dev)
56 +{
57 +       unsigned char mask[MAX_ADDR_LEN];
58 +       struct net_device *cur;
59 +       struct list_head *iter;
60 +
61 +       memset(mask, 0, sizeof(mask));
62 +       __netdev_upper_mask(mask, dev, dev);
63 +       memcpy(dev->local_addr_mask, mask, dev->addr_len);
64 +
65 +       netdev_for_each_lower_dev(dev, cur, iter)
66 +               __netdev_update_addr_mask(cur);
67 +}
68 +
69 +static void netdev_update_addr_mask(struct net_device *dev)
70 +{
71 +       rcu_read_lock();
72 +       __netdev_update_addr_mask(dev);
73 +       rcu_read_unlock();
74 +}
75 +
76  static int __netdev_upper_dev_link(struct net_device *dev,
77                                    struct net_device *upper_dev, bool master,
78                                    void *private)
79 @@ -5374,6 +5419,7 @@ static int __netdev_upper_dev_link(struc
80                         goto rollback_lower_mesh;
81         }
82  
83 +       netdev_update_addr_mask(dev);
84         call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
85                                       &changeupper_info.info);
86         return 0;
87 @@ -5497,6 +5543,7 @@ void netdev_upper_dev_unlink(struct net_
88         list_for_each_entry(i, &upper_dev->all_adj_list.upper, list)
89                 __netdev_adjacent_dev_unlink(dev, i->dev);
90  
91 +       netdev_update_addr_mask(dev);
92         call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
93                                       &changeupper_info.info);
94  }
95 @@ -6037,6 +6084,7 @@ int dev_set_mac_address(struct net_devic
96         if (err)
97                 return err;
98         dev->addr_assign_type = NET_ADDR_SET;
99 +       netdev_update_addr_mask(dev);
100         call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
101         add_device_randomness(dev->dev_addr, dev->addr_len);
102         return 0;
103 --- a/include/linux/netdevice.h
104 +++ b/include/linux/netdevice.h
105 @@ -1623,6 +1623,8 @@ struct net_device {
106         struct netdev_hw_addr_list      mc;
107         struct netdev_hw_addr_list      dev_addrs;
108  
109 +       unsigned char           local_addr_mask[MAX_ADDR_LEN];
110 +
111  #ifdef CONFIG_SYSFS
112         struct kset             *queues_kset;
113  #endif
114 --- a/include/linux/skbuff.h
115 +++ b/include/linux/skbuff.h
116 @@ -632,7 +632,8 @@ struct sk_buff {
117         __u8                    ipvs_property:1;
118         __u8                    inner_protocol_type:1;
119         __u8                    remcsum_offload:1;
120 -       /* 3 or 5 bit hole */
121 +       __u8                    gro_skip:1;
122 +       /* 2 or 4 bit hole */
123  
124  #ifdef CONFIG_NET_SCHED
125         __u16                   tc_index;       /* traffic control index */
126 --- a/net/ethernet/eth.c
127 +++ b/net/ethernet/eth.c
128 @@ -140,6 +140,18 @@ u32 eth_get_headlen(void *data, unsigned
129  }
130  EXPORT_SYMBOL(eth_get_headlen);
131  
132 +static inline bool
133 +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
134 +{
135 +       const u16 *a1 = addr1;
136 +       const u16 *a2 = addr2;
137 +       const u16 *m = mask;
138 +
139 +       return (((a1[0] ^ a2[0]) & ~m[0]) |
140 +               ((a1[1] ^ a2[1]) & ~m[1]) |
141 +               ((a1[2] ^ a2[2]) & ~m[2]));
142 +}
143 +
144  /**
145   * eth_type_trans - determine the packet's protocol ID.
146   * @skb: received socket data
147 @@ -168,8 +180,12 @@ __be16 eth_type_trans(struct sk_buff *sk
148                         skb->pkt_type = PACKET_MULTICAST;
149         }
150         else if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
151 -                                                  dev->dev_addr)))
152 +                                                  dev->dev_addr))) {
153                 skb->pkt_type = PACKET_OTHERHOST;
154 +               if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
155 +                                        dev->local_addr_mask))
156 +                       skb->gro_skip = 1;
157 +       }
158  
159         /*
160          * Some variants of DSA tagging don't have an ethertype field