diff options
author | Nikolay Aleksandrov <nikolay@cumulusnetworks.com> | 2020-03-20 13:23:02 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-03-20 08:52:20 -0700 |
commit | fa388f29a9211352d41ce341caa8cf18761e21c9 (patch) | |
tree | 4f0dc829184efe454ee0c7a83865f3735e1809b2 /net/bridge | |
parent | ee9d0cb6c4f42f50cdc7513fd4b8534f80fcf327 (diff) | |
download | linux-fa388f29a9211352d41ce341caa8cf18761e21c9.tar.bz2 |
net: bridge: vlan options: nest the tunnel id into a tunnel info attribute
While discussing the new API, Roopa mentioned that we'll be adding more
tunnel attributes and options in the future, so it's better to make it a
nested attribute, since this is still in net-next we can easily change it
and nest the tunnel id attribute under BRIDGE_VLANDB_ENTRY_TUNNEL_INFO.
The new format is:
[BRIDGE_VLANDB_ENTRY]
[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]
[BRIDGE_VLANDB_TINFO_ID]
Any new tunnel attributes can be nested under
BRIDGE_VLANDB_ENTRY_TUNNEL_INFO.
Suggested-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_vlan.c | 2 | ||||
-rw-r--r-- | net/bridge/br_vlan_options.c | 37 |
2 files changed, 32 insertions, 7 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 4398f3796665..f9092c71225f 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -1888,7 +1888,7 @@ static const struct nla_policy br_vlan_db_policy[BRIDGE_VLANDB_ENTRY_MAX + 1] = .len = sizeof(struct bridge_vlan_info) }, [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, [BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 }, - [BRIDGE_VLANDB_ENTRY_TUNNEL_ID] = { .type = NLA_U32 }, + [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED }, }; static int br_vlan_rtm_process_one(struct net_device *dev, diff --git a/net/bridge/br_vlan_options.c b/net/bridge/br_vlan_options.c index 138e180cf4d8..b39427f75457 100644 --- a/net/bridge/br_vlan_options.c +++ b/net/bridge/br_vlan_options.c @@ -12,12 +12,21 @@ static bool __vlan_tun_put(struct sk_buff *skb, const struct net_bridge_vlan *v) { __be32 tid = tunnel_id_to_key32(v->tinfo.tunnel_id); + struct nlattr *nest; if (!v->tinfo.tunnel_dst) return true; - return !nla_put_u32(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_ID, - be32_to_cpu(tid)); + nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_INFO); + if (!nest) + return false; + if (nla_put_u32(skb, BRIDGE_VLANDB_TINFO_ID, be32_to_cpu(tid))) { + nla_nest_cancel(skb, nest); + return false; + } + nla_nest_end(skb, nest); + + return true; } static bool __vlan_tun_can_enter_range(const struct net_bridge_vlan *v_curr, @@ -45,7 +54,8 @@ bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v) size_t br_vlan_opts_nl_size(void) { return nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_STATE */ - + nla_total_size(sizeof(u32)); /* BRIDGE_VLANDB_ENTRY_TUNNEL_ID */ + + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY_TUNNEL_INFO */ + + nla_total_size(sizeof(u32)); /* BRIDGE_VLANDB_TINFO_ID */ } static int br_vlan_modify_state(struct net_bridge_vlan_group *vg, @@ -85,14 +95,19 @@ static int br_vlan_modify_state(struct net_bridge_vlan_group *vg, return 0; } +static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = { + [BRIDGE_VLANDB_TINFO_ID] = { .type = NLA_U32 }, +}; + static int br_vlan_modify_tunnel(const struct net_bridge_port *p, struct net_bridge_vlan *v, struct nlattr **tb, bool *changed, struct netlink_ext_ack *extack) { + struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr; struct bridge_vlan_info *vinfo; - int cmdmap; + int cmdmap, err; u32 tun_id; if (!p) { @@ -104,12 +119,22 @@ static int br_vlan_modify_tunnel(const struct net_bridge_port *p, return -EINVAL; } + attr = tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]; + err = nla_parse_nested(tun_tb, BRIDGE_VLANDB_TINFO_MAX, attr, + br_vlandb_tinfo_pol, extack); + if (err) + return err; + + if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) { + NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute"); + return -ENOENT; + } /* vlan info attribute is guaranteed by br_vlan_rtm_process_one */ vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); cmdmap = vinfo->flags & BRIDGE_VLAN_INFO_REMOVE_TUN ? RTM_DELLINK : RTM_SETLINK; /* when working on vlan ranges this represents the starting tunnel id */ - tun_id = nla_get_u32(tb[BRIDGE_VLANDB_ENTRY_TUNNEL_ID]); + tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]); /* tunnel ids are mapped to each vlan in increasing order, * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the * current vlan, so we compute: tun_id + v - vinfo->vid @@ -137,7 +162,7 @@ static int br_vlan_process_one_opts(const struct net_bridge *br, if (err) return err; } - if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_ID]) { + if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) { err = br_vlan_modify_tunnel(p, v, tb, changed, extack); if (err) return err; |