Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Nikolay Aleksandrov and committed by
David S. Miller
fa388f29 ee9d0cb6

+47 -8
+15 -1
include/uapi/linux/if_bridge.h
··· 203 203 BRIDGE_VLANDB_ENTRY_INFO, 204 204 BRIDGE_VLANDB_ENTRY_RANGE, 205 205 BRIDGE_VLANDB_ENTRY_STATE, 206 - BRIDGE_VLANDB_ENTRY_TUNNEL_ID, 206 + BRIDGE_VLANDB_ENTRY_TUNNEL_INFO, 207 207 BRIDGE_VLANDB_ENTRY_STATS, 208 208 __BRIDGE_VLANDB_ENTRY_MAX, 209 209 }; 210 210 #define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1) 211 + 212 + /* [BRIDGE_VLANDB_ENTRY] = { 213 + * [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { 214 + * [BRIDGE_VLANDB_TINFO_ID] 215 + * ... 216 + * } 217 + * } 218 + */ 219 + enum { 220 + BRIDGE_VLANDB_TINFO_UNSPEC, 221 + BRIDGE_VLANDB_TINFO_ID, 222 + __BRIDGE_VLANDB_TINFO_MAX, 223 + }; 224 + #define BRIDGE_VLANDB_TINFO_MAX (__BRIDGE_VLANDB_TINFO_MAX - 1) 211 225 212 226 /* [BRIDGE_VLANDB_ENTRY] = { 213 227 * [BRIDGE_VLANDB_ENTRY_STATS] = {
+1 -1
net/bridge/br_vlan.c
··· 1888 1888 .len = sizeof(struct bridge_vlan_info) }, 1889 1889 [BRIDGE_VLANDB_ENTRY_RANGE] = { .type = NLA_U16 }, 1890 1890 [BRIDGE_VLANDB_ENTRY_STATE] = { .type = NLA_U8 }, 1891 - [BRIDGE_VLANDB_ENTRY_TUNNEL_ID] = { .type = NLA_U32 }, 1891 + [BRIDGE_VLANDB_ENTRY_TUNNEL_INFO] = { .type = NLA_NESTED }, 1892 1892 }; 1893 1893 1894 1894 static int br_vlan_rtm_process_one(struct net_device *dev,
+31 -6
net/bridge/br_vlan_options.c
··· 12 12 static bool __vlan_tun_put(struct sk_buff *skb, const struct net_bridge_vlan *v) 13 13 { 14 14 __be32 tid = tunnel_id_to_key32(v->tinfo.tunnel_id); 15 + struct nlattr *nest; 15 16 16 17 if (!v->tinfo.tunnel_dst) 17 18 return true; 18 19 19 - return !nla_put_u32(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_ID, 20 - be32_to_cpu(tid)); 20 + nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_INFO); 21 + if (!nest) 22 + return false; 23 + if (nla_put_u32(skb, BRIDGE_VLANDB_TINFO_ID, be32_to_cpu(tid))) { 24 + nla_nest_cancel(skb, nest); 25 + return false; 26 + } 27 + nla_nest_end(skb, nest); 28 + 29 + return true; 21 30 } 22 31 23 32 static bool __vlan_tun_can_enter_range(const struct net_bridge_vlan *v_curr, ··· 54 45 size_t br_vlan_opts_nl_size(void) 55 46 { 56 47 return nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_STATE */ 57 - + nla_total_size(sizeof(u32)); /* BRIDGE_VLANDB_ENTRY_TUNNEL_ID */ 48 + + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY_TUNNEL_INFO */ 49 + + nla_total_size(sizeof(u32)); /* BRIDGE_VLANDB_TINFO_ID */ 58 50 } 59 51 60 52 static int br_vlan_modify_state(struct net_bridge_vlan_group *vg, ··· 95 85 return 0; 96 86 } 97 87 88 + static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = { 89 + [BRIDGE_VLANDB_TINFO_ID] = { .type = NLA_U32 }, 90 + }; 91 + 98 92 static int br_vlan_modify_tunnel(const struct net_bridge_port *p, 99 93 struct net_bridge_vlan *v, 100 94 struct nlattr **tb, 101 95 bool *changed, 102 96 struct netlink_ext_ack *extack) 103 97 { 98 + struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr; 104 99 struct bridge_vlan_info *vinfo; 105 - int cmdmap; 100 + int cmdmap, err; 106 101 u32 tun_id; 107 102 108 103 if (!p) { ··· 119 104 return -EINVAL; 120 105 } 121 106 107 + attr = tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]; 108 + err = nla_parse_nested(tun_tb, BRIDGE_VLANDB_TINFO_MAX, attr, 109 + br_vlandb_tinfo_pol, extack); 110 + if (err) 111 + return err; 112 + 113 + if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) { 114 + NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute"); 115 + return -ENOENT; 116 + } 122 117 /* vlan info attribute is guaranteed by br_vlan_rtm_process_one */ 123 118 vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); 124 119 cmdmap = vinfo->flags & BRIDGE_VLAN_INFO_REMOVE_TUN ? RTM_DELLINK : 125 120 RTM_SETLINK; 126 121 /* when working on vlan ranges this represents the starting tunnel id */ 127 - tun_id = nla_get_u32(tb[BRIDGE_VLANDB_ENTRY_TUNNEL_ID]); 122 + tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]); 128 123 /* tunnel ids are mapped to each vlan in increasing order, 129 124 * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the 130 125 * current vlan, so we compute: tun_id + v - vinfo->vid ··· 162 137 if (err) 163 138 return err; 164 139 } 165 - if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_ID]) { 140 + if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) { 166 141 err = br_vlan_modify_tunnel(p, v, tb, changed, extack); 167 142 if (err) 168 143 return err;