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

net: bridge: mcast: add rt_protocol field to the port group struct

We need to be able to differentiate between pg entries created by
user-space and the kernel when we start generating S,G entries for
IGMPv3/MLDv2's fast path. User-space entries are created by default as
RTPROT_STATIC and the kernel entries are RTPROT_KERNEL. Later we can
allow user-space to provide the entry rt_protocol so we can
differentiate between who added the entries specifically (e.g. clag,
admin, frr etc).
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7d07a68c
...@@ -458,6 +458,7 @@ enum { ...@@ -458,6 +458,7 @@ enum {
MDBA_MDB_EATTR_SRC_LIST, MDBA_MDB_EATTR_SRC_LIST,
MDBA_MDB_EATTR_GROUP_MODE, MDBA_MDB_EATTR_GROUP_MODE,
MDBA_MDB_EATTR_SOURCE, MDBA_MDB_EATTR_SOURCE,
MDBA_MDB_EATTR_RTPROT,
__MDBA_MDB_EATTR_MAX __MDBA_MDB_EATTR_MAX
}; };
#define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) #define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1)
......
...@@ -184,6 +184,7 @@ static int __mdb_fill_info(struct sk_buff *skb, ...@@ -184,6 +184,7 @@ static int __mdb_fill_info(struct sk_buff *skb,
MDBA_MDB_EATTR_TIMER, MDBA_MDB_EATTR_TIMER,
br_timer_value(mtimer))) br_timer_value(mtimer)))
goto nest_err; goto nest_err;
switch (mp->addr.proto) { switch (mp->addr.proto) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
dump_srcs_mode = !!(mp->br->multicast_igmp_version == 3); dump_srcs_mode = !!(mp->br->multicast_igmp_version == 3);
...@@ -206,10 +207,15 @@ static int __mdb_fill_info(struct sk_buff *skb, ...@@ -206,10 +207,15 @@ static int __mdb_fill_info(struct sk_buff *skb,
break; break;
#endif #endif
} }
if (p && dump_srcs_mode && if (p) {
(__mdb_fill_srcs(skb, p) || if (nla_put_u8(skb, MDBA_MDB_EATTR_RTPROT, p->rt_protocol))
nla_put_u8(skb, MDBA_MDB_EATTR_GROUP_MODE, p->filter_mode))) goto nest_err;
goto nest_err; if (dump_srcs_mode &&
(__mdb_fill_srcs(skb, p) ||
nla_put_u8(skb, MDBA_MDB_EATTR_GROUP_MODE,
p->filter_mode)))
goto nest_err;
}
nla_nest_end(skb, nest_ent); nla_nest_end(skb, nest_ent);
return 0; return 0;
...@@ -414,6 +420,9 @@ static size_t rtnl_mdb_nlmsg_size(struct net_bridge_port_group *pg) ...@@ -414,6 +420,9 @@ static size_t rtnl_mdb_nlmsg_size(struct net_bridge_port_group *pg)
if (!pg) if (!pg)
goto out; goto out;
/* MDBA_MDB_EATTR_RTPROT */
nlmsg_size += nla_total_size(sizeof(u8));
switch (pg->addr.proto) { switch (pg->addr.proto) {
case htons(ETH_P_IP): case htons(ETH_P_IP):
/* MDBA_MDB_EATTR_SOURCE */ /* MDBA_MDB_EATTR_SOURCE */
...@@ -809,16 +818,20 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -809,16 +818,20 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh,
} }
static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
struct br_ip *group, struct br_mdb_entry *entry, struct br_mdb_entry *entry,
struct nlattr **mdb_attrs,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct net_bridge_mdb_entry *mp; struct net_bridge_mdb_entry *mp;
struct net_bridge_port_group *p; struct net_bridge_port_group *p;
struct net_bridge_port_group __rcu **pp; struct net_bridge_port_group __rcu **pp;
unsigned long now = jiffies; unsigned long now = jiffies;
struct br_ip group;
u8 filter_mode; u8 filter_mode;
int err; int err;
__mdb_entry_to_br_ip(entry, &group, mdb_attrs);
/* host join errors which can happen before creating the group */ /* host join errors which can happen before creating the group */
if (!port) { if (!port) {
/* don't allow any flags for host-joined groups */ /* don't allow any flags for host-joined groups */
...@@ -826,15 +839,15 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, ...@@ -826,15 +839,15 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
NL_SET_ERR_MSG_MOD(extack, "Flags are not allowed for host groups"); NL_SET_ERR_MSG_MOD(extack, "Flags are not allowed for host groups");
return -EINVAL; return -EINVAL;
} }
if (!br_multicast_is_star_g(group)) { if (!br_multicast_is_star_g(&group)) {
NL_SET_ERR_MSG_MOD(extack, "Groups with sources cannot be manually host joined"); NL_SET_ERR_MSG_MOD(extack, "Groups with sources cannot be manually host joined");
return -EINVAL; return -EINVAL;
} }
} }
mp = br_mdb_ip_get(br, group); mp = br_mdb_ip_get(br, &group);
if (!mp) { if (!mp) {
mp = br_multicast_new_group(br, group); mp = br_multicast_new_group(br, &group);
err = PTR_ERR_OR_ZERO(mp); err = PTR_ERR_OR_ZERO(mp);
if (err) if (err)
return err; return err;
...@@ -864,11 +877,11 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, ...@@ -864,11 +877,11 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
break; break;
} }
filter_mode = br_multicast_is_star_g(group) ? MCAST_EXCLUDE : filter_mode = br_multicast_is_star_g(&group) ? MCAST_EXCLUDE :
MCAST_INCLUDE; MCAST_INCLUDE;
p = br_multicast_new_port_group(port, group, *pp, entry->state, NULL, p = br_multicast_new_port_group(port, &group, *pp, entry->state, NULL,
filter_mode); filter_mode, RTPROT_STATIC);
if (unlikely(!p)) { if (unlikely(!p)) {
NL_SET_ERR_MSG_MOD(extack, "Couldn't allocate new port group"); NL_SET_ERR_MSG_MOD(extack, "Couldn't allocate new port group");
return -ENOMEM; return -ENOMEM;
...@@ -887,13 +900,10 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, ...@@ -887,13 +900,10 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
struct nlattr **mdb_attrs, struct nlattr **mdb_attrs,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct br_ip ip;
int ret; int ret;
__mdb_entry_to_br_ip(entry, &ip, mdb_attrs);
spin_lock_bh(&br->multicast_lock); spin_lock_bh(&br->multicast_lock);
ret = br_mdb_add_group(br, p, &ip, entry, extack); ret = br_mdb_add_group(br, p, entry, mdb_attrs, extack);
spin_unlock_bh(&br->multicast_lock); spin_unlock_bh(&br->multicast_lock);
return ret; return ret;
......
...@@ -795,7 +795,8 @@ struct net_bridge_port_group *br_multicast_new_port_group( ...@@ -795,7 +795,8 @@ struct net_bridge_port_group *br_multicast_new_port_group(
struct net_bridge_port_group __rcu *next, struct net_bridge_port_group __rcu *next,
unsigned char flags, unsigned char flags,
const unsigned char *src, const unsigned char *src,
u8 filter_mode) u8 filter_mode,
u8 rt_protocol)
{ {
struct net_bridge_port_group *p; struct net_bridge_port_group *p;
...@@ -807,6 +808,7 @@ struct net_bridge_port_group *br_multicast_new_port_group( ...@@ -807,6 +808,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
p->port = port; p->port = port;
p->flags = flags; p->flags = flags;
p->filter_mode = filter_mode; p->filter_mode = filter_mode;
p->rt_protocol = rt_protocol;
p->mcast_gc.destroy = br_multicast_destroy_port_group; p->mcast_gc.destroy = br_multicast_destroy_port_group;
INIT_HLIST_HEAD(&p->src_list); INIT_HLIST_HEAD(&p->src_list);
rcu_assign_pointer(p->next, next); rcu_assign_pointer(p->next, next);
...@@ -892,7 +894,8 @@ static int br_multicast_add_group(struct net_bridge *br, ...@@ -892,7 +894,8 @@ static int br_multicast_add_group(struct net_bridge *br,
break; break;
} }
p = br_multicast_new_port_group(port, group, *pp, 0, src, filter_mode); p = br_multicast_new_port_group(port, group, *pp, 0, src, filter_mode,
RTPROT_KERNEL);
if (unlikely(!p)) if (unlikely(!p))
goto err; goto err;
rcu_assign_pointer(*pp, p); rcu_assign_pointer(*pp, p);
......
...@@ -246,6 +246,7 @@ struct net_bridge_port_group { ...@@ -246,6 +246,7 @@ struct net_bridge_port_group {
unsigned char flags; unsigned char flags;
unsigned char filter_mode; unsigned char filter_mode;
unsigned char grp_query_rexmit_cnt; unsigned char grp_query_rexmit_cnt;
unsigned char rt_protocol;
struct hlist_head src_list; struct hlist_head src_list;
unsigned int src_ents; unsigned int src_ents;
...@@ -804,7 +805,7 @@ struct net_bridge_port_group * ...@@ -804,7 +805,7 @@ struct net_bridge_port_group *
br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group,
struct net_bridge_port_group __rcu *next, struct net_bridge_port_group __rcu *next,
unsigned char flags, const unsigned char *src, unsigned char flags, const unsigned char *src,
u8 filter_mode); u8 filter_mode, u8 rt_protocol);
int br_mdb_hash_init(struct net_bridge *br); int br_mdb_hash_init(struct net_bridge *br);
void br_mdb_hash_fini(struct net_bridge *br); void br_mdb_hash_fini(struct net_bridge *br);
void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp, void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp,
......
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