From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> To: netdev@vger.kernel.org Cc: roopa@cumulusnetworks.com, davem@davemloft.net, bridge@lists.linux-foundation.org, Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Subject: [PATCH net-next 4/8] net: bridge: vlan: add new rtm message support Date: Mon, 13 Jan 2020 17:52:29 +0200 [thread overview] Message-ID: <20200113155233.20771-5-nikolay@cumulusnetworks.com> (raw) In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> 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 <nikolay@cumulusnetworks.com> --- net/bridge/br_netlink.c | 12 ++--- net/bridge/br_private.h | 6 +++ net/bridge/br_vlan.c | 110 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 75a7ecf95d7f..b3da4f46dc64 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -561,12 +561,12 @@ static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p, return err; } -static int br_process_vlan_info(struct net_bridge *br, - struct net_bridge_port *p, int cmd, - struct bridge_vlan_info *vinfo_curr, - struct bridge_vlan_info **vinfo_last, - bool *changed, - struct netlink_ext_ack *extack) +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack) { if (!br_vlan_valid_id(vinfo_curr->vid, extack)) return -EINVAL; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1c00411ae938..ee3871dea68f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1237,6 +1237,12 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags, int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask, int nlflags); +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack); #ifdef CONFIG_SYSFS /* br_sysfs_if.c */ diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 0135a67f50a7..b8f52a7616c4 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1644,13 +1644,123 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) return err; } +static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { + [BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN, + .len = sizeof(struct bridge_vlan_info) }, +}; + +static int br_vlan_rtm_process_one(struct net_device *dev, + const struct nlattr *attr, + int cmd, struct netlink_ext_ack *extack) +{ + struct bridge_vlan_info *vinfo, *vinfo_last = NULL; + struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; + struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; + int err = 0, cmdmap = 0; + struct net_bridge *br; + bool changed = false; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + vg = br_vlan_group(br); + } else { + p = br_port_get_rtnl(dev); + if (WARN_ON(!p)) + return -ENODEV; + br = p->br; + vg = nbp_vlan_group(p); + } + + if (WARN_ON(!vg)) + return -ENODEV; + + err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr, + br_vlan_db_policy, extack); + if (err) + return err; + + if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) { + NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); + return -EINVAL; + } + + vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); + if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | + BRIDGE_VLAN_INFO_RANGE_END)) { + NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls"); + return -EINVAL; + } + if (!br_vlan_valid_id(vinfo->vid, extack)) + return -EINVAL; + + switch (cmd) { + case RTM_NEWVLAN: + cmdmap = RTM_SETLINK; + break; + } + + err = br_process_vlan_info(br, p, cmdmap, vinfo, &vinfo_last, &changed, + extack); + if (changed) + br_ifinfo_notify(cmdmap, br, p); + + return err; +} + +static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack) +{ + struct net *net = sock_net(skb->sk); + int err = -EINVAL, vlans = 0; + struct br_vlan_msg *bvm; + struct net_device *dev; + struct nlattr *attr; + int rem; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bvm))) { + NL_SET_ERR_MSG_MOD(extack, "Invalid header for vlan request"); + return -EINVAL; + } + + bvm = nlmsg_data(nlh); + dev = __dev_get_by_index(net, bvm->ifindex); + if (!dev) + return -ENODEV; + + if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) { + NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port"); + return -EINVAL; + } + + nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { + if (nla_type(attr) != BRIDGE_VLANDB_ENTRY) + continue; + + vlans++; + err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type, + extack); + if (err) + break; + } + if (!vlans) { + NL_SET_ERR_MSG_MOD(extack, "No vlans found to process"); + err = -EINVAL; + } + + return err; +} + void br_vlan_rtnl_init(void) { rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, br_vlan_rtm_dump, 0); + rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, + br_vlan_rtm_process, NULL, 0); } void br_vlan_rtnl_uninit(void) { rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); + rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); } -- 2.21.0
WARNING: multiple messages have this Message-ID (diff)
From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> To: netdev@vger.kernel.org Cc: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>, roopa@cumulusnetworks.com, bridge@lists.linux-foundation.org, davem@davemloft.net Subject: [Bridge] [PATCH net-next 4/8] net: bridge: vlan: add new rtm message support Date: Mon, 13 Jan 2020 17:52:29 +0200 [thread overview] Message-ID: <20200113155233.20771-5-nikolay@cumulusnetworks.com> (raw) In-Reply-To: <20200113155233.20771-1-nikolay@cumulusnetworks.com> 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 <nikolay@cumulusnetworks.com> --- net/bridge/br_netlink.c | 12 ++--- net/bridge/br_private.h | 6 +++ net/bridge/br_vlan.c | 110 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 122 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 75a7ecf95d7f..b3da4f46dc64 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -561,12 +561,12 @@ static int br_vlan_info(struct net_bridge *br, struct net_bridge_port *p, return err; } -static int br_process_vlan_info(struct net_bridge *br, - struct net_bridge_port *p, int cmd, - struct bridge_vlan_info *vinfo_curr, - struct bridge_vlan_info **vinfo_last, - bool *changed, - struct netlink_ext_ack *extack) +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack) { if (!br_vlan_valid_id(vinfo_curr->vid, extack)) return -EINVAL; diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1c00411ae938..ee3871dea68f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -1237,6 +1237,12 @@ int br_setlink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags, int br_dellink(struct net_device *dev, struct nlmsghdr *nlmsg, u16 flags); int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, struct net_device *dev, u32 filter_mask, int nlflags); +int br_process_vlan_info(struct net_bridge *br, + struct net_bridge_port *p, int cmd, + struct bridge_vlan_info *vinfo_curr, + struct bridge_vlan_info **vinfo_last, + bool *changed, + struct netlink_ext_ack *extack); #ifdef CONFIG_SYSFS /* br_sysfs_if.c */ diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 0135a67f50a7..b8f52a7616c4 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1644,13 +1644,123 @@ static int br_vlan_rtm_dump(struct sk_buff *skb, struct netlink_callback *cb) return err; } +static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = { + [BRIDGE_VLANDB_ENTRY_INFO] = { .type = NLA_EXACT_LEN, + .len = sizeof(struct bridge_vlan_info) }, +}; + +static int br_vlan_rtm_process_one(struct net_device *dev, + const struct nlattr *attr, + int cmd, struct netlink_ext_ack *extack) +{ + struct bridge_vlan_info *vinfo, *vinfo_last = NULL; + struct nlattr *tb[BRIDGE_VLANDB_ENTRY_MAX + 1]; + struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; + int err = 0, cmdmap = 0; + struct net_bridge *br; + bool changed = false; + + if (netif_is_bridge_master(dev)) { + br = netdev_priv(dev); + vg = br_vlan_group(br); + } else { + p = br_port_get_rtnl(dev); + if (WARN_ON(!p)) + return -ENODEV; + br = p->br; + vg = nbp_vlan_group(p); + } + + if (WARN_ON(!vg)) + return -ENODEV; + + err = nla_parse_nested(tb, BRIDGE_VLANDB_ENTRY_MAX, attr, + br_vlan_db_policy, extack); + if (err) + return err; + + if (!tb[BRIDGE_VLANDB_ENTRY_INFO]) { + NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry info"); + return -EINVAL; + } + + vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); + if (vinfo->flags & (BRIDGE_VLAN_INFO_RANGE_BEGIN | + BRIDGE_VLAN_INFO_RANGE_END)) { + NL_SET_ERR_MSG_MOD(extack, "Old-style vlan ranges are not allowed when using RTM vlan calls"); + return -EINVAL; + } + if (!br_vlan_valid_id(vinfo->vid, extack)) + return -EINVAL; + + switch (cmd) { + case RTM_NEWVLAN: + cmdmap = RTM_SETLINK; + break; + } + + err = br_process_vlan_info(br, p, cmdmap, vinfo, &vinfo_last, &changed, + extack); + if (changed) + br_ifinfo_notify(cmdmap, br, p); + + return err; +} + +static int br_vlan_rtm_process(struct sk_buff *skb, struct nlmsghdr *nlh, + struct netlink_ext_ack *extack) +{ + struct net *net = sock_net(skb->sk); + int err = -EINVAL, vlans = 0; + struct br_vlan_msg *bvm; + struct net_device *dev; + struct nlattr *attr; + int rem; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*bvm))) { + NL_SET_ERR_MSG_MOD(extack, "Invalid header for vlan request"); + return -EINVAL; + } + + bvm = nlmsg_data(nlh); + dev = __dev_get_by_index(net, bvm->ifindex); + if (!dev) + return -ENODEV; + + if (!netif_is_bridge_master(dev) && !netif_is_bridge_port(dev)) { + NL_SET_ERR_MSG_MOD(extack, "The device is not a valid bridge or bridge port"); + return -EINVAL; + } + + nlmsg_for_each_attr(attr, nlh, sizeof(*bvm), rem) { + if (nla_type(attr) != BRIDGE_VLANDB_ENTRY) + continue; + + vlans++; + err = br_vlan_rtm_process_one(dev, attr, nlh->nlmsg_type, + extack); + if (err) + break; + } + if (!vlans) { + NL_SET_ERR_MSG_MOD(extack, "No vlans found to process"); + err = -EINVAL; + } + + return err; +} + void br_vlan_rtnl_init(void) { rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_GETVLAN, NULL, br_vlan_rtm_dump, 0); + rtnl_register_module(THIS_MODULE, PF_BRIDGE, RTM_NEWVLAN, + br_vlan_rtm_process, NULL, 0); } void br_vlan_rtnl_uninit(void) { rtnl_unregister(PF_BRIDGE, RTM_GETVLAN); + rtnl_unregister(PF_BRIDGE, RTM_NEWVLAN); } -- 2.21.0
next prev parent reply other threads:[~2020-01-13 15:53 UTC|newest] Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-01-13 15:52 [PATCH net-next 0/8] net: bridge: add vlan notifications and rtm support Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 1/8] net: bridge: vlan: add helpers to check for vlan id/range validity Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 2/8] net: bridge: netlink: add extack error messages when processing vlans Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 3/8] net: bridge: vlan: add rtm definitions and dump support Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-14 13:55 ` Jakub Kicinski 2020-01-14 13:55 ` [Bridge] " Jakub Kicinski 2020-01-14 15:34 ` David Ahern 2020-01-14 15:34 ` [Bridge] " David Ahern 2020-01-14 16:36 ` Nikolay Aleksandrov 2020-01-14 16:36 ` [Bridge] " Nikolay Aleksandrov 2020-01-14 16:45 ` Nikolay Aleksandrov 2020-01-14 16:45 ` [Bridge] " Nikolay Aleksandrov 2020-01-14 16:49 ` David Ahern 2020-01-14 16:49 ` [Bridge] " David Ahern 2020-01-14 16:50 ` Nikolay Aleksandrov 2020-01-14 16:50 ` [Bridge] " Nikolay Aleksandrov 2020-01-14 16:53 ` David Ahern 2020-01-14 16:53 ` [Bridge] " David Ahern 2020-01-14 17:52 ` Nikolay Aleksandrov 2020-01-14 17:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` Nikolay Aleksandrov [this message] 2020-01-13 15:52 ` [Bridge] [PATCH net-next 4/8] net: bridge: vlan: add new rtm message support Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 5/8] net: bridge: vlan: add del " Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 6/8] net: bridge: vlan: add rtm range support Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 7/8] net: bridge: vlan: add rtnetlink group and notify support Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov 2020-01-13 15:52 ` [PATCH net-next 8/8] net: bridge: vlan: notify on vlan add/delete/change flags Nikolay Aleksandrov 2020-01-13 15:52 ` [Bridge] " Nikolay Aleksandrov
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200113155233.20771-5-nikolay@cumulusnetworks.com \ --to=nikolay@cumulusnetworks.com \ --cc=bridge@lists.linux-foundation.org \ --cc=davem@davemloft.net \ --cc=netdev@vger.kernel.org \ --cc=roopa@cumulusnetworks.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.