Commit 77751ee8 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

bridge: vlan: move pvid inside net_bridge_vlan_group

One obvious way to converge more code (which was also used by the
previous vlan code) is to move pvid inside net_bridge_vlan_group. This
allows us to simplify some and remove other port-specific functions.
Also gives us the ability to simply pass the vlan group and use all of the
contained information.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 468e7944
...@@ -56,7 +56,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -56,7 +56,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
skb_reset_mac_header(skb); skb_reset_mac_header(skb);
skb_pull(skb, ETH_HLEN); skb_pull(skb, ETH_HLEN);
if (!br_allowed_ingress(br, skb, &vid)) if (!br_allowed_ingress(br, br_vlan_group(br), skb, &vid))
goto out; goto out;
if (is_broadcast_ether_addr(dest)) if (is_broadcast_ether_addr(dest))
......
...@@ -140,7 +140,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb ...@@ -140,7 +140,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
if (!p || p->state == BR_STATE_DISABLED) if (!p || p->state == BR_STATE_DISABLED)
goto drop; goto drop;
if (!nbp_allowed_ingress(p, skb, &vid)) if (!br_allowed_ingress(p->br, nbp_vlan_group(p), skb, &vid))
goto out; goto out;
/* insert into forwarding database after filtering to avoid spoofing */ /* insert into forwarding database after filtering to avoid spoofing */
......
...@@ -22,17 +22,17 @@ ...@@ -22,17 +22,17 @@
#include "br_private_stp.h" #include "br_private_stp.h"
static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg, static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
u32 filter_mask, u32 filter_mask)
u16 pvid)
{ {
struct net_bridge_vlan *v; struct net_bridge_vlan *v;
u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0; u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0;
u16 flags; u16 flags, pvid;
int num_vlans = 0; int num_vlans = 0;
if (!(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) if (!(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED))
return 0; return 0;
pvid = br_get_pvid(vg);
/* Count number of vlan infos */ /* Count number of vlan infos */
list_for_each_entry(v, &vg->vlan_list, vlist) { list_for_each_entry(v, &vg->vlan_list, vlist) {
flags = 0; flags = 0;
...@@ -74,7 +74,7 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg, ...@@ -74,7 +74,7 @@ static int __get_num_vlan_infos(struct net_bridge_vlan_group *vg,
} }
static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg, static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg,
u32 filter_mask, u16 pvid) u32 filter_mask)
{ {
if (!vg) if (!vg)
return 0; return 0;
...@@ -82,7 +82,7 @@ static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg, ...@@ -82,7 +82,7 @@ static int br_get_num_vlan_infos(struct net_bridge_vlan_group *vg,
if (filter_mask & RTEXT_FILTER_BRVLAN) if (filter_mask & RTEXT_FILTER_BRVLAN)
return vg->num_vlans; return vg->num_vlans;
return __get_num_vlan_infos(vg, filter_mask, pvid); return __get_num_vlan_infos(vg, filter_mask);
} }
static size_t br_get_link_af_size_filtered(const struct net_device *dev, static size_t br_get_link_af_size_filtered(const struct net_device *dev,
...@@ -92,19 +92,16 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev, ...@@ -92,19 +92,16 @@ static size_t br_get_link_af_size_filtered(const struct net_device *dev,
struct net_bridge_port *p; struct net_bridge_port *p;
struct net_bridge *br; struct net_bridge *br;
int num_vlan_infos; int num_vlan_infos;
u16 pvid = 0;
rcu_read_lock(); rcu_read_lock();
if (br_port_exists(dev)) { if (br_port_exists(dev)) {
p = br_port_get_rcu(dev); p = br_port_get_rcu(dev);
vg = nbp_vlan_group(p); vg = nbp_vlan_group(p);
pvid = nbp_get_pvid(p);
} else if (dev->priv_flags & IFF_EBRIDGE) { } else if (dev->priv_flags & IFF_EBRIDGE) {
br = netdev_priv(dev); br = netdev_priv(dev);
vg = br_vlan_group(br); vg = br_vlan_group(br);
pvid = br_get_pvid(br);
} }
num_vlan_infos = br_get_num_vlan_infos(vg, filter_mask, pvid); num_vlan_infos = br_get_num_vlan_infos(vg, filter_mask);
rcu_read_unlock(); rcu_read_unlock();
/* Each VLAN is returned in bridge_vlan_info along with flags */ /* Each VLAN is returned in bridge_vlan_info along with flags */
...@@ -196,18 +193,18 @@ static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start, ...@@ -196,18 +193,18 @@ static int br_fill_ifvlaninfo_range(struct sk_buff *skb, u16 vid_start,
} }
static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb, static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
struct net_bridge_vlan_group *vg, struct net_bridge_vlan_group *vg)
u16 pvid)
{ {
struct net_bridge_vlan *v; struct net_bridge_vlan *v;
u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0; u16 vid_range_start = 0, vid_range_end = 0, vid_range_flags = 0;
u16 flags; u16 flags, pvid;
int err = 0; int err = 0;
/* Pack IFLA_BRIDGE_VLAN_INFO's for every vlan /* Pack IFLA_BRIDGE_VLAN_INFO's for every vlan
* and mark vlan info with begin and end flags * and mark vlan info with begin and end flags
* if vlaninfo represents a range * if vlaninfo represents a range
*/ */
pvid = br_get_pvid(vg);
list_for_each_entry(v, &vg->vlan_list, vlist) { list_for_each_entry(v, &vg->vlan_list, vlist) {
flags = 0; flags = 0;
if (!br_vlan_should_use(v)) if (!br_vlan_should_use(v))
...@@ -251,12 +248,13 @@ static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb, ...@@ -251,12 +248,13 @@ static int br_fill_ifvlaninfo_compressed(struct sk_buff *skb,
} }
static int br_fill_ifvlaninfo(struct sk_buff *skb, static int br_fill_ifvlaninfo(struct sk_buff *skb,
struct net_bridge_vlan_group *vg, struct net_bridge_vlan_group *vg)
u16 pvid)
{ {
struct bridge_vlan_info vinfo; struct bridge_vlan_info vinfo;
struct net_bridge_vlan *v; struct net_bridge_vlan *v;
u16 pvid;
pvid = br_get_pvid(vg);
list_for_each_entry(v, &vg->vlan_list, vlist) { list_for_each_entry(v, &vg->vlan_list, vlist) {
if (!br_vlan_should_use(v)) if (!br_vlan_should_use(v))
continue; continue;
...@@ -338,16 +336,12 @@ static int br_fill_ifinfo(struct sk_buff *skb, ...@@ -338,16 +336,12 @@ static int br_fill_ifinfo(struct sk_buff *skb,
(filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) { (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)) {
struct net_bridge_vlan_group *vg; struct net_bridge_vlan_group *vg;
struct nlattr *af; struct nlattr *af;
u16 pvid;
int err; int err;
if (port) { if (port)
vg = nbp_vlan_group(port); vg = nbp_vlan_group(port);
pvid = nbp_get_pvid(port); else
} else {
vg = br_vlan_group(br); vg = br_vlan_group(br);
pvid = br_get_pvid(br);
}
if (!vg || !vg->num_vlans) if (!vg || !vg->num_vlans)
goto done; goto done;
...@@ -357,9 +351,9 @@ static int br_fill_ifinfo(struct sk_buff *skb, ...@@ -357,9 +351,9 @@ static int br_fill_ifinfo(struct sk_buff *skb,
goto nla_put_failure; goto nla_put_failure;
if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED) if (filter_mask & RTEXT_FILTER_BRVLAN_COMPRESSED)
err = br_fill_ifvlaninfo_compressed(skb, vg, pvid); err = br_fill_ifvlaninfo_compressed(skb, vg);
else else
err = br_fill_ifvlaninfo(skb, vg, pvid); err = br_fill_ifvlaninfo(skb, vg);
if (err) if (err)
goto nla_put_failure; goto nla_put_failure;
nla_nest_end(skb, af); nla_nest_end(skb, af);
...@@ -884,11 +878,11 @@ static size_t br_get_link_af_size(const struct net_device *dev) ...@@ -884,11 +878,11 @@ static size_t br_get_link_af_size(const struct net_device *dev)
if (br_port_exists(dev)) { if (br_port_exists(dev)) {
p = br_port_get_rtnl(dev); p = br_port_get_rtnl(dev);
num_vlans = br_get_num_vlan_infos(nbp_vlan_group(p), num_vlans = br_get_num_vlan_infos(nbp_vlan_group(p),
RTEXT_FILTER_BRVLAN, 0); RTEXT_FILTER_BRVLAN);
} else if (dev->priv_flags & IFF_EBRIDGE) { } else if (dev->priv_flags & IFF_EBRIDGE) {
br = netdev_priv(dev); br = netdev_priv(dev);
num_vlans = br_get_num_vlan_infos(br_vlan_group(br), num_vlans = br_get_num_vlan_infos(br_vlan_group(br),
RTEXT_FILTER_BRVLAN, 0); RTEXT_FILTER_BRVLAN);
} }
/* Each VLAN is returned in bridge_vlan_info along with flags */ /* Each VLAN is returned in bridge_vlan_info along with flags */
......
...@@ -119,6 +119,7 @@ struct net_bridge_vlan { ...@@ -119,6 +119,7 @@ struct net_bridge_vlan {
* @vlan_hash: VLAN entry rhashtable * @vlan_hash: VLAN entry rhashtable
* @vlan_list: sorted VLAN entry list * @vlan_list: sorted VLAN entry list
* @num_vlans: number of total VLAN entries * @num_vlans: number of total VLAN entries
* @pvid: PVID VLAN id
* *
* IMPORTANT: Be careful when checking if there're VLAN entries using list * IMPORTANT: Be careful when checking if there're VLAN entries using list
* primitives because the bridge can have entries in its list which * primitives because the bridge can have entries in its list which
...@@ -130,6 +131,7 @@ struct net_bridge_vlan_group { ...@@ -130,6 +131,7 @@ struct net_bridge_vlan_group {
struct rhashtable vlan_hash; struct rhashtable vlan_hash;
struct list_head vlan_list; struct list_head vlan_list;
u16 num_vlans; u16 num_vlans;
u16 pvid;
}; };
struct net_bridge_fdb_entry struct net_bridge_fdb_entry
...@@ -228,7 +230,6 @@ struct net_bridge_port ...@@ -228,7 +230,6 @@ struct net_bridge_port
#endif #endif
#ifdef CONFIG_BRIDGE_VLAN_FILTERING #ifdef CONFIG_BRIDGE_VLAN_FILTERING
struct net_bridge_vlan_group *vlgrp; struct net_bridge_vlan_group *vlgrp;
u16 pvid;
#endif #endif
}; };
...@@ -340,7 +341,6 @@ struct net_bridge ...@@ -340,7 +341,6 @@ struct net_bridge
u8 vlan_enabled; u8 vlan_enabled;
__be16 vlan_proto; __be16 vlan_proto;
u16 default_pvid; u16 default_pvid;
u16 pvid;
#endif #endif
}; };
...@@ -670,10 +670,10 @@ static inline void br_mdb_uninit(void) ...@@ -670,10 +670,10 @@ static inline void br_mdb_uninit(void)
/* br_vlan.c */ /* br_vlan.c */
#ifdef CONFIG_BRIDGE_VLAN_FILTERING #ifdef CONFIG_BRIDGE_VLAN_FILTERING
bool br_allowed_ingress(struct net_bridge *br, struct sk_buff *skb, u16 *vid); bool br_allowed_ingress(const struct net_bridge *br,
bool nbp_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb, struct net_bridge_vlan_group *vg, struct sk_buff *skb,
u16 *vid); u16 *vid);
bool br_allowed_egress(struct net_bridge_vlan_group *br, bool br_allowed_egress(struct net_bridge_vlan_group *vg,
const struct sk_buff *skb); const struct sk_buff *skb);
bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid); bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid);
struct sk_buff *br_handle_vlan(struct net_bridge *br, struct sk_buff *br_handle_vlan(struct net_bridge *br,
...@@ -725,22 +725,13 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid) ...@@ -725,22 +725,13 @@ static inline int br_vlan_get_tag(const struct sk_buff *skb, u16 *vid)
return err; return err;
} }
static inline u16 br_get_pvid(const struct net_bridge *br) static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
{
if (!br)
return 0;
smp_rmb();
return br->pvid;
}
static inline u16 nbp_get_pvid(const struct net_bridge_port *p)
{ {
if (!p) if (!vg)
return 0; return 0;
smp_rmb(); smp_rmb();
return p->pvid; return vg->pvid;
} }
static inline int br_vlan_enabled(struct net_bridge *br) static inline int br_vlan_enabled(struct net_bridge *br)
...@@ -748,14 +739,8 @@ static inline int br_vlan_enabled(struct net_bridge *br) ...@@ -748,14 +739,8 @@ static inline int br_vlan_enabled(struct net_bridge *br)
return br->vlan_enabled; return br->vlan_enabled;
} }
#else #else
static inline bool br_allowed_ingress(struct net_bridge *br, static inline bool br_allowed_ingress(const struct net_bridge *br,
struct sk_buff *skb, struct net_bridge_vlan_group *vg,
u16 *vid)
{
return true;
}
static inline bool nbp_allowed_ingress(struct net_bridge_port *p,
struct sk_buff *skb, struct sk_buff *skb,
u16 *vid) u16 *vid)
{ {
...@@ -834,12 +819,7 @@ static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag) ...@@ -834,12 +819,7 @@ static inline u16 br_vlan_get_tag(const struct sk_buff *skb, u16 *tag)
return 0; return 0;
} }
static inline u16 br_get_pvid(const struct net_bridge *br) static inline u16 br_get_pvid(const struct net_bridge_vlan_group *vg)
{
return 0;
}
static inline u16 nbp_get_pvid(const struct net_bridge_port *p)
{ {
return 0; return 0;
} }
......
...@@ -31,37 +31,37 @@ static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid) ...@@ -31,37 +31,37 @@ static struct net_bridge_vlan *br_vlan_lookup(struct rhashtable *tbl, u16 vid)
return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params); return rhashtable_lookup_fast(tbl, &vid, br_vlan_rht_params);
} }
static void __vlan_add_pvid(u16 *pvid, u16 vid) static void __vlan_add_pvid(struct net_bridge_vlan_group *vg, u16 vid)
{ {
if (*pvid == vid) if (vg->pvid == vid)
return; return;
smp_wmb(); smp_wmb();
*pvid = vid; vg->pvid = vid;
} }
static void __vlan_delete_pvid(u16 *pvid, u16 vid) static void __vlan_delete_pvid(struct net_bridge_vlan_group *vg, u16 vid)
{ {
if (*pvid != vid) if (vg->pvid != vid)
return; return;
smp_wmb(); smp_wmb();
*pvid = 0; vg->pvid = 0;
} }
static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags) static void __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
{ {
if (flags & BRIDGE_VLAN_INFO_PVID) { struct net_bridge_vlan_group *vg;
if (br_vlan_is_master(v)) if (br_vlan_is_master(v))
__vlan_add_pvid(&v->br->pvid, v->vid); vg = v->br->vlgrp;
else else
__vlan_add_pvid(&v->port->pvid, v->vid); vg = v->port->vlgrp;
} else {
if (br_vlan_is_master(v)) if (flags & BRIDGE_VLAN_INFO_PVID)
__vlan_delete_pvid(&v->br->pvid, v->vid); __vlan_add_pvid(vg, v->vid);
else else
__vlan_delete_pvid(&v->port->pvid, v->vid); __vlan_delete_pvid(vg, v->vid);
}
if (flags & BRIDGE_VLAN_INFO_UNTAGGED) if (flags & BRIDGE_VLAN_INFO_UNTAGGED)
v->flags |= BRIDGE_VLAN_INFO_UNTAGGED; v->flags |= BRIDGE_VLAN_INFO_UNTAGGED;
...@@ -249,25 +249,22 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags) ...@@ -249,25 +249,22 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags)
static int __vlan_del(struct net_bridge_vlan *v) static int __vlan_del(struct net_bridge_vlan *v)
{ {
struct net_bridge_vlan *masterv = v; struct net_bridge_vlan *masterv = v;
struct net_bridge_vlan_group *vg;
struct net_bridge_port *p = NULL; struct net_bridge_port *p = NULL;
struct net_bridge *br; struct net_bridge *br;
int err = 0; int err = 0;
struct rhashtable *tbl;
u16 *pvid;
if (br_vlan_is_master(v)) { if (br_vlan_is_master(v)) {
br = v->br; br = v->br;
tbl = &v->br->vlgrp->vlan_hash; vg = v->br->vlgrp;
pvid = &v->br->pvid;
} else { } else {
p = v->port; p = v->port;
br = p->br; br = p->br;
tbl = &p->vlgrp->vlan_hash; vg = v->port->vlgrp;
masterv = v->brvlan; masterv = v->brvlan;
pvid = &p->pvid;
} }
__vlan_delete_pvid(pvid, v->vid); __vlan_delete_pvid(vg, v->vid);
if (p) { if (p) {
err = __vlan_vid_del(p->dev, p->br, v->vid); err = __vlan_vid_del(p->dev, p->br, v->vid);
if (err) if (err)
...@@ -284,7 +281,8 @@ static int __vlan_del(struct net_bridge_vlan *v) ...@@ -284,7 +281,8 @@ static int __vlan_del(struct net_bridge_vlan *v)
} }
if (masterv != v) { if (masterv != v) {
rhashtable_remove_fast(tbl, &v->vnode, br_vlan_rht_params); rhashtable_remove_fast(&vg->vlan_hash, &v->vnode,
br_vlan_rht_params);
__vlan_del_list(v); __vlan_del_list(v);
kfree_rcu(v, rcu); kfree_rcu(v, rcu);
} }
...@@ -299,11 +297,11 @@ static int __vlan_del(struct net_bridge_vlan *v) ...@@ -299,11 +297,11 @@ static int __vlan_del(struct net_bridge_vlan *v)
return err; return err;
} }
static void __vlan_flush(struct net_bridge_vlan_group *vlgrp, u16 *pvid) static void __vlan_flush(struct net_bridge_vlan_group *vlgrp)
{ {
struct net_bridge_vlan *vlan, *tmp; struct net_bridge_vlan *vlan, *tmp;
__vlan_delete_pvid(pvid, *pvid); __vlan_delete_pvid(vlgrp, vlgrp->pvid);
list_for_each_entry_safe(vlan, tmp, &vlgrp->vlan_list, vlist) list_for_each_entry_safe(vlan, tmp, &vlgrp->vlan_list, vlist)
__vlan_del(vlan); __vlan_del(vlan);
rhashtable_destroy(&vlgrp->vlan_hash); rhashtable_destroy(&vlgrp->vlan_hash);
...@@ -348,7 +346,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, ...@@ -348,7 +346,7 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br,
} }
/* Called under RCU */ /* Called under RCU */
static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto, static bool __allowed_ingress(struct net_bridge_vlan_group *vg, __be16 proto,
struct sk_buff *skb, u16 *vid) struct sk_buff *skb, u16 *vid)
{ {
const struct net_bridge_vlan *v; const struct net_bridge_vlan *v;
...@@ -389,6 +387,8 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto, ...@@ -389,6 +387,8 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto,
} }
if (!*vid) { if (!*vid) {
u16 pvid = br_get_pvid(vg);
/* Frame had a tag with VID 0 or did not have a tag. /* Frame had a tag with VID 0 or did not have a tag.
* See if pvid is set on this port. That tells us which * See if pvid is set on this port. That tells us which
* vlan untagged or priority-tagged traffic belongs to. * vlan untagged or priority-tagged traffic belongs to.
...@@ -415,7 +415,7 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto, ...@@ -415,7 +415,7 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto,
} }
/* Frame had a valid vlan tag. See if vlan is allowed */ /* Frame had a valid vlan tag. See if vlan is allowed */
v = br_vlan_lookup(tbl, *vid); v = br_vlan_find(vg, *vid);
if (v && br_vlan_should_use(v)) if (v && br_vlan_should_use(v))
return true; return true;
drop: drop:
...@@ -423,25 +423,10 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto, ...@@ -423,25 +423,10 @@ static bool __allowed_ingress(struct rhashtable *tbl, u16 pvid, __be16 proto,
return false; return false;
} }
bool br_allowed_ingress(struct net_bridge *br, struct sk_buff *skb, u16 *vid) bool br_allowed_ingress(const struct net_bridge *br,
{ struct net_bridge_vlan_group *vg, struct sk_buff *skb,
/* If VLAN filtering is disabled on the bridge, all packets are
* permitted.
*/
if (!br->vlan_enabled) {
BR_INPUT_SKB_CB(skb)->vlan_filtered = false;
return true;
}
return __allowed_ingress(&br->vlgrp->vlan_hash, br->pvid,
br->vlan_proto, skb, vid);
}
bool nbp_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb,
u16 *vid) u16 *vid)
{ {
struct net_bridge *br = p->br;
/* If VLAN filtering is disabled on the bridge, all packets are /* If VLAN filtering is disabled on the bridge, all packets are
* permitted. * permitted.
*/ */
...@@ -450,8 +435,7 @@ bool nbp_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb, ...@@ -450,8 +435,7 @@ bool nbp_allowed_ingress(struct net_bridge_port *p, struct sk_buff *skb,
return true; return true;
} }
return __allowed_ingress(&p->vlgrp->vlan_hash, p->pvid, br->vlan_proto, return __allowed_ingress(vg, br->vlan_proto, skb, vid);
skb, vid);
} }
/* Called under RCU. */ /* Called under RCU. */
...@@ -491,14 +475,14 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) ...@@ -491,14 +475,14 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid)
*vid = 0; *vid = 0;
if (!*vid) { if (!*vid) {
*vid = nbp_get_pvid(p); *vid = br_get_pvid(vg);
if (!*vid) if (!*vid)
return false; return false;
return true; return true;
} }
if (br_vlan_find(p->vlgrp, *vid)) if (br_vlan_find(vg, *vid))
return true; return true;
return false; return false;
...@@ -574,7 +558,7 @@ void br_vlan_flush(struct net_bridge *br) ...@@ -574,7 +558,7 @@ void br_vlan_flush(struct net_bridge *br)
{ {
ASSERT_RTNL(); ASSERT_RTNL();
__vlan_flush(br_vlan_group(br), &br->pvid); __vlan_flush(br_vlan_group(br));
} }
struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid) struct net_bridge_vlan *br_vlan_find(struct net_bridge_vlan_group *vg, u16 vid)
...@@ -695,12 +679,11 @@ int br_vlan_set_proto(struct net_bridge *br, unsigned long val) ...@@ -695,12 +679,11 @@ int br_vlan_set_proto(struct net_bridge *br, unsigned long val)
return err; return err;
} }
static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 pvid, static bool vlan_default_pvid(struct net_bridge_vlan_group *vg, u16 vid)
u16 vid)
{ {
struct net_bridge_vlan *v; struct net_bridge_vlan *v;
if (vid != pvid) if (vid != vg->pvid)
return false; return false;
v = br_vlan_lookup(&vg->vlan_hash, vid); v = br_vlan_lookup(&vg->vlan_hash, vid);
...@@ -719,11 +702,11 @@ static void br_vlan_disable_default_pvid(struct net_bridge *br) ...@@ -719,11 +702,11 @@ static void br_vlan_disable_default_pvid(struct net_bridge *br)
/* Disable default_pvid on all ports where it is still /* Disable default_pvid on all ports where it is still
* configured. * configured.
*/ */
if (vlan_default_pvid(br->vlgrp, br->pvid, pvid)) if (vlan_default_pvid(br->vlgrp, pvid))
br_vlan_delete(br, pvid); br_vlan_delete(br, pvid);
list_for_each_entry(p, &br->port_list, list) { list_for_each_entry(p, &br->port_list, list) {
if (vlan_default_pvid(p->vlgrp, p->pvid, pvid)) if (vlan_default_pvid(p->vlgrp, pvid))
nbp_vlan_delete(p, pvid); nbp_vlan_delete(p, pvid);
} }
...@@ -749,7 +732,7 @@ static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid) ...@@ -749,7 +732,7 @@ static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
* user configuration. * user configuration.
*/ */
pvent = br_vlan_find(br->vlgrp, pvid); pvent = br_vlan_find(br->vlgrp, pvid);
if ((!old_pvid || vlan_default_pvid(br->vlgrp, br->pvid, old_pvid)) && if ((!old_pvid || vlan_default_pvid(br->vlgrp, old_pvid)) &&
(!pvent || !br_vlan_should_use(pvent))) { (!pvent || !br_vlan_should_use(pvent))) {
err = br_vlan_add(br, pvid, err = br_vlan_add(br, pvid,
BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_PVID |
...@@ -766,7 +749,7 @@ static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid) ...@@ -766,7 +749,7 @@ static int __br_vlan_set_default_pvid(struct net_bridge *br, u16 pvid)
* user configuration. * user configuration.
*/ */
if ((old_pvid && if ((old_pvid &&
!vlan_default_pvid(p->vlgrp, p->pvid, old_pvid)) || !vlan_default_pvid(p->vlgrp, old_pvid)) ||
br_vlan_find(p->vlgrp, pvid)) br_vlan_find(p->vlgrp, pvid))
continue; continue;
...@@ -955,5 +938,5 @@ void nbp_vlan_flush(struct net_bridge_port *port) ...@@ -955,5 +938,5 @@ void nbp_vlan_flush(struct net_bridge_port *port)
list_for_each_entry(vlan, &port->vlgrp->vlan_list, vlist) list_for_each_entry(vlan, &port->vlgrp->vlan_list, vlist)
vlan_vid_del(port->dev, port->br->vlan_proto, vlan->vid); vlan_vid_del(port->dev, port->br->vlan_proto, vlan->vid);
__vlan_flush(nbp_vlan_group(port), &port->pvid); __vlan_flush(nbp_vlan_group(port));
} }
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