diff options
author | Eric Dumazet <edumazet@google.com> | 2013-02-07 11:41:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-08 17:55:48 -0500 |
commit | 3807ff5899f892abb4f06747c245fd648a2acdc5 (patch) | |
tree | a4c6bc690e612da44dab7e8beb71c5c0bdb8b6ba /drivers/net/macvlan.c | |
parent | d527043040740f41192dfd71793f905a998ee4f6 (diff) |
macvlan: add a salt to mc_hash()
Some multicast addresses are common to all macvlans,
so if a multicast message has a hash value collision, we
have to deliver a copy to all macvlans, adding significant
latency and possible packet drops if netdev_max_backlog
limit is hit.
Having a per macvlan hash function permits to reduce the
impact of hash collisions.
Suggested-by: Maciej Żenczykowski <maze@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Maciej Żenczykowski <maze@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index ce7c9268c740..e4b8078e88a9 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -127,10 +127,18 @@ static int macvlan_broadcast_one(struct sk_buff *skb, | |||
127 | return vlan->receive(skb); | 127 | return vlan->receive(skb); |
128 | } | 128 | } |
129 | 129 | ||
130 | static unsigned int mc_hash(const unsigned char *addr) | 130 | static u32 macvlan_hash_mix(const struct macvlan_dev *vlan) |
131 | { | ||
132 | return (u32)(((unsigned long)vlan) >> L1_CACHE_SHIFT); | ||
133 | } | ||
134 | |||
135 | |||
136 | static unsigned int mc_hash(const struct macvlan_dev *vlan, | ||
137 | const unsigned char *addr) | ||
131 | { | 138 | { |
132 | u32 val = __get_unaligned_cpu32(addr + 2); | 139 | u32 val = __get_unaligned_cpu32(addr + 2); |
133 | 140 | ||
141 | val ^= macvlan_hash_mix(vlan); | ||
134 | return hash_32(val, MACVLAN_MC_FILTER_BITS); | 142 | return hash_32(val, MACVLAN_MC_FILTER_BITS); |
135 | } | 143 | } |
136 | 144 | ||
@@ -145,7 +153,7 @@ static void macvlan_broadcast(struct sk_buff *skb, | |||
145 | struct sk_buff *nskb; | 153 | struct sk_buff *nskb; |
146 | unsigned int i; | 154 | unsigned int i; |
147 | int err; | 155 | int err; |
148 | unsigned int hash = mc_hash(eth->h_dest); | 156 | unsigned int hash; |
149 | 157 | ||
150 | if (skb->protocol == htons(ETH_P_PAUSE)) | 158 | if (skb->protocol == htons(ETH_P_PAUSE)) |
151 | return; | 159 | return; |
@@ -155,6 +163,7 @@ static void macvlan_broadcast(struct sk_buff *skb, | |||
155 | if (vlan->dev == src || !(vlan->mode & mode)) | 163 | if (vlan->dev == src || !(vlan->mode & mode)) |
156 | continue; | 164 | continue; |
157 | 165 | ||
166 | hash = mc_hash(vlan, eth->h_dest); | ||
158 | if (!test_bit(hash, vlan->mc_filter)) | 167 | if (!test_bit(hash, vlan->mc_filter)) |
159 | continue; | 168 | continue; |
160 | nskb = skb_clone(skb, GFP_ATOMIC); | 169 | nskb = skb_clone(skb, GFP_ATOMIC); |
@@ -424,10 +433,10 @@ static void macvlan_set_mac_lists(struct net_device *dev) | |||
424 | 433 | ||
425 | bitmap_zero(filter, MACVLAN_MC_FILTER_SZ); | 434 | bitmap_zero(filter, MACVLAN_MC_FILTER_SZ); |
426 | netdev_for_each_mc_addr(ha, dev) { | 435 | netdev_for_each_mc_addr(ha, dev) { |
427 | __set_bit(mc_hash(ha->addr), filter); | 436 | __set_bit(mc_hash(vlan, ha->addr), filter); |
428 | } | 437 | } |
429 | 438 | ||
430 | __set_bit(mc_hash(dev->broadcast), filter); | 439 | __set_bit(mc_hash(vlan, dev->broadcast), filter); |
431 | 440 | ||
432 | bitmap_copy(vlan->mc_filter, filter, MACVLAN_MC_FILTER_SZ); | 441 | bitmap_copy(vlan->mc_filter, filter, MACVLAN_MC_FILTER_SZ); |
433 | } | 442 | } |