Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit f26b296

Browse files
Nikolay Aleksandrovdavem330
authored andcommitted
net: bridge: vlan: add new rtm message support
Add initial RTM_NEWVLAN support which can only create vlans, operating similar to the current br_afspec(). We will use it later to also change per-vlan options. Old-style (flag-based) vlan ranges are not allowed when using RTM messages, we will introduce vlan ranges later via a new nested attribute which would allow us to have all the information about a range encapsulated into a single nl attribute. Signed-off-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8dcea18 commit f26b296

File tree

3 files changed

+123
-6
lines changed

3 files changed

+123
-6
lines changed

net/bridge/br_netlink.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -561,12 +561,12 @@ static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p,
561561
return err;
562562
}
563563

564-
static int br_process_vlan_info(struct net_bridge *br,
565-
struct net_bridge_port *p, int cmd,
566-
struct bridge_vlan_info *vinfo_curr,
567-
struct bridge_vlan_info **vinfo_last,
568-
bool *changed,
569-
struct netlink_ext_ack *extack)
564+
int br_process_vlan_info(struct net_bridge *br,
565+
struct net_bridge_port *p, int cmd,
566+
struct bridge_vlan_info *vinfo_curr,
567+
struct bridge_vlan_info **vinfo_last,
568+
bool *changed,
569+
struct netlink_ext_ack *extack)
570570
{
571571
if (!br_vlan_valid_id(vinfo_curr->vid, extack))
572572
return -EINVAL;

net/bridge/br_private.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,6 +1237,12 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags,
12371237
int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags);
12381238
int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev,
12391239
u32 filter_mask, int nlflags);
1240+
int br_process_vlan_info(struct net_bridge *br,
1241+
struct net_bridge_port *p, int cmd,
1242+
struct bridge_vlan_info *vinfo_curr,
1243+
struct bridge_vlan_info **vinfo_last,
1244+
bool *changed,
1245+
struct netlink_ext_ack *extack);
12401246

12411247
#ifdef CONFIG_SYSFS
12421248
/* br_sysfs_if.c */

net/bridge/br_vlan.c

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1643,13 +1643,124 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb)
16431643
return err;
16441644
}
16451645

1646+
static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = {
1647+
[BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN,
1648+
.len = sizeof(struct bridge_vlan_info) },
1649+
};
1650+
1651+
static int br_vlan_rtm_process_one(struct net_device *dev,
1652+
const struct nlattr *attr,
1653+
int cmd, struct netlink_ext_ack *extack)
1654+
{
1655+
struct bridge_vlan_info *vinfo, *vinfo_last = NULL;
1656+
struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1];
1657+
struct net_bridge_vlan_group *vg;
1658+
struct net_bridge_port *p = NULL;
1659+
int err = 0, cmdmap = 0;
1660+
struct net_bridge *br;
1661+
bool changed = false;
1662+
1663+
if (netif_is_bridge_master(dev)) {
1664+
br = netdev_priv(dev);
1665+
vg = br_vlan_group(br);
1666+
} else {
1667+
p = br_port_get_rtnl(dev);
1668+
if (WARN_ON(!p))
1669+
return -ENODEV;
1670+
br = p->br;
1671+
vg = nbp_vlan_group(p);
1672+
}
1673+
1674+
if (WARN_ON(!vg))
1675+
return -ENODEV;
1676+
1677+
err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr,
1678+
br_vlan_db_policy, extack);
1679+
if (err)
1680+
return err;
1681+
1682+
if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) {
1683+
NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info");
1684+
return -EINVAL;
1685+
}
1686+
1687+
vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
1688+
if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN |
1689+
BRIDGE_VLAN_INFO_RANGE_END)) {
1690+
NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls");
1691+
return -EINVAL;
1692+
}
1693+
if (!br_vlan_valid_id(vinfo->vid, extack))
1694+
return -EINVAL;
1695+
1696+
switch (cmd) {
1697+
case RTM_NEWVLAN:
1698+
cmdmap = RTM_SETLINK;
1699+
break;
1700+
}
1701+
1702+
err = br_process_vlan_info(br, p, cmdmap, vinfo, &vinfo_last, &changed,
1703+
extack);
1704+
if (changed)
1705+
br_ifinfo_notify(cmdmap, br, p);
1706+
1707+
return err;
1708+
}
1709+
1710+
static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh,
1711+
struct netlink_ext_ack *extack)
1712+
{
1713+
struct net *net = sock_net(skb->sk);
1714+
struct br_vlan_msg *bvm;
1715+
struct net_device *dev;
1716+
struct nlattr *attr;
1717+
int err, vlans = 0;
1718+
int rem;
1719+
1720+
/* this should validate the header and check for remaining bytes */
1721+
err = nlmsg_parse(nlh, sizeof(*bvm), NULL, BRIDGE_VLANDB_MAX, NULL,
1722+
extack);
1723+
if (err < 0)
1724+
return err;
1725+
1726+
bvm = nlmsg_data(nlh);
1727+
dev = __dev_get_by_index(net, bvm->ifindex);
1728+
if (!dev)
1729+
return -ENODEV;
1730+
1731+
if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) {
1732+
NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port");
1733+
return -EINVAL;
1734+
}
1735+
1736+
nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) {
1737+
if (nla_type(attr) != BRIDGE_VLANDB_ENTRY)
1738+
continue;
1739+
1740+
vlans++;
1741+
err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type,
1742+
extack);
1743+
if (err)
1744+
break;
1745+
}
1746+
if (!vlans) {
1747+
NL_SET_ERR_MSG_MOD(extack, "No vlans found to process");
1748+
err = -EINVAL;
1749+
}
1750+
1751+
return err;
1752+
}
1753+
16461754
void br_vlan_rtnl_init(void)
16471755
{
16481756
rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL,
16491757
br_vlan_rtm_dump, 0);
1758+
rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN,
1759+
br_vlan_rtm_process, NULL, 0);
16501760
}
16511761

16521762
void br_vlan_rtnl_uninit(void)
16531763
{
16541764
rtnl_unregister(PF_BRIDGE, RTM_GETVLAN);
1765+
rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN);
16551766
}

0 commit comments

Comments
 (0)