1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright (c) 2020, Nikolay Aleksandrov <nikolay@cumulusnetworks.com> 3 #include <linux/kernel.h> 4 #include <linux/netdevice.h> 5 #include <linux/rtnetlink.h> 6 #include <linux/slab.h> 7 #include <net/ip_tunnels.h> 8 9 #include "br_private.h" 10 #include "br_private_tunnel.h" 11 12 static bool __vlan_tun_put(struct sk_buff *skb, const struct net_bridge_vlan *v) 13 { 14 __be32 tid = tunnel_id_to_key32(v->tinfo.tunnel_id); 15 struct nlattr *nest; 16 17 if (!v->tinfo.tunnel_dst) 18 return true; 19 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; 30 } 31 32 static bool __vlan_tun_can_enter_range(const struct net_bridge_vlan *v_curr, 33 const struct net_bridge_vlan *range_end) 34 { 35 return (!v_curr->tinfo.tunnel_dst && !range_end->tinfo.tunnel_dst) || 36 vlan_tunid_inrange(v_curr, range_end); 37 } 38 39 /* check if the options' state of v_curr allow it to enter the range */ 40 bool br_vlan_opts_eq_range(const struct net_bridge_vlan *v_curr, 41 const struct net_bridge_vlan *range_end) 42 { 43 u8 range_mc_rtr = br_vlan_multicast_router(range_end); 44 u8 curr_mc_rtr = br_vlan_multicast_router(v_curr); 45 46 return v_curr->state == range_end->state && 47 __vlan_tun_can_enter_range(v_curr, range_end) && 48 curr_mc_rtr == range_mc_rtr; 49 } 50 51 bool br_vlan_opts_fill(struct sk_buff *skb, const struct net_bridge_vlan *v, 52 const struct net_bridge_port *p) 53 { 54 if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_STATE, br_vlan_get_state(v)) || 55 !__vlan_tun_put(skb, v) || 56 nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS, 57 !!(v->priv_flags & BR_VLFLAG_NEIGH_SUPPRESS_ENABLED))) 58 return false; 59 60 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 61 if (nla_put_u8(skb, BRIDGE_VLANDB_ENTRY_MCAST_ROUTER, 62 br_vlan_multicast_router(v))) 63 return false; 64 if (p && !br_multicast_port_ctx_vlan_disabled(&v->port_mcast_ctx) && 65 (nla_put_u32(skb, BRIDGE_VLANDB_ENTRY_MCAST_N_GROUPS, 66 br_multicast_ngroups_get(&v->port_mcast_ctx)) || 67 nla_put_u32(skb, BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS, 68 br_multicast_ngroups_get_max(&v->port_mcast_ctx)))) 69 return false; 70 #endif 71 72 return true; 73 } 74 75 size_t br_vlan_opts_nl_size(void) 76 { 77 return nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_STATE */ 78 + nla_total_size(0) /* BRIDGE_VLANDB_ENTRY_TUNNEL_INFO */ 79 + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_TINFO_ID */ 80 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 81 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_MCAST_ROUTER */ 82 + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_ENTRY_MCAST_N_GROUPS */ 83 + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS */ 84 #endif 85 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS */ 86 + 0; 87 } 88 89 static int br_vlan_modify_state(struct net_bridge_vlan_group *vg, 90 struct net_bridge_vlan *v, 91 u8 state, 92 bool *changed, 93 struct netlink_ext_ack *extack) 94 { 95 struct net_bridge *br; 96 97 ASSERT_RTNL(); 98 99 if (state > BR_STATE_BLOCKING) { 100 NL_SET_ERR_MSG_MOD(extack, "Invalid vlan state"); 101 return -EINVAL; 102 } 103 104 if (br_vlan_is_brentry(v)) 105 br = v->br; 106 else 107 br = v->port->br; 108 109 if (br->stp_enabled == BR_KERNEL_STP) { 110 NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state when using kernel STP"); 111 return -EBUSY; 112 } 113 114 if (br_opt_get(br, BROPT_MST_ENABLED)) { 115 NL_SET_ERR_MSG_MOD(extack, "Can't modify vlan state directly when MST is enabled"); 116 return -EBUSY; 117 } 118 119 if (v->state == state) 120 return 0; 121 122 if (v->vid == br_get_pvid(vg)) 123 br_vlan_set_pvid_state(vg, state); 124 125 br_vlan_set_state(v, state); 126 *changed = true; 127 128 return 0; 129 } 130 131 static const struct nla_policy br_vlandb_tinfo_pol[BRIDGE_VLANDB_TINFO_MAX + 1] = { 132 [BRIDGE_VLANDB_TINFO_ID] = { .type = NLA_U32 }, 133 [BRIDGE_VLANDB_TINFO_CMD] = { .type = NLA_U32 }, 134 }; 135 136 static int br_vlan_modify_tunnel(const struct net_bridge_port *p, 137 struct net_bridge_vlan *v, 138 struct nlattr **tb, 139 bool *changed, 140 struct netlink_ext_ack *extack) 141 { 142 struct nlattr *tun_tb[BRIDGE_VLANDB_TINFO_MAX + 1], *attr; 143 struct bridge_vlan_info *vinfo; 144 u32 tun_id = 0; 145 int cmd, err; 146 147 if (!p) { 148 NL_SET_ERR_MSG_MOD(extack, "Can't modify tunnel mapping of non-port vlans"); 149 return -EINVAL; 150 } 151 if (!(p->flags & BR_VLAN_TUNNEL)) { 152 NL_SET_ERR_MSG_MOD(extack, "Port doesn't have tunnel flag set"); 153 return -EINVAL; 154 } 155 156 attr = tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]; 157 err = nla_parse_nested(tun_tb, BRIDGE_VLANDB_TINFO_MAX, attr, 158 br_vlandb_tinfo_pol, extack); 159 if (err) 160 return err; 161 162 if (!tun_tb[BRIDGE_VLANDB_TINFO_CMD]) { 163 NL_SET_ERR_MSG_MOD(extack, "Missing tunnel command attribute"); 164 return -ENOENT; 165 } 166 cmd = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_CMD]); 167 switch (cmd) { 168 case RTM_SETLINK: 169 if (!tun_tb[BRIDGE_VLANDB_TINFO_ID]) { 170 NL_SET_ERR_MSG_MOD(extack, "Missing tunnel id attribute"); 171 return -ENOENT; 172 } 173 /* when working on vlan ranges this is the starting tunnel id */ 174 tun_id = nla_get_u32(tun_tb[BRIDGE_VLANDB_TINFO_ID]); 175 /* vlan info attr is guaranteed by br_vlan_rtm_process_one */ 176 vinfo = nla_data(tb[BRIDGE_VLANDB_ENTRY_INFO]); 177 /* tunnel ids are mapped to each vlan in increasing order, 178 * the starting vlan is in BRIDGE_VLANDB_ENTRY_INFO and v is the 179 * current vlan, so we compute: tun_id + v - vinfo->vid 180 */ 181 tun_id += v->vid - vinfo->vid; 182 break; 183 case RTM_DELLINK: 184 break; 185 default: 186 NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel command"); 187 return -EINVAL; 188 } 189 190 return br_vlan_tunnel_info(p, cmd, v->vid, tun_id, changed); 191 } 192 193 static int br_vlan_process_one_opts(const struct net_bridge *br, 194 const struct net_bridge_port *p, 195 struct net_bridge_vlan_group *vg, 196 struct net_bridge_vlan *v, 197 struct nlattr **tb, 198 bool *changed, 199 struct netlink_ext_ack *extack) 200 { 201 int err; 202 203 *changed = false; 204 if (tb[BRIDGE_VLANDB_ENTRY_STATE]) { 205 u8 state = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_STATE]); 206 207 err = br_vlan_modify_state(vg, v, state, changed, extack); 208 if (err) 209 return err; 210 } 211 if (tb[BRIDGE_VLANDB_ENTRY_TUNNEL_INFO]) { 212 err = br_vlan_modify_tunnel(p, v, tb, changed, extack); 213 if (err) 214 return err; 215 } 216 217 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 218 if (tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) { 219 u8 val; 220 221 val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]); 222 err = br_multicast_set_vlan_router(v, val); 223 if (err) 224 return err; 225 *changed = true; 226 } 227 if (tb[BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS]) { 228 u32 val; 229 230 if (!p) { 231 NL_SET_ERR_MSG_MOD(extack, "Can't set mcast_max_groups for non-port vlans"); 232 return -EINVAL; 233 } 234 if (br_multicast_port_ctx_vlan_disabled(&v->port_mcast_ctx)) { 235 NL_SET_ERR_MSG_MOD(extack, "Multicast snooping disabled on this VLAN"); 236 return -EINVAL; 237 } 238 239 val = nla_get_u32(tb[BRIDGE_VLANDB_ENTRY_MCAST_MAX_GROUPS]); 240 br_multicast_ngroups_set_max(&v->port_mcast_ctx, val); 241 *changed = true; 242 } 243 #endif 244 245 if (tb[BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS]) { 246 bool enabled = v->priv_flags & BR_VLFLAG_NEIGH_SUPPRESS_ENABLED; 247 bool val = nla_get_u8(tb[BRIDGE_VLANDB_ENTRY_NEIGH_SUPPRESS]); 248 249 if (!p) { 250 NL_SET_ERR_MSG_MOD(extack, "Can't set neigh_suppress for non-port vlans"); 251 return -EINVAL; 252 } 253 254 if (val != enabled) { 255 v->priv_flags ^= BR_VLFLAG_NEIGH_SUPPRESS_ENABLED; 256 *changed = true; 257 } 258 } 259 260 return 0; 261 } 262 263 int br_vlan_process_options(const struct net_bridge *br, 264 const struct net_bridge_port *p, 265 struct net_bridge_vlan *range_start, 266 struct net_bridge_vlan *range_end, 267 struct nlattr **tb, 268 struct netlink_ext_ack *extack) 269 { 270 struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL; 271 struct net_bridge_vlan_group *vg; 272 int vid, err = 0; 273 u16 pvid; 274 275 if (p) 276 vg = nbp_vlan_group(p); 277 else 278 vg = br_vlan_group(br); 279 280 if (!range_start || !br_vlan_should_use(range_start)) { 281 NL_SET_ERR_MSG_MOD(extack, "Vlan range start doesn't exist, can't process options"); 282 return -ENOENT; 283 } 284 if (!range_end || !br_vlan_should_use(range_end)) { 285 NL_SET_ERR_MSG_MOD(extack, "Vlan range end doesn't exist, can't process options"); 286 return -ENOENT; 287 } 288 289 pvid = br_get_pvid(vg); 290 for (vid = range_start->vid; vid <= range_end->vid; vid++) { 291 bool changed = false; 292 293 v = br_vlan_find(vg, vid); 294 if (!v || !br_vlan_should_use(v)) { 295 NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process options"); 296 err = -ENOENT; 297 break; 298 } 299 300 err = br_vlan_process_one_opts(br, p, vg, v, tb, &changed, 301 extack); 302 if (err) 303 break; 304 305 if (changed) { 306 /* vlan options changed, check for range */ 307 if (!curr_start) { 308 curr_start = v; 309 curr_end = v; 310 continue; 311 } 312 313 if (v->vid == pvid || 314 !br_vlan_can_enter_range(v, curr_end)) { 315 br_vlan_notify(br, p, curr_start->vid, 316 curr_end->vid, RTM_NEWVLAN); 317 curr_start = v; 318 } 319 curr_end = v; 320 } else { 321 /* nothing changed and nothing to notify yet */ 322 if (!curr_start) 323 continue; 324 325 br_vlan_notify(br, p, curr_start->vid, curr_end->vid, 326 RTM_NEWVLAN); 327 curr_start = NULL; 328 curr_end = NULL; 329 } 330 } 331 if (curr_start) 332 br_vlan_notify(br, p, curr_start->vid, curr_end->vid, 333 RTM_NEWVLAN); 334 335 return err; 336 } 337 338 bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr, 339 const struct net_bridge_vlan *r_end) 340 { 341 return v_curr->vid - r_end->vid == 1 && 342 v_curr->msti == r_end->msti && 343 ((v_curr->priv_flags ^ r_end->priv_flags) & 344 BR_VLFLAG_GLOBAL_MCAST_ENABLED) == 0 && 345 br_multicast_ctx_options_equal(&v_curr->br_mcast_ctx, 346 &r_end->br_mcast_ctx); 347 } 348 349 bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range, 350 const struct net_bridge_vlan *v_opts) 351 { 352 struct nlattr *nest2 __maybe_unused; 353 u64 clockval __maybe_unused; 354 struct nlattr *nest; 355 356 nest = nla_nest_start(skb, BRIDGE_VLANDB_GLOBAL_OPTIONS); 357 if (!nest) 358 return false; 359 360 if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_ID, vid)) 361 goto out_err; 362 363 if (vid_range && vid < vid_range && 364 nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_RANGE, vid_range)) 365 goto out_err; 366 367 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 368 if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING, 369 !!(v_opts->priv_flags & BR_VLFLAG_GLOBAL_MCAST_ENABLED)) || 370 nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION, 371 v_opts->br_mcast_ctx.multicast_igmp_version) || 372 nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT, 373 v_opts->br_mcast_ctx.multicast_last_member_count) || 374 nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, 375 v_opts->br_mcast_ctx.multicast_startup_query_count) || 376 nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, 377 v_opts->br_mcast_ctx.multicast_querier) || 378 br_multicast_dump_querier_state(skb, &v_opts->br_mcast_ctx, 379 BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE)) 380 goto out_err; 381 382 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_last_member_interval); 383 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL, 384 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 385 goto out_err; 386 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_membership_interval); 387 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL, 388 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 389 goto out_err; 390 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_querier_interval); 391 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL, 392 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 393 goto out_err; 394 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_interval); 395 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL, 396 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 397 goto out_err; 398 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_query_response_interval); 399 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL, 400 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 401 goto out_err; 402 clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_startup_query_interval); 403 if (nla_put_u64_64bit(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL, 404 clockval, BRIDGE_VLANDB_GOPTS_PAD)) 405 goto out_err; 406 407 if (br_rports_have_mc_router(&v_opts->br_mcast_ctx)) { 408 nest2 = nla_nest_start(skb, 409 BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS); 410 if (!nest2) 411 goto out_err; 412 413 rcu_read_lock(); 414 if (br_rports_fill_info(skb, &v_opts->br_mcast_ctx)) { 415 rcu_read_unlock(); 416 nla_nest_cancel(skb, nest2); 417 goto out_err; 418 } 419 rcu_read_unlock(); 420 421 nla_nest_end(skb, nest2); 422 } 423 424 #if IS_ENABLED(CONFIG_IPV6) 425 if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION, 426 v_opts->br_mcast_ctx.multicast_mld_version)) 427 goto out_err; 428 #endif 429 #endif 430 431 if (nla_put_u16(skb, BRIDGE_VLANDB_GOPTS_MSTI, v_opts->msti)) 432 goto out_err; 433 434 nla_nest_end(skb, nest); 435 436 return true; 437 438 out_err: 439 nla_nest_cancel(skb, nest); 440 return false; 441 } 442 443 static size_t rtnl_vlan_global_opts_nlmsg_size(const struct net_bridge_vlan *v) 444 { 445 return NLMSG_ALIGN(sizeof(struct br_vlan_msg)) 446 + nla_total_size(0) /* BRIDGE_VLANDB_GLOBAL_OPTIONS */ 447 + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_ID */ 448 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 449 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING */ 450 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION */ 451 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION */ 452 + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT */ 453 + nla_total_size(sizeof(u32)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT */ 454 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL */ 455 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL */ 456 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL */ 457 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL */ 458 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */ 459 + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */ 460 + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */ 461 + br_multicast_querier_state_size() /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE */ 462 + nla_total_size(0) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */ 463 + br_rports_size(&v->br_mcast_ctx) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS */ 464 #endif 465 + nla_total_size(sizeof(u16)) /* BRIDGE_VLANDB_GOPTS_MSTI */ 466 + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */ 467 } 468 469 static void br_vlan_global_opts_notify(const struct net_bridge *br, 470 u16 vid, u16 vid_range) 471 { 472 struct net_bridge_vlan *v; 473 struct br_vlan_msg *bvm; 474 struct nlmsghdr *nlh; 475 struct sk_buff *skb; 476 int err = -ENOBUFS; 477 478 /* right now notifications are done only with rtnl held */ 479 ASSERT_RTNL(); 480 481 /* need to find the vlan due to flags/options */ 482 v = br_vlan_find(br_vlan_group(br), vid); 483 if (!v) 484 return; 485 486 skb = nlmsg_new(rtnl_vlan_global_opts_nlmsg_size(v), GFP_KERNEL); 487 if (!skb) 488 goto out_err; 489 490 err = -EMSGSIZE; 491 nlh = nlmsg_put(skb, 0, 0, RTM_NEWVLAN, sizeof(*bvm), 0); 492 if (!nlh) 493 goto out_err; 494 bvm = nlmsg_data(nlh); 495 memset(bvm, 0, sizeof(*bvm)); 496 bvm->family = AF_BRIDGE; 497 bvm->ifindex = br->dev->ifindex; 498 499 if (!br_vlan_global_opts_fill(skb, vid, vid_range, v)) 500 goto out_err; 501 502 nlmsg_end(skb, nlh); 503 rtnl_notify(skb, dev_net(br->dev), 0, RTNLGRP_BRVLAN, NULL, GFP_KERNEL); 504 return; 505 506 out_err: 507 rtnl_set_sk_err(dev_net(br->dev), RTNLGRP_BRVLAN, err); 508 kfree_skb(skb); 509 } 510 511 static int br_vlan_process_global_one_opts(const struct net_bridge *br, 512 struct net_bridge_vlan_group *vg, 513 struct net_bridge_vlan *v, 514 struct nlattr **tb, 515 bool *changed, 516 struct netlink_ext_ack *extack) 517 { 518 int err __maybe_unused; 519 520 *changed = false; 521 #ifdef CONFIG_BRIDGE_IGMP_SNOOPING 522 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]) { 523 u8 mc_snooping; 524 525 mc_snooping = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]); 526 if (br_multicast_toggle_global_vlan(v, !!mc_snooping)) 527 *changed = true; 528 } 529 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]) { 530 u8 ver; 531 532 ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]); 533 err = br_multicast_set_igmp_version(&v->br_mcast_ctx, ver); 534 if (err) 535 return err; 536 *changed = true; 537 } 538 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]) { 539 u32 cnt; 540 541 cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT]); 542 v->br_mcast_ctx.multicast_last_member_count = cnt; 543 *changed = true; 544 } 545 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]) { 546 u32 cnt; 547 548 cnt = nla_get_u32(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]); 549 v->br_mcast_ctx.multicast_startup_query_count = cnt; 550 *changed = true; 551 } 552 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]) { 553 u64 val; 554 555 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]); 556 v->br_mcast_ctx.multicast_last_member_interval = clock_t_to_jiffies(val); 557 *changed = true; 558 } 559 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]) { 560 u64 val; 561 562 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]); 563 v->br_mcast_ctx.multicast_membership_interval = clock_t_to_jiffies(val); 564 *changed = true; 565 } 566 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]) { 567 u64 val; 568 569 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]); 570 v->br_mcast_ctx.multicast_querier_interval = clock_t_to_jiffies(val); 571 *changed = true; 572 } 573 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]) { 574 u64 val; 575 576 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]); 577 br_multicast_set_query_intvl(&v->br_mcast_ctx, val); 578 *changed = true; 579 } 580 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) { 581 u64 val; 582 583 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]); 584 v->br_mcast_ctx.multicast_query_response_interval = clock_t_to_jiffies(val); 585 *changed = true; 586 } 587 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]) { 588 u64 val; 589 590 val = nla_get_u64(tb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]); 591 br_multicast_set_startup_query_intvl(&v->br_mcast_ctx, val); 592 *changed = true; 593 } 594 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) { 595 u8 val; 596 597 val = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]); 598 err = br_multicast_set_querier(&v->br_mcast_ctx, val); 599 if (err) 600 return err; 601 *changed = true; 602 } 603 #if IS_ENABLED(CONFIG_IPV6) 604 if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) { 605 u8 ver; 606 607 ver = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]); 608 err = br_multicast_set_mld_version(&v->br_mcast_ctx, ver); 609 if (err) 610 return err; 611 *changed = true; 612 } 613 #endif 614 #endif 615 if (tb[BRIDGE_VLANDB_GOPTS_MSTI]) { 616 u16 msti; 617 618 msti = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_MSTI]); 619 err = br_mst_vlan_set_msti(v, msti); 620 if (err) 621 return err; 622 *changed = true; 623 } 624 625 return 0; 626 } 627 628 static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = { 629 [BRIDGE_VLANDB_GOPTS_ID] = { .type = NLA_U16 }, 630 [BRIDGE_VLANDB_GOPTS_RANGE] = { .type = NLA_U16 }, 631 [BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING] = { .type = NLA_U8 }, 632 [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 }, 633 [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 }, 634 [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 }, 635 [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, 636 [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 }, 637 [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 }, 638 [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL] = { .type = NLA_U64 }, 639 [BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL] = { .type = NLA_U64 }, 640 [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL] = { .type = NLA_U64 }, 641 [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL] = { .type = NLA_U64 }, 642 [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL] = { .type = NLA_U64 }, 643 [BRIDGE_VLANDB_GOPTS_MSTI] = NLA_POLICY_MAX(NLA_U16, VLAN_N_VID - 1), 644 }; 645 646 int br_vlan_rtm_process_global_options(struct net_device *dev, 647 const struct nlattr *attr, 648 int cmd, 649 struct netlink_ext_ack *extack) 650 { 651 struct net_bridge_vlan *v, *curr_start = NULL, *curr_end = NULL; 652 struct nlattr *tb[BRIDGE_VLANDB_GOPTS_MAX + 1]; 653 struct net_bridge_vlan_group *vg; 654 u16 vid, vid_range = 0; 655 struct net_bridge *br; 656 int err = 0; 657 658 if (cmd != RTM_NEWVLAN) { 659 NL_SET_ERR_MSG_MOD(extack, "Global vlan options support only set operation"); 660 return -EINVAL; 661 } 662 if (!netif_is_bridge_master(dev)) { 663 NL_SET_ERR_MSG_MOD(extack, "Global vlan options can only be set on bridge device"); 664 return -EINVAL; 665 } 666 br = netdev_priv(dev); 667 vg = br_vlan_group(br); 668 if (WARN_ON(!vg)) 669 return -ENODEV; 670 671 err = nla_parse_nested(tb, BRIDGE_VLANDB_GOPTS_MAX, attr, 672 br_vlan_db_gpol, extack); 673 if (err) 674 return err; 675 676 if (!tb[BRIDGE_VLANDB_GOPTS_ID]) { 677 NL_SET_ERR_MSG_MOD(extack, "Missing vlan entry id"); 678 return -EINVAL; 679 } 680 vid = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_ID]); 681 if (!br_vlan_valid_id(vid, extack)) 682 return -EINVAL; 683 684 if (tb[BRIDGE_VLANDB_GOPTS_RANGE]) { 685 vid_range = nla_get_u16(tb[BRIDGE_VLANDB_GOPTS_RANGE]); 686 if (!br_vlan_valid_id(vid_range, extack)) 687 return -EINVAL; 688 if (vid >= vid_range) { 689 NL_SET_ERR_MSG_MOD(extack, "End vlan id is less than or equal to start vlan id"); 690 return -EINVAL; 691 } 692 } else { 693 vid_range = vid; 694 } 695 696 for (; vid <= vid_range; vid++) { 697 bool changed = false; 698 699 v = br_vlan_find(vg, vid); 700 if (!v) { 701 NL_SET_ERR_MSG_MOD(extack, "Vlan in range doesn't exist, can't process global options"); 702 err = -ENOENT; 703 break; 704 } 705 706 err = br_vlan_process_global_one_opts(br, vg, v, tb, &changed, 707 extack); 708 if (err) 709 break; 710 711 if (changed) { 712 /* vlan options changed, check for range */ 713 if (!curr_start) { 714 curr_start = v; 715 curr_end = v; 716 continue; 717 } 718 719 if (!br_vlan_global_opts_can_enter_range(v, curr_end)) { 720 br_vlan_global_opts_notify(br, curr_start->vid, 721 curr_end->vid); 722 curr_start = v; 723 } 724 curr_end = v; 725 } else { 726 /* nothing changed and nothing to notify yet */ 727 if (!curr_start) 728 continue; 729 730 br_vlan_global_opts_notify(br, curr_start->vid, 731 curr_end->vid); 732 curr_start = NULL; 733 curr_end = NULL; 734 } 735 } 736 if (curr_start) 737 br_vlan_global_opts_notify(br, curr_start->vid, curr_end->vid); 738 739 return err; 740 } 741
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.