• Nikolay Aleksandrov's avatar
    bridge: vlan: add per-vlan struct and move to rhashtables · 2594e906
    Nikolay Aleksandrov authored
    
    
    This patch changes the bridge vlan implementation to use rhashtables
    instead of bitmaps. The main motivation behind this change is that we
    need extensible per-vlan structures (both per-port and global) so more
    advanced features can be introduced and the vlan support can be
    extended. I've tried to break this up but the moment net_port_vlans is
    changed and the whole API goes away, thus this is a larger patch.
    A few short goals of this patch are:
    - Extensible per-vlan structs stored in rhashtables and a sorted list
    - Keep user-visible behaviour (compressed vlans etc)
    - Keep fastpath ingress/egress logic the same (optimizations to come
      later)
    
    Here's a brief list of some of the new features we'd like to introduce:
    - per-vlan counters
    - vlan ingress/egress mapping
    - per-vlan igmp configuration
    - vlan priorities
    - avoid fdb entries replication (e.g. local fdb scaling issues)
    
    The structure is kept single for both global and per-port entries so to
    avoid code duplication where possible and also because we'll soon introduce
    "port0 / aka bridge as port" which should simplify things further
    (thanks to Vlad for the suggestion!).
    
    Now we have per-vlan global rhashtable (bridge-wide) and per-vlan port
    rhashtable, if an entry is added to a port it'll get a pointer to its
    global context so it can be quickly accessed later. There's also a
    sorted vlan list which is used for stable walks and some user-visible
    behaviour such as the vlan ranges, also for error paths.
    VLANs are stored in a "vlan group" which currently contains the
    rhashtable, sorted vlan list and the number of "real" vlan entries.
    A good side-effect of this change is that it resembles how hw keeps
    per-vlan data.
    One important note after this change is that if a VLAN is being looked up
    in the bridge's rhashtable for filtering purposes (or to check if it's an
    existing usable entry, not just a global context) then the new helper
    br_vlan_should_use() needs to be used if the vlan is found. In case the
    lookup is done only with a port's vlan group, then this check can be
    skipped.
    
    Things tested so far:
    - basic vlan ingress/egress
    - pvids
    - untagged vlans
    - undef CONFIG_BRIDGE_VLAN_FILTERING
    - adding/deleting vlans in different scenarios (with/without global ctx,
      while transmitting traffic, in ranges etc)
    - loading/removing the module while having/adding/deleting vlans
    - extracting bridge vlan information (user ABI), compressed requests
    - adding/deleting fdbs on vlans
    - bridge mac change, promisc mode
    - default pvid change
    - kmemleak ON during the whole time
    Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    2594e906