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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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. Signed-off-by: Felix Fietkau <nbd@nbd.name>
  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. @@ -1772,6 +1772,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. @@ -782,6 +782,7 @@ struct sk_buff {
  23. __u8 tc_redirected:1;
  24. __u8 tc_from_ingress:1;
  25. #endif
  26. + __u8 gro_skip:1;
  27. #ifdef CONFIG_NET_SCHED
  28. __u16 tc_index; /* traffic control index */
  29. --- a/net/core/dev.c
  30. +++ b/net/core/dev.c
  31. @@ -4802,6 +4802,9 @@ static enum gro_result dev_gro_receive(s
  32. enum gro_result ret;
  33. int grow;
  34. + if (skb->gro_skip)
  35. + goto normal;
  36. +
  37. if (netif_elide_gro(skb->dev))
  38. goto normal;
  39. @@ -6280,6 +6283,48 @@ static void __netdev_adjacent_dev_unlink
  40. &upper_dev->adj_list.lower);
  41. }
  42. +static void __netdev_addr_mask(unsigned char *mask, const unsigned char *addr,
  43. + struct net_device *dev)
  44. +{
  45. + int i;
  46. +
  47. + for (i = 0; i < dev->addr_len; i++)
  48. + mask[i] |= addr[i] ^ dev->dev_addr[i];
  49. +}
  50. +
  51. +static void __netdev_upper_mask(unsigned char *mask, struct net_device *dev,
  52. + struct net_device *lower)
  53. +{
  54. + struct net_device *cur;
  55. + struct list_head *iter;
  56. +
  57. + netdev_for_each_upper_dev_rcu(dev, cur, iter) {
  58. + __netdev_addr_mask(mask, cur->dev_addr, lower);
  59. + __netdev_upper_mask(mask, cur, lower);
  60. + }
  61. +}
  62. +
  63. +static void __netdev_update_addr_mask(struct net_device *dev)
  64. +{
  65. + unsigned char mask[MAX_ADDR_LEN];
  66. + struct net_device *cur;
  67. + struct list_head *iter;
  68. +
  69. + memset(mask, 0, sizeof(mask));
  70. + __netdev_upper_mask(mask, dev, dev);
  71. + memcpy(dev->local_addr_mask, mask, dev->addr_len);
  72. +
  73. + netdev_for_each_lower_dev(dev, cur, iter)
  74. + __netdev_update_addr_mask(cur);
  75. +}
  76. +
  77. +static void netdev_update_addr_mask(struct net_device *dev)
  78. +{
  79. + rcu_read_lock();
  80. + __netdev_update_addr_mask(dev);
  81. + rcu_read_unlock();
  82. +}
  83. +
  84. static int __netdev_upper_dev_link(struct net_device *dev,
  85. struct net_device *upper_dev, bool master,
  86. void *upper_priv, void *upper_info)
  87. @@ -6318,6 +6363,7 @@ static int __netdev_upper_dev_link(struc
  88. if (ret)
  89. return ret;
  90. + netdev_update_addr_mask(dev);
  91. ret = call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
  92. &changeupper_info.info);
  93. ret = notifier_to_errno(ret);
  94. @@ -6395,6 +6441,7 @@ void netdev_upper_dev_unlink(struct net_
  95. __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
  96. + netdev_update_addr_mask(dev);
  97. call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
  98. &changeupper_info.info);
  99. }
  100. @@ -6959,6 +7006,7 @@ int dev_set_mac_address(struct net_devic
  101. if (err)
  102. return err;
  103. dev->addr_assign_type = NET_ADDR_SET;
  104. + netdev_update_addr_mask(dev);
  105. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  106. add_device_randomness(dev->dev_addr, dev->addr_len);
  107. return 0;
  108. --- a/net/ethernet/eth.c
  109. +++ b/net/ethernet/eth.c
  110. @@ -144,6 +144,18 @@ u32 eth_get_headlen(void *data, unsigned
  111. }
  112. EXPORT_SYMBOL(eth_get_headlen);
  113. +static inline bool
  114. +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
  115. +{
  116. + const u16 *a1 = addr1;
  117. + const u16 *a2 = addr2;
  118. + const u16 *m = mask;
  119. +
  120. + return (((a1[0] ^ a2[0]) & ~m[0]) |
  121. + ((a1[1] ^ a2[1]) & ~m[1]) |
  122. + ((a1[2] ^ a2[2]) & ~m[2]));
  123. +}
  124. +
  125. /**
  126. * eth_type_trans - determine the packet's protocol ID.
  127. * @skb: received socket data
  128. @@ -172,8 +184,12 @@ __be16 eth_type_trans(struct sk_buff *sk
  129. skb->pkt_type = PACKET_MULTICAST;
  130. }
  131. else if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
  132. - dev->dev_addr)))
  133. + dev->dev_addr))) {
  134. skb->pkt_type = PACKET_OTHERHOST;
  135. + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
  136. + dev->local_addr_mask))
  137. + skb->gro_skip = 1;
  138. + }
  139. /*
  140. * Some variants of DSA tagging don't have an ethertype field