Commit a97df080 authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: bridge: vlan: add support for mcast router global option

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.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 62938182
...@@ -561,6 +561,7 @@ enum { ...@@ -561,6 +561,7 @@ enum {
BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL, BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
BRIDGE_VLANDB_GOPTS_MCAST_ROUTER,
__BRIDGE_VLANDB_GOPTS_MAX __BRIDGE_VLANDB_GOPTS_MAX
}; };
#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
......
...@@ -4053,17 +4053,16 @@ void br_multicast_dev_del(struct net_bridge *br) ...@@ -4053,17 +4053,16 @@ void br_multicast_dev_del(struct net_bridge *br)
rcu_barrier(); rcu_barrier();
} }
int br_multicast_set_router(struct net_bridge *br, unsigned long val) int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val)
{ {
struct net_bridge_mcast *brmctx = &br->multicast_ctx;
int err = -EINVAL; int err = -EINVAL;
spin_lock_bh(&br->multicast_lock); spin_lock_bh(&brmctx->br->multicast_lock);
switch (val) { switch (val) {
case MDB_RTR_TYPE_DISABLED: case MDB_RTR_TYPE_DISABLED:
case MDB_RTR_TYPE_PERM: case MDB_RTR_TYPE_PERM:
br_mc_router_state_change(br, val == MDB_RTR_TYPE_PERM); br_mc_router_state_change(brmctx->br, val == MDB_RTR_TYPE_PERM);
del_timer(&brmctx->ip4_mc_router_timer); del_timer(&brmctx->ip4_mc_router_timer);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
del_timer(&brmctx->ip6_mc_router_timer); del_timer(&brmctx->ip6_mc_router_timer);
...@@ -4073,13 +4072,13 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) ...@@ -4073,13 +4072,13 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val)
break; break;
case MDB_RTR_TYPE_TEMP_QUERY: case MDB_RTR_TYPE_TEMP_QUERY:
if (brmctx->multicast_router != MDB_RTR_TYPE_TEMP_QUERY) if (brmctx->multicast_router != MDB_RTR_TYPE_TEMP_QUERY)
br_mc_router_state_change(br, false); br_mc_router_state_change(brmctx->br, false);
brmctx->multicast_router = val; brmctx->multicast_router = val;
err = 0; err = 0;
break; break;
} }
spin_unlock_bh(&br->multicast_lock); spin_unlock_bh(&brmctx->br->multicast_lock);
return err; return err;
} }
......
...@@ -1286,7 +1286,8 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], ...@@ -1286,7 +1286,8 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
if (data[IFLA_BR_MCAST_ROUTER]) { if (data[IFLA_BR_MCAST_ROUTER]) {
u8 multicast_router = nla_get_u8(data[IFLA_BR_MCAST_ROUTER]); u8 multicast_router = nla_get_u8(data[IFLA_BR_MCAST_ROUTER]);
err = br_multicast_set_router(br, multicast_router); err = br_multicast_set_router(&br->multicast_ctx,
multicast_router);
if (err) if (err)
return err; return err;
} }
......
...@@ -877,7 +877,7 @@ void br_multicast_dev_del(struct net_bridge *br); ...@@ -877,7 +877,7 @@ void br_multicast_dev_del(struct net_bridge *br);
void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb, void br_multicast_flood(struct net_bridge_mdb_entry *mdst, struct sk_buff *skb,
struct net_bridge_mcast *brmctx, struct net_bridge_mcast *brmctx,
bool local_rcv, bool local_orig); bool local_rcv, bool local_orig);
int br_multicast_set_router(struct net_bridge *br, unsigned long val); int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val);
int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val); int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val);
int br_multicast_toggle(struct net_bridge *br, unsigned long val, int br_multicast_toggle(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
...@@ -1191,6 +1191,7 @@ br_multicast_ctx_options_equal(const struct net_bridge_mcast *brmctx1, ...@@ -1191,6 +1191,7 @@ br_multicast_ctx_options_equal(const struct net_bridge_mcast *brmctx1,
brmctx1->multicast_startup_query_interval == brmctx1->multicast_startup_query_interval ==
brmctx2->multicast_startup_query_interval && brmctx2->multicast_startup_query_interval &&
brmctx1->multicast_querier == brmctx2->multicast_querier && brmctx1->multicast_querier == brmctx2->multicast_querier &&
brmctx1->multicast_router == brmctx2->multicast_router &&
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
brmctx1->multicast_mld_version == brmctx1->multicast_mld_version ==
brmctx2->multicast_mld_version && brmctx2->multicast_mld_version &&
......
...@@ -390,7 +390,7 @@ static ssize_t multicast_router_show(struct device *d, ...@@ -390,7 +390,7 @@ static ssize_t multicast_router_show(struct device *d,
static int set_multicast_router(struct net_bridge *br, unsigned long val, static int set_multicast_router(struct net_bridge *br, unsigned long val,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
return br_multicast_set_router(br, val); return br_multicast_set_router(&br->multicast_ctx, val);
} }
static ssize_t multicast_router_store(struct device *d, 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, ...@@ -296,7 +296,9 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, nla_put_u32(skb, BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
v_opts->br_mcast_ctx.multicast_startup_query_count) || v_opts->br_mcast_ctx.multicast_startup_query_count) ||
nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
v_opts->br_mcast_ctx.multicast_querier)) v_opts->br_mcast_ctx.multicast_querier) ||
nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_ROUTER,
v_opts->br_mcast_ctx.multicast_router))
goto out_err; goto out_err;
clockval = jiffies_to_clock_t(v_opts->br_mcast_ctx.multicast_last_member_interval); 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) ...@@ -358,6 +360,7 @@ static size_t rtnl_vlan_global_opts_nlmsg_size(void)
+ nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */ + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL */
+ nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */ + nla_total_size(sizeof(u64)) /* BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL */
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */ + nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_QUERIER */
+ nla_total_size(sizeof(u8)) /* BRIDGE_VLANDB_GOPTS_MCAST_ROUTER */
#endif #endif
+ nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */ + nla_total_size(sizeof(u16)); /* BRIDGE_VLANDB_GOPTS_RANGE */
} }
...@@ -497,6 +500,15 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br, ...@@ -497,6 +500,15 @@ static int br_vlan_process_global_one_opts(const struct net_bridge *br,
return err; return err;
*changed = true; *changed = true;
} }
if (tb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER]) {
u8 val;
val = nla_get_u8(tb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER]);
err = br_multicast_set_router(&v->br_mcast_ctx, val);
if (err)
return err;
*changed = true;
}
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) { if (tb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
u8 ver; u8 ver;
...@@ -520,6 +532,7 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = { ...@@ -520,6 +532,7 @@ static const struct nla_policy br_vlan_db_gpol[BRIDGE_VLANDB_GOPTS_MAX + 1] = {
[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 }, [BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION] = { .type = NLA_U8 },
[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL] = { .type = NLA_U64 },
[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 }, [BRIDGE_VLANDB_GOPTS_MCAST_QUERIER] = { .type = NLA_U8 },
[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER] = { .type = NLA_U8 },
[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] = { .type = NLA_U8 }, [BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION] = { .type = NLA_U8 },
[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 }, [BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT] = { .type = NLA_U32 },
[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 }, [BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT] = { .type = NLA_U32 },
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment