forked from Minki/linux
net: bridge: vlan: add rtnetlink group and notify support
Add a new rtnetlink group for bridge vlan notifications - RTNLGRP_BRVLAN and add support for sending vlan notifications (both single and ranges). No functional changes intended, the notification support will be used by later patches. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
0ab5587951
commit
cf5bddb95c
@ -730,6 +730,8 @@ enum rtnetlink_groups {
|
||||
#define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R
|
||||
RTNLGRP_NEXTHOP,
|
||||
#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP
|
||||
RTNLGRP_BRVLAN,
|
||||
#define RTNLGRP_BRVLAN RTNLGRP_BRVLAN
|
||||
__RTNLGRP_MAX
|
||||
};
|
||||
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
|
||||
|
@ -960,6 +960,10 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
|
||||
void *ptr);
|
||||
void br_vlan_rtnl_init(void);
|
||||
void br_vlan_rtnl_uninit(void);
|
||||
void br_vlan_notify(const struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
u16 vid, u16 vid_range,
|
||||
int cmd);
|
||||
|
||||
static inline struct net_bridge_vlan_group *br_vlan_group(
|
||||
const struct net_bridge *br)
|
||||
@ -1166,6 +1170,13 @@ static inline void br_vlan_rtnl_init(void)
|
||||
static inline void br_vlan_rtnl_uninit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void br_vlan_notify(const struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
u16 vid, u16 vid_range,
|
||||
int cmd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
struct nf_br_ops {
|
||||
|
@ -1540,6 +1540,85 @@ out_err:
|
||||
return false;
|
||||
}
|
||||
|
||||
static size_t rtnl_vlan_nlmsg_size(void)
|
||||
{
|
||||
return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
|
||||
+ nla_total_size(0) /* BRIDGE_VLANDB_ENTRY */
|
||||
+ nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_ENTRY_RANGE */
|
||||
+ nla_total_size(sizeof(struct bridge_vlan_info)); /* BRIDGE_VLANDB_ENTRY_INFO */
|
||||
}
|
||||
|
||||
void br_vlan_notify(const struct net_bridge *br,
|
||||
const struct net_bridge_port *p,
|
||||
u16 vid, u16 vid_range,
|
||||
int cmd)
|
||||
{
|
||||
struct net_bridge_vlan_group *vg;
|
||||
struct net_bridge_vlan *v;
|
||||
struct br_vlan_msg *bvm;
|
||||
struct nlmsghdr *nlh;
|
||||
struct sk_buff *skb;
|
||||
int err = -ENOBUFS;
|
||||
struct net *net;
|
||||
u16 flags = 0;
|
||||
int ifindex;
|
||||
|
||||
/* right now notifications are done only with rtnl held */
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (p) {
|
||||
ifindex = p->dev->ifindex;
|
||||
vg = nbp_vlan_group(p);
|
||||
net = dev_net(p->dev);
|
||||
} else {
|
||||
ifindex = br->dev->ifindex;
|
||||
vg = br_vlan_group(br);
|
||||
net = dev_net(br->dev);
|
||||
}
|
||||
|
||||
skb = nlmsg_new(rtnl_vlan_nlmsg_size(), GFP_KERNEL);
|
||||
if (!skb)
|
||||
goto out_err;
|
||||
|
||||
err = -EMSGSIZE;
|
||||
nlh = nlmsg_put(skb, 0, 0, cmd, sizeof(*bvm), 0);
|
||||
if (!nlh)
|
||||
goto out_err;
|
||||
bvm = nlmsg_data(nlh);
|
||||
memset(bvm, 0, sizeof(*bvm));
|
||||
bvm->family = AF_BRIDGE;
|
||||
bvm->ifindex = ifindex;
|
||||
|
||||
switch (cmd) {
|
||||
case RTM_NEWVLAN:
|
||||
/* need to find the vlan due to flags/options */
|
||||
v = br_vlan_find(vg, vid);
|
||||
if (!v || !br_vlan_should_use(v))
|
||||
goto out_kfree;
|
||||
|
||||
flags = v->flags;
|
||||
if (br_get_pvid(vg) == v->vid)
|
||||
flags |= BRIDGE_VLAN_INFO_PVID;
|
||||
break;
|
||||
case RTM_DELVLAN:
|
||||
break;
|
||||
default:
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
if (!br_vlan_fill_vids(skb, vid, vid_range, flags))
|
||||
goto out_err;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
rtnl_notify(skb, net, 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL);
|
||||
return;
|
||||
|
||||
out_err:
|
||||
rtnl_set_sk_err(net, RTNLGRP_BRVLAN, err);
|
||||
out_kfree:
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
/* check if v_curr can enter a range ending in range_end */
|
||||
static bool br_vlan_can_enter_range(const struct net_bridge_vlan *v_curr,
|
||||
const struct net_bridge_vlan *range_end)
|
||||
|
Loading…
Reference in New Issue
Block a user