diff options
author | John Crispin <john@phrozen.org> | 2016-12-25 20:11:34 +0100 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2017-08-05 08:46:36 +0200 |
commit | 74d00a8c3849c1340efd713eb94b786e304c201f (patch) | |
tree | de481743de61c34da96ab5f9dba3af3edcfb8260 /target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch | |
parent | de350550ef648d9728351b986b0516fa29465c45 (diff) | |
download | mtk-20170518-74d00a8c3849c1340efd713eb94b786e304c201f.zip mtk-20170518-74d00a8c3849c1340efd713eb94b786e304c201f.tar.gz mtk-20170518-74d00a8c3849c1340efd713eb94b786e304c201f.tar.bz2 |
kernel: split patches folder up into backport, pending and hack folders
* properly format/comment all patches
* merge debloat patches
* merge Kconfig patches
* merge swconfig patches
* merge hotplug patches
* drop 200-fix_localversion.patch - upstream
* drop 222-arm_zimage_none.patch - unused
* drop 252-mv_cesa_depends.patch - no longer required
* drop 410-mtd-move-forward-declaration-of-struct-mtd_info.patch - unused
* drop 661-fq_codel_keep_dropped_stats.patch - outdated
* drop 702-phy_add_aneg_done_function.patch - upstream
* drop 840-rtc7301.patch - unused
* drop 841-rtc_pt7c4338.patch - upstream
* drop 921-use_preinit_as_init.patch - unused
* drop spio-gpio-old and gpio-mmc - unused
Signed-off-by: John Crispin <john@phrozen.org>
Diffstat (limited to 'target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch')
-rw-r--r-- | target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch b/target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch new file mode 100644 index 0000000..e886d70 --- /dev/null +++ b/target/linux/generic/pending-4.9/680-NET-skip-GRO-for-foreign-MAC-addresses.patch @@ -0,0 +1,158 @@ +From: Felix Fietkau <nbd@nbd.name> +Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses + +Signed-off-by: Felix Fietkau <nbd@nbd.name> +--- + include/linux/netdevice.h | 2 ++ + include/linux/skbuff.h | 3 ++- + net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ + net/ethernet/eth.c | 18 +++++++++++++++++- + 4 files changed, 69 insertions(+), 2 deletions(-) + +diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h +index 780e7171f548..6b738c662bc1 100644 +--- a/include/linux/netdevice.h ++++ b/include/linux/netdevice.h +@@ -1749,6 +1749,8 @@ struct net_device { + struct netdev_hw_addr_list mc; + struct netdev_hw_addr_list dev_addrs; + ++ unsigned char local_addr_mask[MAX_ADDR_LEN]; ++ + #ifdef CONFIG_SYSFS + struct kset *queues_kset; + #endif +diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h +index 5f3343ae25ef..3a04baab9b28 100644 +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -742,7 +742,8 @@ struct sk_buff { + #ifdef CONFIG_NET_SWITCHDEV + __u8 offload_fwd_mark:1; + #endif +- /* 2, 4 or 5 bit hole */ ++ __u8 gro_skip:1; ++ /* 1, 3 or 4 bit hole */ + + #ifdef CONFIG_NET_SCHED + __u16 tc_index; /* traffic control index */ +diff --git a/net/core/dev.c b/net/core/dev.c +index 2e04fd188081..c7c96308bc84 100644 +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -4512,6 +4512,9 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff + enum gro_result ret; + int grow; + ++ if (skb->gro_skip) ++ goto normal; ++ + if (!(skb->dev->features & NETIF_F_GRO)) + goto normal; + +@@ -5789,6 +5792,48 @@ static void __netdev_adjacent_dev_unlink_neighbour(struct net_device *dev, + &upper_dev->adj_list.lower); + } + ++static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr, ++ struct net_device *dev) ++{ ++ int i; ++ ++ for (i = 0; i < dev->addr_len; i++) ++ mask[i] |= addr[i] ^ dev->dev_addr[i]; ++} ++ ++static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev, ++ struct net_device *lower) ++{ ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ netdev_for_each_upper_dev_rcu(dev, cur, iter) { ++ __netdev_addr_mask(mask, cur->dev_addr, lower); ++ __netdev_upper_mask(mask, cur, lower); ++ } ++} ++ ++static void __netdev_update_addr_mask(struct net_device *dev) ++{ ++ unsigned char mask[MAX_ADDR_LEN]; ++ struct net_device *cur; ++ struct list_head *iter; ++ ++ memset(mask, 0, sizeof(mask)); ++ __netdev_upper_mask(mask, dev, dev); ++ memcpy(dev->local_addr_mask, mask, dev->addr_len); ++ ++ netdev_for_each_lower_dev(dev, cur, iter) ++ __netdev_update_addr_mask(cur); ++} ++ ++static void netdev_update_addr_mask(struct net_device *dev) ++{ ++ rcu_read_lock(); ++ __netdev_update_addr_mask(dev); ++ rcu_read_unlock(); ++} ++ + static int __netdev_upper_dev_link(struct net_device *dev, + struct net_device *upper_dev, bool master, + void *upper_priv, void *upper_info) +@@ -5987,6 +6032,8 @@ void netdev_upper_dev_unlink(struct net_device *dev, + list_for_each_entry(i, &upper_dev->all_adj_list.upper, list) + __netdev_adjacent_dev_unlink(dev, i->dev, i->ref_nr); + ++ netdev_update_addr_mask(dev); ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev, + &changeupper_info.info); + } +@@ -6587,6 +6634,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) + if (err) + return err; + dev->addr_assign_type = NET_ADDR_SET; ++ netdev_update_addr_mask(dev); + call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); + return 0; +diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c +index fbf1de965a9a..6a6d90b9a880 100644 +--- a/net/ethernet/eth.c ++++ b/net/ethernet/eth.c +@@ -143,6 +143,18 @@ u32 eth_get_headlen(void *data, unsigned int len) + } + EXPORT_SYMBOL(eth_get_headlen); + ++static inline bool ++eth_check_local_mask(const void *addr1, const void *addr2, const void *mask) ++{ ++ const u16 *a1 = addr1; ++ const u16 *a2 = addr2; ++ const u16 *m = mask; ++ ++ return (((a1[0] ^ a2[0]) & ~m[0]) | ++ ((a1[1] ^ a2[1]) & ~m[1]) | ++ ((a1[2] ^ a2[2]) & ~m[2])); ++} ++ + /** + * eth_type_trans - determine the packet's protocol ID. + * @skb: received socket data +@@ -171,8 +183,12 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) + skb->pkt_type = PACKET_MULTICAST; + } + else if (unlikely(!ether_addr_equal_64bits(eth->h_dest, +- dev->dev_addr))) ++ dev->dev_addr))) { + skb->pkt_type = PACKET_OTHERHOST; ++ if (eth_check_local_mask(eth->h_dest, dev->dev_addr, ++ dev->local_addr_mask)) ++ skb->gro_skip = 1; ++ } + + /* + * Some variants of DSA tagging don't have an ethertype field +-- +2.11.0 + |