Add support to change and retrieve global vlan multicast router state which is used for the bridge itself. We just need to pass multicast context to br_multicast_set_router instead of bridge device and the rest of the logic remains the same.
Unified · Split
| @@ -561,6 +561,7 @@ enum { · 560 unmodified lines | ||
| 561 | 561 | BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL, |
| 562 | 562 | BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL, |
| 563 | 563 | BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, |
| 564 | + BRIDGE_VLANDB_GOPTS_MCAST_ROUTER, | |
| 564 | 565 | __BRIDGE_VLANDB_GOPTS_MAX |
| 565 | 566 | }; |
| 566 | 567 | #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) |
| @@ -4053,17 +4053,16 @@ void br_multicast_dev_del(struct net_bridge *br) · 4052 unmodified lines | ||
| 4053 | 4053 | rcu_barrier(); |
| 4054 | 4054 | } |
| 4055 | 4055 | |
| 4056 | −int br_multicast_set_router(struct net_bridge *br, unsigned long val) | |
| 4056 | +int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val) | |
| 4057 | 4057 | { |
| 4058 | − struct net_bridge_mcast *brmctx = &br->multicast_ctx; | |
| 4059 | 4058 | int err = -EINVAL; |
| 4060 | 4059 | |
| 4061 | − spin_lock_bh(&br->multicast_lock); | |
| 4060 | + spin_lock_bh(&brmctx->br->multicast_lock); | |
| 4062 | 4061 | |
| 4063 | 4062 | switch (val) { |
| 4064 | 4063 | case MDB_RTR_TYPE_DISABLED: |
| 4065 | 4064 | case MDB_RTR_TYPE_PERM: |
| 4066 | − br_mc_router_state_change(br, val == MDB_RTR_TYPE_PERM); | |
| 4065 | + br_mc_router_state_change(brmctx->br, val == MDB_RTR_TYPE_PERM); | |
| 4067 | 4066 | del_timer(&brmctx->ip4_mc_router_timer); |
| 4068 | 4067 | #if IS_ENABLED(CONFIG_IPV6) |
| 4069 | 4068 | del_timer(&brmctx->ip6_mc_router_timer); |
| @@ -4073,13 +4072,13 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) · 3 unmodified lines | ||
| 4073 | 4072 | break; |
| 4074 | 4073 | case MDB_RTR_TYPE_TEMP_QUERY: |
| 4075 | 4074 | if (brmctx->multicast_router != MDB_RTR_TYPE_TEMP_QUERY) |
| 4076 | − br_mc_router_state_change(br, false); | |
| 4075 | + br_mc_router_state_change(brmctx->br, false); | |
| 4077 | 4076 | brmctx->multicast_router = val; |
| 4078 | 4077 | err = 0; |
| 4079 | 4078 | break; |
| 4080 | 4079 | } |
| 4081 | 4080 | |
| 4082 | − spin_unlock_bh(&br->multicast_lock); | |
| 4081 | + spin_unlock_bh(&brmctx->br->multicast_lock); | |
| 4083 | 4082 | |
| 4084 | 4083 | return err; |
| 4085 | 4084 | } |
| @@ -1286,7 +1286,8 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], · 1285 unmodified lines | ||
| 1286 | 1286 | if (data[IFLA_BR_MCAST_ROUTER]) { |
| 1287 | 1287 | u8 multicast_router = nla_get_u8(data[IFLA_BR_MCAST_ROUTER]); |
| 1288 | 1288 | |
| 1289 | − err = br_multicast_set_router(br, multicast_router); | |
| 1289 | + err = br_multicast_set_router(&br->multicast_ctx, | |
| 1290 | + multicast_router); | |
| 1290 | 1291 | if (err) |
| 1291 | 1292 | return err; |
| 1292 | 1293 | } |
| @@ -877,7 +877,7 @@ void br_multicast_dev_del(struct net_bridge *br); · 876 unmodified lines | ||
| 877 | 877 | void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, |
| 878 | 878 | struct net_bridge_mcast *brmctx, |
| 879 | 879 | bool local_rcv, bool local_orig); |
| 880 | −int br_multicast_set_router(struct net_bridge *br, unsigned long val); | |
| 880 | +int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val); | |
| 881 | 881 | int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); |
| 882 | 882 | int br_multicast_toggle(struct net_bridge *br, unsigned long val, |
| 883 | 883 | struct netlink_ext_ack *extack); |
| @@ -1191,6 +1191,7 @@ br_multicast_ctx_options_equal(const struct net_bridge_mcast *brmctx1, · 307 unmodified lines | ||
| 1191 | 1191 | brmctx1->multicast_startup_query_interval == |
| 1192 | 1192 | brmctx2->multicast_startup_query_interval && |
| 1193 | 1193 | brmctx1->multicast_querier == brmctx2->multicast_querier && |
| 1194 | + brmctx1->multicast_router == brmctx2->multicast_router && | |
| 1194 | 1195 | #if IS_ENABLED(CONFIG_IPV6) |
| 1195 | 1196 | brmctx1->multicast_mld_version == |
| 1196 | 1197 | brmctx2->multicast_mld_version && |
| @@ -390,7 +390,7 @@ static ssize_t multicast_router_show(struct device *d, · 389 unmodified lines | ||
| 390 | 390 | static int set_multicast_router(struct net_bridge *br, unsigned long val, |
| 391 | 391 | struct netlink_ext_ack *extack) |
| 392 | 392 | { |
| 393 | − return br_multicast_set_router(br, val); | |
| 393 | + return br_multicast_set_router(&br->multicast_ctx, val); | |
| 394 | 394 | } |
| 395 | 395 | |
| 396 | 396 | static ssize_t multicast_router_store(struct device *d, |
| @@ -296,7 +296,9 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range, · 295 unmodified lines | ||
| 296 | 296 | nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, |
| 297 | 297 | v_opts->br_mcast_ctx.multicast_startup_query_count) || |
| 298 | 298 | nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, |
| 299 | − v_opts->br_mcast_ctx.multicast_querier)) | |
| 299 | + v_opts->br_mcast_ctx.multicast_querier) || | |
| 300 | + nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_ROUTER, | |
| 301 | + v_opts->br_mcast_ctx.multicast_router)) | |
| 300 | 302 | goto out_err; |
| 301 | 303 | |
| 302 | 304 | clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_last_member_interval); |
| @@ -358,6 +360,7 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(void) · 55 unmodified lines | ||
| 358 | 360 | + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */ |
| 359 | 361 | + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */ |
| 360 | 362 | + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */ |
| 363 | + + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER */ | |
| 361 | 364 | #endif |
| 362 | 365 | + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */ |
| 363 | 366 | } |
| @@ -497,6 +500,15 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br, · 133 unmodified lines | ||
| 497 | 500 | return err; |
| 498 | 501 | *changed = true; |
| 499 | 502 | } |
| 503 | + if (tb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER]) { | |
| 504 | + u8 val; | |
| 505 | + | |
| 506 | + val = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER]); | |
| 507 | + err = br_multicast_set_router(&v->br_mcast_ctx, val); | |
| 508 | + if (err) | |
| 509 | + return err; | |
| 510 | + *changed = true; | |
| 511 | + } | |
| 500 | 512 | #if IS_ENABLED(CONFIG_IPV6) |
| 501 | 513 | if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) { |
| 502 | 514 | u8 ver; |
| @@ -520,6 +532,7 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = { · 17 unmodified lines | ||
| 520 | 532 | [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 }, |
| 521 | 533 | [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 }, |
| 522 | 534 | [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 }, |
| 535 | + [BRIDGE_VLANDB_GOPTS_MCAST_ROUTER] = { .type = NLA_U8 }, | |
| 523 | 536 | [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, |
| 524 | 537 | [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 }, |
| 525 | 538 | [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 }, |