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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. @@ -2036,6 +2036,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. @@ -858,6 +858,7 @@ struct sk_buff {
  23. #ifdef CONFIG_TLS_DEVICE
  24. __u8 decrypted: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. @@ -6066,6 +6066,9 @@ static enum gro_result dev_gro_receive(s
  32. int same_flow;
  33. int grow;
  34. + if (skb->gro_skip)
  35. + goto normal;
  36. +
  37. if (netif_elide_gro(skb->dev))
  38. goto normal;
  39. @@ -8043,6 +8046,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. @@ -8094,6 +8139,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,
  92. &changeupper_info.info);
  93. ret = notifier_to_errno(ret);
  94. @@ -8190,6 +8236,7 @@ static void __netdev_upper_dev_unlink(st
  95. __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
  96. + netdev_update_addr_mask(dev);
  97. call_netdevice_notifiers_info(NETDEV_CHANGEUPPER,
  98. &changeupper_info.info);
  99. @@ -8976,6 +9023,7 @@ int dev_set_mac_address(struct net_devic
  100. if (err)
  101. return err;
  102. dev->addr_assign_type = NET_ADDR_SET;
  103. + netdev_update_addr_mask(dev);
  104. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  105. add_device_randomness(dev->dev_addr, dev->addr_len);
  106. return 0;
  107. --- a/net/ethernet/eth.c
  108. +++ b/net/ethernet/eth.c
  109. @@ -143,6 +143,18 @@ u32 eth_get_headlen(const struct net_dev
  110. }
  111. EXPORT_SYMBOL(eth_get_headlen);
  112. +static inline bool
  113. +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
  114. +{
  115. + const u16 *a1 = addr1;
  116. + const u16 *a2 = addr2;
  117. + const u16 *m = mask;
  118. +
  119. + return (((a1[0] ^ a2[0]) & ~m[0]) |
  120. + ((a1[1] ^ a2[1]) & ~m[1]) |
  121. + ((a1[2] ^ a2[2]) & ~m[2]));
  122. +}
  123. +
  124. /**
  125. * eth_type_trans - determine the packet's protocol ID.
  126. * @skb: received socket data
  127. @@ -174,6 +186,10 @@ __be16 eth_type_trans(struct sk_buff *sk
  128. } else {
  129. skb->pkt_type = PACKET_OTHERHOST;
  130. }
  131. +
  132. + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
  133. + dev->local_addr_mask))
  134. + skb->gro_skip = 1;
  135. }
  136. /*