Skip to content

Commit

Permalink
Merge branch 'bridge_vlan'
Browse files Browse the repository at this point in the history
Vlad Yasevich says:

====================
VLAN filtering/VLAN aware bridge

Changes since v10
* Updated implemenation of ndo_fdb_del in emulex and qlogic drivers.

Changes since v9:
* series re-ordering so make functionality more distinct.  Basic vlan
  filtering is patches 1-4.  Support for PVID/untagged vlans is patches
  5 and 6.  VLAN support for FDB/MDB is patches 7-11.  Patch 12 is
  still additional egress policy.
* Slight simplification to code that extracts the VID from skb.  Since we
  now depend on the vlan module, at the time of input skb_tci is guaranteed
  to be set if the packet had 8021q header.  We can simply refere to it.
* Changed the opaque 'parent' pointer from prior patches to a union so we
  can be much more explicit in our assignments.
* Lots of additional testing with STP turned on.  No issues were observed.

Changes since v8:
* Unified vlans_to_* calls into a single interface
* Fixed the rest of the issues report by Michal Miroslaw
* Fixed a bug where fdb entries were not created for all added vlans.

Changes since v7:
* Rebases on the latest net-next and removed the vlan wrapper patch from
the series.
* Fixed a crash in br_fdb_add/br_fdb_delete.

Changes since v6:
* VLANs are now stored in a VLAN bitmap per port.  This allows for O(1)
lookup at ingress and egress.  We simply check to see if the bit associated
with the vlan id is set in the map.  The drawback to this approach is that
it wastes some space when there is only a small number of VLANs.
* In addition to the build time configuration option, VLAN filtering also has
a configuration paramter in sysfs.  By default the filtering is turned off
and all traffic is permitted.  When the filtring is turned on, we do strict
matching to the filter configured.  Thus, if there is no configuration, all
packets are rejected.  This was done to make the behavior more streight
forward.  Without this (and if egress policy patch is rejected), the
decision for how to forward untagged traffic that was not filtered at ingress
is almost impossible to make.  It would not be right to deliver to every
port that has PVID set as, each port may have a different PVID.
* Separate egress policy bitmap patch has been isolated and is provided last
in the series.  This has been a more contentious piece of functionality and I
wanted to isolate it so that it could easily be dropped and not block the whole
series.

Changes since v5:
 - Pulled VLAN filtering into its own file and made it a configuration options.
 - Made new vlan filtering option dependent on VLAN_8021Q.
 - Got rid of HW filter inlines and moved then vlan_core.c.
   (All of the above suggested by Stephen Hemminger)

Changes since v4:
 - Pull per-port vlan data into its own structures and give it to the bridge
   device thus making bridge device behave like a regular port for vlan
   configuration.
 - Add a per-vlan 'untagged' bitmap that determins egress policy.  If a port
   is part of this bitmap, traffic egresses untagged.
 - PVID is now used for ingress policy only.  Incomming frames without VLAN tag
   are assigned to the PVID vlan.  Egress is determined via bitmap memberships.
 - Allow for incremental config of a vlan.  Now, PVID and untagged memberships
   may be set on existing vlans.  They however can NOT be cleared separately.
 - VLAN deletion is now done via RTM_DELLINK command for PF_BRIDGE family.
   This cleans up the netlink interface.

Changes since v3:
 - Re-integrated compiler problems that got left out last time.  Appologies.
 - checkpatches.pl errors fixed

Changes since v2:
 - Added inline functiosn to manimulate vlan hw filters and re-use in 8021q
   and bridge code.
 - Use rtnl_dereference (Michael Tsirkin)
 - Remove synchronize_net() call (Eric Dumazet)
 - Fix NULL ptr deref bug I introduced in br_ifinfo_notify.

Changes since v1:
 - Fixed some forwarding bugs.
 - Add vlan to local fdb entries.  New local entries are created per vlan
   to facilite correct forwarding to bridge interface.
 - Allow configuration of vlans directly on the bridge master device
   in addition to ports.

Changes since rfc v2:
 - Per-port vlan bitmap is gone and is replaced with a vlan list.
 - Added bridge vlan list, which is referenced by each port.  Entries in
   the birdge vlan list have port bitmap that shows which port are parts
   of which vlan.
 - Netlink API changes.
 - Dropped sysfs support for now.  If people think this is really usefull,
   can add it back.
 - Support for native/untagged vlans.

Changes since rfc v1:
 - Comments addressed regarding formatting and RCU usage
 - iocts have been removed and changed over the netlink interface.
 - Added support of user added ndb entries.
 - changed sysfs interface to export a bitmap.  Also added a write interface.
   I am not sure how much I like it, but it made my testing easier/faster.  I
   might change the write interface to take text instead of binary.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Feb 14, 2013
2 parents 2222299 + 35e03f3 commit 93197b1
Show file tree
Hide file tree
Showing 23 changed files with 1,265 additions and 131 deletions.
5 changes: 3 additions & 2 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7002,7 +7002,7 @@ static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return err;
}

static int ixgbe_ndo_fdb_del(struct ndmsg *ndm,
static int ixgbe_ndo_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr)
{
Expand Down Expand Up @@ -7079,7 +7079,8 @@ static int ixgbe_ndo_bridge_setlink(struct net_device *dev,
}

static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
struct net_device *dev)
struct net_device *dev,
u32 filter_mask)
{
struct ixgbe_adapter *adapter = netdev_priv(dev);
u16 mode;
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/mellanox/mlx4/en_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1959,6 +1959,7 @@ static int mlx4_en_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
}

static int mlx4_en_fdb_del(struct ndmsg *ndm,
struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr)
{
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,8 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p)
return 0;
}

static int qlcnic_fdb_del(struct ndmsg *ndm, struct net_device *netdev,
const unsigned char *addr)
static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *netdev, const unsigned char *addr)
{
struct qlcnic_adapter *adapter = netdev_priv(netdev);
int err = -EOPNOTSUPP;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ static int macvlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
return err;
}

static int macvlan_fdb_del(struct ndmsg *ndm,
static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr)
{
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,8 @@ static int vxlan_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
}

/* Delete entry (via netlink) */
static int vxlan_fdb_delete(struct ndmsg *ndm, struct net_device *dev,
static int vxlan_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
Expand Down
9 changes: 7 additions & 2 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,8 @@ struct netdev_fcoe_hbainfo {
* struct net_device *dev,
* const unsigned char *addr, u16 flags)
* Adds an FDB entry to dev for addr.
* int (*ndo_fdb_del)(struct ndmsg *ndm, struct net_device *dev,
* int (*ndo_fdb_del)(struct ndmsg *ndm, struct nlattr *tb[],
* struct net_device *dev,
* const unsigned char *addr)
* Deletes the FDB entry from dev coresponding to addr.
* int (*ndo_fdb_dump)(struct sk_buff *skb, struct netlink_callback *cb,
Expand Down Expand Up @@ -1008,6 +1009,7 @@ struct net_device_ops {
const unsigned char *addr,
u16 flags);
int (*ndo_fdb_del)(struct ndmsg *ndm,
struct nlattr *tb[],
struct net_device *dev,
const unsigned char *addr);
int (*ndo_fdb_dump)(struct sk_buff *skb,
Expand All @@ -1019,7 +1021,10 @@ struct net_device_ops {
struct nlmsghdr *nlh);
int (*ndo_bridge_getlink)(struct sk_buff *skb,
u32 pid, u32 seq,
struct net_device *dev);
struct net_device *dev,
u32 filter_mask);
int (*ndo_bridge_dellink)(struct net_device *dev,
struct nlmsghdr *nlh);
int (*ndo_change_carrier)(struct net_device *dev,
bool new_carrier);
};
Expand Down
11 changes: 11 additions & 0 deletions include/uapi/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,26 @@ struct __fdb_entry {
* [IFLA_AF_SPEC] = {
* [IFLA_BRIDGE_FLAGS]
* [IFLA_BRIDGE_MODE]
* [IFLA_BRIDGE_VLAN_INFO]
* }
*/
enum {
IFLA_BRIDGE_FLAGS,
IFLA_BRIDGE_MODE,
IFLA_BRIDGE_VLAN_INFO,
__IFLA_BRIDGE_MAX,
};
#define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1)

#define BRIDGE_VLAN_INFO_MASTER (1<<0) /* Operate on Bridge device as well */
#define BRIDGE_VLAN_INFO_PVID (1<<1) /* VLAN is PVID, ingress untagged */
#define BRIDGE_VLAN_INFO_UNTAGGED (1<<2) /* VLAN egresses untagged */

struct bridge_vlan_info {
u16 flags;
u16 vid;
};

/* Bridge multicast database attributes
* [MDBA_MDB] = {
* [MDBA_MDB_ENTRY] = {
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/neighbour.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum {
NDA_LLADDR,
NDA_CACHEINFO,
NDA_PROBES,
NDA_VLAN,
__NDA_MAX
};

Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/rtnetlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,7 @@ struct tcamsg {

/* New extended info filters for IFLA_EXT_MASK */
#define RTEXT_FILTER_VF (1 << 0)
#define RTEXT_FILTER_BRVLAN (1 << 1)

/* End of information exported to user level */

Expand Down
1 change: 1 addition & 0 deletions net/8021q/vlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
kfree_skb(skb);
return NULL;
}
EXPORT_SYMBOL(vlan_untag);


/*
Expand Down
14 changes: 14 additions & 0 deletions net/bridge/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,17 @@ config BRIDGE_IGMP_SNOOPING
Say N to exclude this support and reduce the binary size.

If unsure, say Y.

config BRIDGE_VLAN_FILTERING
bool "VLAN filtering"
depends on BRIDGE
depends on VLAN_8021Q
default n
---help---
If you say Y here, then the Ethernet bridge will be able selectively
receive and forward traffic based on VLAN information in the packet
any VLAN information configured on the bridge port or bridge device.

Say N to exclude this support and reduce the binary size.

If unsure, say Y.
2 changes: 2 additions & 0 deletions net/bridge/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o

bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o

bridge-$(CONFIG_BRIDGE_VLAN_FILTERING) += br_vlan.o

obj-$(CONFIG_BRIDGE_NF_EBTABLES) += netfilter/
7 changes: 6 additions & 1 deletion net/bridge/br_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
struct net_bridge_fdb_entry *dst;
struct net_bridge_mdb_entry *mdst;
struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats);
u16 vid = 0;

rcu_read_lock();
#ifdef CONFIG_BRIDGE_NETFILTER
Expand All @@ -45,6 +46,9 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
brstats->tx_bytes += skb->len;
u64_stats_update_end(&brstats->syncp);

if (!br_allowed_ingress(br, br_get_vlan_info(br), skb, &vid))
goto out;

BR_INPUT_SKB_CB(skb)->brdev = dev;

skb_reset_mac_header(skb);
Expand All @@ -67,7 +71,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
br_multicast_deliver(mdst, skb);
else
br_flood_deliver(br, skb);
} else if ((dst = __br_fdb_get(br, dest)) != NULL)
} else if ((dst = __br_fdb_get(br, dest, vid)) != NULL)
br_deliver(dst->dst, skb);
else
br_flood_deliver(br, skb);
Expand Down Expand Up @@ -313,6 +317,7 @@ static const struct net_device_ops br_netdev_ops = {
.ndo_fdb_dump = br_fdb_dump,
.ndo_bridge_getlink = br_getlink,
.ndo_bridge_setlink = br_setlink,
.ndo_bridge_dellink = br_dellink,
};

static void br_dev_free(struct net_device *dev)
Expand Down
Loading

0 comments on commit 93197b1

Please sign in to comment.