2
0

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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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. @@ -1752,6 +1752,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. @@ -780,6 +780,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. @@ -4768,6 +4768,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. @@ -6238,6 +6241,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. @@ -6353,6 +6398,8 @@ void netdev_upper_dev_unlink(struct net_
  88. __netdev_adjacent_dev_unlink_neighbour(dev, upper_dev);
  89. + netdev_update_addr_mask(dev);
  90. + netdev_update_addr_mask(dev);
  91. call_netdevice_notifiers_info(NETDEV_CHANGEUPPER, dev,
  92. &changeupper_info.info);
  93. }
  94. @@ -6923,6 +6970,7 @@ int dev_set_mac_address(struct net_devic
  95. if (err)
  96. return err;
  97. dev->addr_assign_type = NET_ADDR_SET;
  98. + netdev_update_addr_mask(dev);
  99. call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
  100. add_device_randomness(dev->dev_addr, dev->addr_len);
  101. return 0;
  102. --- a/net/ethernet/eth.c
  103. +++ b/net/ethernet/eth.c
  104. @@ -144,6 +144,18 @@ u32 eth_get_headlen(void *data, unsigned
  105. }
  106. EXPORT_SYMBOL(eth_get_headlen);
  107. +static inline bool
  108. +eth_check_local_mask(const void *addr1, const void *addr2, const void *mask)
  109. +{
  110. + const u16 *a1 = addr1;
  111. + const u16 *a2 = addr2;
  112. + const u16 *m = mask;
  113. +
  114. + return (((a1[0] ^ a2[0]) & ~m[0]) |
  115. + ((a1[1] ^ a2[1]) & ~m[1]) |
  116. + ((a1[2] ^ a2[2]) & ~m[2]));
  117. +}
  118. +
  119. /**
  120. * eth_type_trans - determine the packet's protocol ID.
  121. * @skb: received socket data
  122. @@ -172,8 +184,12 @@ __be16 eth_type_trans(struct sk_buff *sk
  123. skb->pkt_type = PACKET_MULTICAST;
  124. }
  125. else if (unlikely(!ether_addr_equal_64bits(eth->h_dest,
  126. - dev->dev_addr)))
  127. + dev->dev_addr))) {
  128. skb->pkt_type = PACKET_OTHERHOST;
  129. + if (eth_check_local_mask(eth->h_dest, dev->dev_addr,
  130. + dev->local_addr_mask))
  131. + skb->gro_skip = 1;
  132. + }
  133. /*
  134. * Some variants of DSA tagging don't have an ethertype field