Commit 8adff41c authored by Toshiaki Makita's avatar Toshiaki Makita Committed by David S. Miller

bridge: Don't use VID 0 and 4095 in vlan filtering

IEEE 802.1Q says that:
- VID 0 shall not be configured as a PVID, or configured in any Filtering
Database entry.
- VID 4095 shall not be configured as a PVID, or transmitted in a tag
header. This VID value may be used to indicate a wildcard match for the VID
in management operations or Filtering Database entries.
(See IEEE 802.1Q-2011 6.9.1 and Table 9-2)

Don't accept adding these VIDs in the vlan_filtering implementation.
Signed-off-by: default avatarToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Reviewed-by: default avatarVlad Yasevich <vyasevic@redhat.com>
Acked-by: default avatarStephen Hemminger <stephen@networkplumber.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4b6c7879
...@@ -700,7 +700,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], ...@@ -700,7 +700,7 @@ int br_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
vid = nla_get_u16(tb[NDA_VLAN]); vid = nla_get_u16(tb[NDA_VLAN]);
if (vid >= VLAN_N_VID) { if (!vid || vid >= VLAN_VID_MASK) {
pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
vid); vid);
return -EINVAL; return -EINVAL;
...@@ -794,7 +794,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], ...@@ -794,7 +794,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[],
vid = nla_get_u16(tb[NDA_VLAN]); vid = nla_get_u16(tb[NDA_VLAN]);
if (vid >= VLAN_N_VID) { if (!vid || vid >= VLAN_VID_MASK) {
pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n", pr_info("bridge: RTM_NEWNEIGH with invalid vlan id %d\n",
vid); vid);
return -EINVAL; return -EINVAL;
......
...@@ -243,7 +243,7 @@ static int br_afspec(struct net_bridge *br, ...@@ -243,7 +243,7 @@ static int br_afspec(struct net_bridge *br,
vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]); vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
if (vinfo->vid >= VLAN_N_VID) if (!vinfo->vid || vinfo->vid >= VLAN_VID_MASK)
return -EINVAL; return -EINVAL;
switch (cmd) { switch (cmd) {
......
...@@ -45,37 +45,34 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) ...@@ -45,37 +45,34 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags)
return 0; return 0;
} }
if (vid) { if (v->port_idx) {
if (v->port_idx) { p = v->parent.port;
p = v->parent.port; br = p->br;
br = p->br; dev = p->dev;
dev = p->dev; } else {
} else { br = v->parent.br;
br = v->parent.br; dev = br->dev;
dev = br->dev; }
} ops = dev->netdev_ops;
ops = dev->netdev_ops;
if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) {
if (p && (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { /* Add VLAN to the device filter if it is supported.
/* Add VLAN to the device filter if it is supported. * Stricly speaking, this is not necessary now, since
* Stricly speaking, this is not necessary now, since * devices are made promiscuous by the bridge, but if
* devices are made promiscuous by the bridge, but if * that ever changes this code will allow tagged
* that ever changes this code will allow tagged * traffic to enter the bridge.
* traffic to enter the bridge. */
*/ err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q),
err = ops->ndo_vlan_rx_add_vid(dev, htons(ETH_P_8021Q), vid);
vid); if (err)
if (err) return err;
return err; }
}
err = br_fdb_insert(br, p, dev->dev_addr, vid);
if (err) {
br_err(br, "failed insert local address into bridge "
"forwarding table\n");
goto out_filt;
}
err = br_fdb_insert(br, p, dev->dev_addr, vid);
if (err) {
br_err(br, "failed insert local address into bridge "
"forwarding table\n");
goto out_filt;
} }
set_bit(vid, v->vlan_bitmap); set_bit(vid, v->vlan_bitmap);
...@@ -98,7 +95,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid) ...@@ -98,7 +95,7 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid)
__vlan_delete_pvid(v, vid); __vlan_delete_pvid(v, vid);
clear_bit(vid, v->untagged_bitmap); clear_bit(vid, v->untagged_bitmap);
if (v->port_idx && vid) { if (v->port_idx) {
struct net_device *dev = v->parent.port->dev; struct net_device *dev = v->parent.port->dev;
const struct net_device_ops *ops = dev->netdev_ops; const struct net_device_ops *ops = dev->netdev_ops;
...@@ -248,7 +245,9 @@ bool br_allowed_egress(struct net_bridge *br, ...@@ -248,7 +245,9 @@ bool br_allowed_egress(struct net_bridge *br,
return false; return false;
} }
/* Must be protected by RTNL */ /* Must be protected by RTNL.
* Must be called with vid in range from 1 to 4094 inclusive.
*/
int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
{ {
struct net_port_vlans *pv = NULL; struct net_port_vlans *pv = NULL;
...@@ -278,7 +277,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags) ...@@ -278,7 +277,9 @@ int br_vlan_add(struct net_bridge *br, u16 vid, u16 flags)
return err; return err;
} }
/* Must be protected by RTNL */ /* Must be protected by RTNL.
* Must be called with vid in range from 1 to 4094 inclusive.
*/
int br_vlan_delete(struct net_bridge *br, u16 vid) int br_vlan_delete(struct net_bridge *br, u16 vid)
{ {
struct net_port_vlans *pv; struct net_port_vlans *pv;
...@@ -289,14 +290,9 @@ int br_vlan_delete(struct net_bridge *br, u16 vid) ...@@ -289,14 +290,9 @@ int br_vlan_delete(struct net_bridge *br, u16 vid)
if (!pv) if (!pv)
return -EINVAL; return -EINVAL;
if (vid) { spin_lock_bh(&br->hash_lock);
/* If the VID !=0 remove fdb for this vid. VID 0 is special fdb_delete_by_addr(br, br->dev->dev_addr, vid);
* in that it's the default and is always there in the fdb. spin_unlock_bh(&br->hash_lock);
*/
spin_lock_bh(&br->hash_lock);
fdb_delete_by_addr(br, br->dev->dev_addr, vid);
spin_unlock_bh(&br->hash_lock);
}
__vlan_del(pv, vid); __vlan_del(pv, vid);
return 0; return 0;
...@@ -329,7 +325,9 @@ int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val) ...@@ -329,7 +325,9 @@ int br_vlan_filter_toggle(struct net_bridge *br, unsigned long val)
return 0; return 0;
} }
/* Must be protected by RTNL */ /* Must be protected by RTNL.
* Must be called with vid in range from 1 to 4094 inclusive.
*/
int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
{ {
struct net_port_vlans *pv = NULL; struct net_port_vlans *pv = NULL;
...@@ -363,7 +361,9 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags) ...@@ -363,7 +361,9 @@ int nbp_vlan_add(struct net_bridge_port *port, u16 vid, u16 flags)
return err; return err;
} }
/* Must be protected by RTNL */ /* Must be protected by RTNL.
* Must be called with vid in range from 1 to 4094 inclusive.
*/
int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
{ {
struct net_port_vlans *pv; struct net_port_vlans *pv;
...@@ -374,14 +374,9 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid) ...@@ -374,14 +374,9 @@ int nbp_vlan_delete(struct net_bridge_port *port, u16 vid)
if (!pv) if (!pv)
return -EINVAL; return -EINVAL;
if (vid) { spin_lock_bh(&port->br->hash_lock);
/* If the VID !=0 remove fdb for this vid. VID 0 is special fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
* in that it's the default and is always there in the fdb. spin_unlock_bh(&port->br->hash_lock);
*/
spin_lock_bh(&port->br->hash_lock);
fdb_delete_by_addr(port->br, port->dev->dev_addr, vid);
spin_unlock_bh(&port->br->hash_lock);
}
return __vlan_del(pv, vid); return __vlan_del(pv, vid);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment