Skip to content

Commit

Permalink
net: bridge: use rhashtable for fdbs
Browse files Browse the repository at this point in the history
Before this patch the bridge used a fixed 256 element hash table which
was fine for small use cases (in my tests it starts to degrade
above 1000 entries), but it wasn't enough for medium or large
scale deployments. Modern setups have thousands of participants in a
single bridge, even only enabling vlans and adding a few thousand vlan
entries will cause a few thousand fdbs to be automatically inserted per
participating port. So we need to scale the fdb table considerably to
cope with modern workloads, and this patch converts it to use a
rhashtable for its operations thus improving the bridge scalability.
Tests show the following results (10 runs each), at up to 1000 entries
rhashtable is ~3% slower, at 2000 rhashtable is 30% faster, at 3000 it
is 2 times faster and at 30000 it is 50 times faster.
Obviously this happens because of the properties of the two constructs
and is expected, rhashtable keeps pretty much a constant time even with
10000000 entries (tested), while the fixed hash table struggles
considerably even above 10000.
As a side effect this also reduces the net_bridge struct size from 3248
bytes to 1344 bytes. Also note that the key struct is 8 bytes.

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Nikolay Aleksandrov authored and David S. Miller committed Dec 13, 2017
1 parent e8952ba commit eb79358
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 219 deletions.
4 changes: 2 additions & 2 deletions include/trace/events/bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ TRACE_EVENT(fdb_delete,
TP_fast_assign(
__assign_str(br_dev, br->dev->name);
__assign_str(dev, f->dst ? f->dst->dev->name : "null");
memcpy(__entry->addr, f->addr.addr, ETH_ALEN);
__entry->vid = f->vlan_id;
memcpy(__entry->addr, f->key.addr.addr, ETH_ALEN);
__entry->vid = f->key.vlan_id;
),

TP_printk("br_dev %s dev %s addr %02x:%02x:%02x:%02x:%02x:%02x vid %u",
Expand Down
10 changes: 10 additions & 0 deletions net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,16 +125,24 @@ static int br_dev_init(struct net_device *dev)
if (!br->stats)
return -ENOMEM;

err = br_fdb_hash_init(br);
if (err) {
free_percpu(br->stats);
return err;
}

err = br_vlan_init(br);
if (err) {
free_percpu(br->stats);
br_fdb_hash_fini(br);
return err;
}

err = br_multicast_init_stats(br);
if (err) {
free_percpu(br->stats);
br_vlan_flush(br);
br_fdb_hash_fini(br);
}
br_set_lockdep_class(dev);

Expand All @@ -148,6 +156,7 @@ static void br_dev_uninit(struct net_device *dev)
br_multicast_dev_del(br);
br_multicast_uninit_stats(br);
br_vlan_flush(br);
br_fdb_hash_fini(br);
free_percpu(br->stats);
}

Expand Down Expand Up @@ -416,6 +425,7 @@ void br_dev_setup(struct net_device *dev)
br->dev = dev;
spin_lock_init(&br->lock);
INIT_LIST_HEAD(&br->port_list);
INIT_HLIST_HEAD(&br->fdb_list);
spin_lock_init(&br->hash_lock);

br->bridge_id.prio[0] = 0x80;
Expand Down
Loading

0 comments on commit eb79358

Please sign in to comment.