Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright (c) 2020, Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
0003 #include <linux/kernel.h>
0004 #include <linux/netdevice.h>
0005 #include <linux/rtnetlink.h>
0006 #include <linux/slab.h>
0007 #include <net/ip_tunnels.h>
0008 
0009 #include "br_private.h"
0010 #include "br_private_tunnel.h"
0011 
0012 static bool __vlan_tun_put(struct sk_buff *skb, const struct net_bridge_vlan *v)
0013 {
0014     __be32 tid = tunnel_id_to_key32(v->tinfo.tunnel_id);
0015     struct nlattr *nest;
0016 
0017     if (!v->tinfo.tunnel_dst)
0018         return true;
0019 
0020     nest = nla_nest_start(skb, BRIDGE_VLANDB_ENTRY_TUNNEL_INFO);
0021     if (!nest)
0022         return false;
0023     if (nla_put_u32(skb, BRIDGE_VLANDB_TINFO_ID, be32_to_cpu(tid))) {
0024         nla_nest_cancel(skb, nest);
0025         return false;
0026     }
0027     nla_nest_end(skb, nest);
0028 
0029     return true;
0030 }
0031 
0032 static bool __vlan_tun_can_enter_range(const struct net_bridge_vlan *v_curr,
0033                        const struct net_bridge_vlan *range_end)
0034 {
0035     return (!v_curr->tinfo.tunnel_dst && !range_end->tinfo.tunnel_dst) ||
0036            vlan_tunid_inrange(v_curr, range_end);
0037 }
0038 
0039 /* check if the options' state of v_curr allow it to enter the range */
0040 bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr,
0041                const struct net_bridge_vlan *range_end)
0042 {
0043     u8 range_mc_rtr = br_vlan_multicast_router(range_end);
0044     u8 curr_mc_rtr = br_vlan_multicast_router(v_curr);
0045 
0046     return v_curr->state == range_end->state &&
0047            __vlan_tun_can_enter_range(v_curr, range_end) &&
0048            curr_mc_rtr == range_mc_rtr;
0049 }
0050 
0051 bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v)
0052 {
0053     if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_STATE, br_vlan_get_state(v)) ||
0054         !__vlan_tun_put(skb, v))
0055         return false;
0056 
0057 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0058     if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_MCAST_ROUTER,
0059                br_vlan_multicast_router(v)))
0060         return false;
0061 #endif
0062 
0063     return true;
0064 }
0065 
0066 size_t br_vlan_opts_nl_size(void)
0067 {
0068     return nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_STATE */
0069            + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY_TUNNEL_INFO */
0070            + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_TINFO_ID */
0071 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0072            + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_MCAST_ROUTER */
0073 #endif
0074            + 0;
0075 }
0076 
0077 static int br_vlan_modify_state(struct net_bridge_vlan_group *vg,
0078                 struct net_bridge_vlan *v,
0079                 u8 state,
0080                 bool *changed,
0081                 struct netlink_ext_ack *extack)
0082 {
0083     struct net_bridge *br;
0084 
0085     ASSERT_RTNL();
0086 
0087     if (state > BR_STATE_BLOCKING) {
0088         NL_SET_ERR_MSG_MOD(extack, "Invalid vlan state");
0089         return -EINVAL;
0090     }
0091 
0092     if (br_vlan_is_brentry(v))
0093         br = v->br;
0094     else
0095         br = v->port->br;
0096 
0097     if (br->stp_enabled == BR_KERNEL_STP) {
0098         NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state when using kernel STP");
0099         return -EBUSY;
0100     }
0101 
0102     if (br_opt_get(br, BROPT_MST_ENABLED)) {
0103         NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state directly when MST is enabled");
0104         return -EBUSY;
0105     }
0106 
0107     if (v->state == state)
0108         return 0;
0109 
0110     if (v->vid == br_get_pvid(vg))
0111         br_vlan_set_pvid_state(vg, state);
0112 
0113     br_vlan_set_state(v, state);
0114     *changed = true;
0115 
0116     return 0;
0117 }
0118 
0119 static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = {
0120     [BRIDGE_VLANDB_TINFO_ID]    = { .type = NLA_U32 },
0121     [BRIDGE_VLANDB_TINFO_CMD]   = { .type = NLA_U32 },
0122 };
0123 
0124 static int br_vlan_modify_tunnel(const struct net_bridge_port *p,
0125                  struct net_bridge_vlan *v,
0126                  struct nlattr **tb,
0127                  bool *changed,
0128                  struct netlink_ext_ack *extack)
0129 {
0130     struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr;
0131     struct bridge_vlan_info *vinfo;
0132     u32 tun_id = 0;
0133     int cmd, err;
0134 
0135     if (!p) {
0136         NL_SET_ERR_MSG_MOD(extack, "Can't modify tunnel mapping of non-port vlans");
0137         return -EINVAL;
0138     }
0139     if (!(p->flags & BR_VLAN_TUNNEL)) {
0140         NL_SET_ERR_MSG_MOD(extack, "Port doesn't have tunnel flag set");
0141         return -EINVAL;
0142     }
0143 
0144     attr = tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO];
0145     err = nla_parse_nested(tun_tb, BRIDGE_VLANDB_TINFO_MAX, attr,
0146                    br_vlandb_tinfo_pol, extack);
0147     if (err)
0148         return err;
0149 
0150     if (!tun_tb[BRIDGE_VLANDB_TINFO_CMD]) {
0151         NL_SET_ERR_MSG_MOD(extack, "Missing tunnel command attribute");
0152         return -ENOENT;
0153     }
0154     cmd = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_CMD]);
0155     switch (cmd) {
0156     case RTM_SETLINK:
0157         if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) {
0158             NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute");
0159             return -ENOENT;
0160         }
0161         /* when working on vlan ranges this is the starting tunnel id */
0162         tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]);
0163         /* vlan info attr is guaranteed by br_vlan_rtm_process_one */
0164         vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]);
0165         /* tunnel ids are mapped to each vlan in increasing order,
0166          * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the
0167          * current vlan, so we compute: tun_id + v - vinfo->vid
0168          */
0169         tun_id += v->vid - vinfo->vid;
0170         break;
0171     case RTM_DELLINK:
0172         break;
0173     default:
0174         NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel command");
0175         return -EINVAL;
0176     }
0177 
0178     return br_vlan_tunnel_info(p, cmd, v->vid, tun_id, changed);
0179 }
0180 
0181 static int br_vlan_process_one_opts(const struct net_bridge *br,
0182                     const struct net_bridge_port *p,
0183                     struct net_bridge_vlan_group *vg,
0184                     struct net_bridge_vlan *v,
0185                     struct nlattr **tb,
0186                     bool *changed,
0187                     struct netlink_ext_ack *extack)
0188 {
0189     int err;
0190 
0191     *changed = false;
0192     if (tb[BRIDGE_VLANDB_ENTRY_STATE]) {
0193         u8 state = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_STATE]);
0194 
0195         err = br_vlan_modify_state(vg, v, state, changed, extack);
0196         if (err)
0197             return err;
0198     }
0199     if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) {
0200         err = br_vlan_modify_tunnel(p, v, tb, changed, extack);
0201         if (err)
0202             return err;
0203     }
0204 
0205 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0206     if (tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) {
0207         u8 val;
0208 
0209         val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]);
0210         err = br_multicast_set_vlan_router(v, val);
0211         if (err)
0212             return err;
0213         *changed = true;
0214     }
0215 #endif
0216 
0217     return 0;
0218 }
0219 
0220 int br_vlan_process_options(const struct net_bridge *br,
0221                 const struct net_bridge_port *p,
0222                 struct net_bridge_vlan *range_start,
0223                 struct net_bridge_vlan *range_end,
0224                 struct nlattr **tb,
0225                 struct netlink_ext_ack *extack)
0226 {
0227     struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL;
0228     struct net_bridge_vlan_group *vg;
0229     int vid, err = 0;
0230     u16 pvid;
0231 
0232     if (p)
0233         vg = nbp_vlan_group(p);
0234     else
0235         vg = br_vlan_group(br);
0236 
0237     if (!range_start || !br_vlan_should_use(range_start)) {
0238         NL_SET_ERR_MSG_MOD(extack, "Vlan range start doesn't exist, can't process options");
0239         return -ENOENT;
0240     }
0241     if (!range_end || !br_vlan_should_use(range_end)) {
0242         NL_SET_ERR_MSG_MOD(extack, "Vlan range end doesn't exist, can't process options");
0243         return -ENOENT;
0244     }
0245 
0246     pvid = br_get_pvid(vg);
0247     for (vid = range_start->vid; vid <= range_end->vid; vid++) {
0248         bool changed = false;
0249 
0250         v = br_vlan_find(vg, vid);
0251         if (!v || !br_vlan_should_use(v)) {
0252             NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process options");
0253             err = -ENOENT;
0254             break;
0255         }
0256 
0257         err = br_vlan_process_one_opts(br, p, vg, v, tb, &changed,
0258                            extack);
0259         if (err)
0260             break;
0261 
0262         if (changed) {
0263             /* vlan options changed, check for range */
0264             if (!curr_start) {
0265                 curr_start = v;
0266                 curr_end = v;
0267                 continue;
0268             }
0269 
0270             if (v->vid == pvid ||
0271                 !br_vlan_can_enter_range(v, curr_end)) {
0272                 br_vlan_notify(br, p, curr_start->vid,
0273                            curr_end->vid, RTM_NEWVLAN);
0274                 curr_start = v;
0275             }
0276             curr_end = v;
0277         } else {
0278             /* nothing changed and nothing to notify yet */
0279             if (!curr_start)
0280                 continue;
0281 
0282             br_vlan_notify(br, p, curr_start->vid, curr_end->vid,
0283                        RTM_NEWVLAN);
0284             curr_start = NULL;
0285             curr_end = NULL;
0286         }
0287     }
0288     if (curr_start)
0289         br_vlan_notify(br, p, curr_start->vid, curr_end->vid,
0290                    RTM_NEWVLAN);
0291 
0292     return err;
0293 }
0294 
0295 bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
0296                      const struct net_bridge_vlan *r_end)
0297 {
0298     return v_curr->vid - r_end->vid == 1 &&
0299         v_curr->msti == r_end->msti &&
0300            ((v_curr->priv_flags ^ r_end->priv_flags) &
0301         BR_VLFLAG_GLOBAL_MCAST_ENABLED) == 0 &&
0302         br_multicast_ctx_options_equal(&v_curr->br_mcast_ctx,
0303                            &r_end->br_mcast_ctx);
0304 }
0305 
0306 bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
0307                   const struct net_bridge_vlan *v_opts)
0308 {
0309     struct nlattr *nest2 __maybe_unused;
0310     u64 clockval __maybe_unused;
0311     struct nlattr *nest;
0312 
0313     nest = nla_nest_start(skb, BRIDGE_VLANDB_GLOBAL_OPTIONS);
0314     if (!nest)
0315         return false;
0316 
0317     if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_ID, vid))
0318         goto out_err;
0319 
0320     if (vid_range && vid < vid_range &&
0321         nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_RANGE, vid_range))
0322         goto out_err;
0323 
0324 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0325     if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING,
0326                !!(v_opts->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED)) ||
0327         nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION,
0328                v_opts->br_mcast_ctx.multicast_igmp_version) ||
0329         nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT,
0330             v_opts->br_mcast_ctx.multicast_last_member_count) ||
0331         nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
0332             v_opts->br_mcast_ctx.multicast_startup_query_count) ||
0333         nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
0334                v_opts->br_mcast_ctx.multicast_querier) ||
0335         br_multicast_dump_querier_state(skb, &v_opts->br_mcast_ctx,
0336                         BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE))
0337         goto out_err;
0338 
0339     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_last_member_interval);
0340     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL,
0341                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0342         goto out_err;
0343     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_membership_interval);
0344     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL,
0345                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0346         goto out_err;
0347     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_querier_interval);
0348     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL,
0349                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0350         goto out_err;
0351     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_interval);
0352     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL,
0353                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0354         goto out_err;
0355     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_response_interval);
0356     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
0357                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0358         goto out_err;
0359     clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_startup_query_interval);
0360     if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
0361                   clockval, BRIDGE_VLANDB_GOPTS_PAD))
0362         goto out_err;
0363 
0364     if (br_rports_have_mc_router(&v_opts->br_mcast_ctx)) {
0365         nest2 = nla_nest_start(skb,
0366                        BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS);
0367         if (!nest2)
0368             goto out_err;
0369 
0370         rcu_read_lock();
0371         if (br_rports_fill_info(skb, &v_opts->br_mcast_ctx)) {
0372             rcu_read_unlock();
0373             nla_nest_cancel(skb, nest2);
0374             goto out_err;
0375         }
0376         rcu_read_unlock();
0377 
0378         nla_nest_end(skb, nest2);
0379     }
0380 
0381 #if IS_ENABLED(CONFIG_IPV6)
0382     if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION,
0383                v_opts->br_mcast_ctx.multicast_mld_version))
0384         goto out_err;
0385 #endif
0386 #endif
0387 
0388     if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_MSTI, v_opts->msti))
0389         goto out_err;
0390 
0391     nla_nest_end(skb, nest);
0392 
0393     return true;
0394 
0395 out_err:
0396     nla_nest_cancel(skb, nest);
0397     return false;
0398 }
0399 
0400 static size_t rtnl_vlan_global_opts_nlmsg_size(const struct net_bridge_vlan *v)
0401 {
0402     return NLMSG_ALIGN(sizeof(struct br_vlan_msg))
0403         + nla_total_size(0) /* BRIDGE_VLANDB_GLOBAL_OPTIONS */
0404         + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_ID */
0405 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0406         + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING */
0407         + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION */
0408         + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION */
0409         + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT */
0410         + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT */
0411         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL */
0412         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL */
0413         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL */
0414         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL */
0415         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */
0416         + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */
0417         + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */
0418         + br_multicast_querier_state_size() /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE */
0419         + nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
0420         + br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */
0421 #endif
0422         + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_MSTI */
0423         + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */
0424 }
0425 
0426 static void br_vlan_global_opts_notify(const struct net_bridge *br,
0427                        u16 vid, u16 vid_range)
0428 {
0429     struct net_bridge_vlan *v;
0430     struct br_vlan_msg *bvm;
0431     struct nlmsghdr *nlh;
0432     struct sk_buff *skb;
0433     int err = -ENOBUFS;
0434 
0435     /* right now notifications are done only with rtnl held */
0436     ASSERT_RTNL();
0437 
0438     /* need to find the vlan due to flags/options */
0439     v = br_vlan_find(br_vlan_group(br), vid);
0440     if (!v)
0441         return;
0442 
0443     skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(v), GFP_KERNEL);
0444     if (!skb)
0445         goto out_err;
0446 
0447     err = -EMSGSIZE;
0448     nlh = nlmsg_put(skb, 0, 0, RTM_NEWVLAN, sizeof(*bvm), 0);
0449     if (!nlh)
0450         goto out_err;
0451     bvm = nlmsg_data(nlh);
0452     memset(bvm, 0, sizeof(*bvm));
0453     bvm->family = AF_BRIDGE;
0454     bvm->ifindex = br->dev->ifindex;
0455 
0456     if (!br_vlan_global_opts_fill(skb, vid, vid_range, v))
0457         goto out_err;
0458 
0459     nlmsg_end(skb, nlh);
0460     rtnl_notify(skb, dev_net(br->dev), 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL);
0461     return;
0462 
0463 out_err:
0464     rtnl_set_sk_err(dev_net(br->dev), RTNLGRP_BRVLAN, err);
0465     kfree_skb(skb);
0466 }
0467 
0468 static int br_vlan_process_global_one_opts(const struct net_bridge *br,
0469                        struct net_bridge_vlan_group *vg,
0470                        struct net_bridge_vlan *v,
0471                        struct nlattr **tb,
0472                        bool *changed,
0473                        struct netlink_ext_ack *extack)
0474 {
0475     int err __maybe_unused;
0476 
0477     *changed = false;
0478 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING
0479     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]) {
0480         u8 mc_snooping;
0481 
0482         mc_snooping = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]);
0483         if (br_multicast_toggle_global_vlan(v, !!mc_snooping))
0484             *changed = true;
0485     }
0486     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]) {
0487         u8 ver;
0488 
0489         ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]);
0490         err = br_multicast_set_igmp_version(&v->br_mcast_ctx, ver);
0491         if (err)
0492             return err;
0493         *changed = true;
0494     }
0495     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]) {
0496         u32 cnt;
0497 
0498         cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]);
0499         v->br_mcast_ctx.multicast_last_member_count = cnt;
0500         *changed = true;
0501     }
0502     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]) {
0503         u32 cnt;
0504 
0505         cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]);
0506         v->br_mcast_ctx.multicast_startup_query_count = cnt;
0507         *changed = true;
0508     }
0509     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]) {
0510         u64 val;
0511 
0512         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]);
0513         v->br_mcast_ctx.multicast_last_member_interval = clock_t_to_jiffies(val);
0514         *changed = true;
0515     }
0516     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]) {
0517         u64 val;
0518 
0519         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]);
0520         v->br_mcast_ctx.multicast_membership_interval = clock_t_to_jiffies(val);
0521         *changed = true;
0522     }
0523     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]) {
0524         u64 val;
0525 
0526         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]);
0527         v->br_mcast_ctx.multicast_querier_interval = clock_t_to_jiffies(val);
0528         *changed = true;
0529     }
0530     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]) {
0531         u64 val;
0532 
0533         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]);
0534         br_multicast_set_query_intvl(&v->br_mcast_ctx, val);
0535         *changed = true;
0536     }
0537     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) {
0538         u64 val;
0539 
0540         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]);
0541         v->br_mcast_ctx.multicast_query_response_interval = clock_t_to_jiffies(val);
0542         *changed = true;
0543     }
0544     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]) {
0545         u64 val;
0546 
0547         val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]);
0548         br_multicast_set_startup_query_intvl(&v->br_mcast_ctx, val);
0549         *changed = true;
0550     }
0551     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) {
0552         u8 val;
0553 
0554         val = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]);
0555         err = br_multicast_set_querier(&v->br_mcast_ctx, val);
0556         if (err)
0557             return err;
0558         *changed = true;
0559     }
0560 #if IS_ENABLED(CONFIG_IPV6)
0561     if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
0562         u8 ver;
0563 
0564         ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]);
0565         err = br_multicast_set_mld_version(&v->br_mcast_ctx, ver);
0566         if (err)
0567             return err;
0568         *changed = true;
0569     }
0570 #endif
0571 #endif
0572     if (tb[BRIDGE_VLANDB_GOPTS_MSTI]) {
0573         u16 msti;
0574 
0575         msti = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_MSTI]);
0576         err = br_mst_vlan_set_msti(v, msti);
0577         if (err)
0578             return err;
0579         *changed = true;
0580     }
0581 
0582     return 0;
0583 }
0584 
0585 static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = {
0586     [BRIDGE_VLANDB_GOPTS_ID]    = { .type = NLA_U16 },
0587     [BRIDGE_VLANDB_GOPTS_RANGE] = { .type = NLA_U16 },
0588     [BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]    = { .type = NLA_U8 },
0589     [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 },
0590     [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 },
0591     [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 },
0592     [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]    = { .type = NLA_U8 },
0593     [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 },
0594     [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]   = { .type = NLA_U32 },
0595     [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]   = { .type = NLA_U64 },
0596     [BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]    = { .type = NLA_U64 },
0597     [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]   = { .type = NLA_U64 },
0598     [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 },
0599     [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 },
0600     [BRIDGE_VLANDB_GOPTS_MSTI] = NLA_POLICY_MAX(NLA_U16, VLAN_N_VID - 1),
0601 };
0602 
0603 int br_vlan_rtm_process_global_options(struct net_device *dev,
0604                        const struct nlattr *attr,
0605                        int cmd,
0606                        struct netlink_ext_ack *extack)
0607 {
0608     struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL;
0609     struct nlattr *tb[BRIDGE_VLANDB_GOPTS_MAX + 1];
0610     struct net_bridge_vlan_group *vg;
0611     u16 vid, vid_range = 0;
0612     struct net_bridge *br;
0613     int err = 0;
0614 
0615     if (cmd != RTM_NEWVLAN) {
0616         NL_SET_ERR_MSG_MOD(extack, "Global vlan options support only set operation");
0617         return -EINVAL;
0618     }
0619     if (!netif_is_bridge_master(dev)) {
0620         NL_SET_ERR_MSG_MOD(extack, "Global vlan options can only be set on bridge device");
0621         return -EINVAL;
0622     }
0623     br = netdev_priv(dev);
0624     vg = br_vlan_group(br);
0625     if (WARN_ON(!vg))
0626         return -ENODEV;
0627 
0628     err = nla_parse_nested(tb, BRIDGE_VLANDB_GOPTS_MAX, attr,
0629                    br_vlan_db_gpol, extack);
0630     if (err)
0631         return err;
0632 
0633     if (!tb[BRIDGE_VLANDB_GOPTS_ID]) {
0634         NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry id");
0635         return -EINVAL;
0636     }
0637     vid = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_ID]);
0638     if (!br_vlan_valid_id(vid, extack))
0639         return -EINVAL;
0640 
0641     if (tb[BRIDGE_VLANDB_GOPTS_RANGE]) {
0642         vid_range = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_RANGE]);
0643         if (!br_vlan_valid_id(vid_range, extack))
0644             return -EINVAL;
0645         if (vid >= vid_range) {
0646             NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id");
0647             return -EINVAL;
0648         }
0649     } else {
0650         vid_range = vid;
0651     }
0652 
0653     for (; vid <= vid_range; vid++) {
0654         bool changed = false;
0655 
0656         v = br_vlan_find(vg, vid);
0657         if (!v) {
0658             NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process global options");
0659             err = -ENOENT;
0660             break;
0661         }
0662 
0663         err = br_vlan_process_global_one_opts(br, vg, v, tb, &changed,
0664                               extack);
0665         if (err)
0666             break;
0667 
0668         if (changed) {
0669             /* vlan options changed, check for range */
0670             if (!curr_start) {
0671                 curr_start = v;
0672                 curr_end = v;
0673                 continue;
0674             }
0675 
0676             if (!br_vlan_global_opts_can_enter_range(v, curr_end)) {
0677                 br_vlan_global_opts_notify(br, curr_start->vid,
0678                                curr_end->vid);
0679                 curr_start = v;
0680             }
0681             curr_end = v;
0682         } else {
0683             /* nothing changed and nothing to notify yet */
0684             if (!curr_start)
0685                 continue;
0686 
0687             br_vlan_global_opts_notify(br, curr_start->vid,
0688                            curr_end->vid);
0689             curr_start = NULL;
0690             curr_end = NULL;
0691         }
0692     }
0693     if (curr_start)
0694         br_vlan_global_opts_notify(br, curr_start->vid, curr_end->vid);
0695 
0696     return err;
0697 }