680-NET-skip-GRO-for-foreign-MAC-addresses.patch 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. From: Felix Fietkau <[email protected]>
  2. Subject: net: replace GRO optimization patch with a new one that supports VLANs/bridges with different MAC addresses
  3. Signed-off-by: Felix Fietkau <[email protected]>
  4. ---
  5. include/linux/netdevice.h | 2 ++
  6. include/linux/skbuff.h | 3 ++-
  7. net/core/dev.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++
  8. net/ethernet/eth.c | 18 +++++++++++++++++-
  9. 4 files changed, 69 insertions(+), 2 deletions(-)
  10. --- a/include/linux/netdevice.h
  11. +++ b/include/linux/netdevice.h
  12. @@ -2210,6 +2210,8 @@ struct net_device {
  13. struct netdev_hw_addr_list mc;
  14. struct netdev_hw_addr_list dev_addrs;
  15. + unsigned char local_addr_mask[MAX_ADDR_LEN];
  16. +
  17. #ifdef CONFIG_SYSFS
  18. struct kset *queues_kset;
  19. #endif
  20. --- a/include/linux/skbuff.h
  21. +++ b/include/linux/skbuff.h
  22. @@ -964,6 +964,7 @@ struct sk_buff {
  23. #ifdef CONFIG_IPV6_NDISC_NODETYPE
  24. __u8 ndisc_nodetype:2;
  25. #endif
  26. + __u8 gro_skip:1;
  27. #if IS_ENABLED(CONFIG_IP_VS)
  28. __u8 ipvs_property:1;
  29. --- a/net/core/gro.c
  30. +++ b/net/core/gro.c
  31. @@ -445,6 +445,9 @@ static enum gro_result dev_gro_receive(s
  32. enum gro_result ret;
  33. int same_flow;
  34. + if (skb->gro_skip)
  35. + goto normal;
  36. +
  37. if (netif_elide_gro(skb->dev))
  38. goto normal;
  39. --- a/net/core/dev.c
  40. +++ b/net/core/dev.c
  41. @@ -7689,6 +7689,48 @@ static void __netdev_adjacent_dev_unlink
  42. &upper_dev->adj_list.lower);
  43. }
  44. +static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr,
  45. + struct net_device *dev)
  46. +{
  47. + int i;
  48. +
  49. + for (i = 0; i < dev->addr_len; i++)
  50. + mask[i] |= addr[i] ^ dev->dev_addr[i];
  51. +}
  52. +
  53. +static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev,
  54. + struct net_device *lower)
  55. +{
  56. + struct net_device *cur;
  57. + struct list_head *iter;
  58. +
  59. + netdev_for_each_upper_dev_rcu(dev, cur, iter) {
  60. + __netdev_addr_mask(mask, cur->dev_addr, lower);
  61. + __netdev_upper_mask(mask, cur, lower);
  62. + }
  63. +}
  64. +
  65. +static void __netdev_update_addr_mask(struct net_device *dev)
  66. +{
  67. + unsigned char mask[MAX_ADDR_LEN];
  68. + struct net_device *cur;
  69. + struct list_head *iter;
  70. +
  71. + memset(mask, 0, sizeof(mask));
  72. + __netdev_upper_mask(mask, dev, dev);
  73. + memcpy(dev->local_addr_mask, mask, dev->addr_len);
  74. +
  75. + netdev_for_each_lower_dev(dev, cur, iter)
  76. + __netdev_update_addr_mask(cur);
  77. +}
  78. +
  79. +static void netdev_update_addr_mask(struct net_device *dev)
  80. +{
  81. + rcu_read_lock();
  82. + __netdev_update_addr_mask(dev);
  83. + rcu_read_unlock();
  84. +}
  85. +
  86. static int __netdev_upper_dev_link(struct net_device *dev,
  87. struct net_device *upper_dev, bool master,
  88. void *upper_priv, void *upper_info,
  89. @@ -7740,6 +7782,7 @@ static int __netdev_upper_dev_link(struc
  90. if (ret)
  91. return ret;
  92. + netdev_update_addr_mask(dev);
  93. ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
  94. &changeupper_info.info);
  95. ret = notifier_to_errno(ret);
  96. @@ -7836,6 +7879,7 @@ static void __netdev_upper_dev_unlink(st
  97. __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
  98. + netdev_update_addr_mask(dev);
  99. call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
  100. &changeupper_info.info);
  101. @@ -8892,6 +8936,7 @@ int dev_set_mac_address(struct net_devic
  102. return err;
  103. }
  104. dev->addr_assign_type = NET_ADDR_SET;
  105. + netdev_update_addr_mask(dev);
  106. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  107. add_device_randomness(dev->dev_addr, dev->addr_len);
  108. return 0;
  109. --- a/net/ethernet/eth.c
  110. +++ b/net/ethernet/eth.c
  111. @@ -143,6 +143,18 @@ u32 eth_get_headlen(const struct net_dev
  112. }
  113. EXPORT_SYMBOL(eth_get_headlen);
  114. +static inline bool
  115. +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
  116. +{
  117. + const u16 *a1 = addr1;
  118. + const u16 *a2 = addr2;
  119. + const u16 *m = mask;
  120. +
  121. + return (((a1[0] ^ a2[0]) & ~m[0]) |
  122. + ((a1[1] ^ a2[1]) & ~m[1]) |
  123. + ((a1[2] ^ a2[2]) & ~m[2]));
  124. +}
  125. +
  126. /**
  127. * eth_type_trans - determine the packet's protocol ID.
  128. * @skb: received socket data
  129. @@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk
  130. } else {
  131. skb->pkt_type = PACKET_OTHERHOST;
  132. }
  133. +
  134. + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
  135. + dev->local_addr_mask))
  136. + skb->gro_skip = 1;
  137. }
  138. /*