forked from mirrors/linux
		
	bridge: add flags to distinguish permanent mdb entires
This patch adds a flag to each mdb entry, so that we can distinguish permanent entries with temporary entries. Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Stephen Hemminger <shemminger@vyatta.com> Cc: "David S. Miller" <davem@davemloft.net> Signed-off-by: Cong Wang <amwang@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									9dd9ff9953
								
							
						
					
					
						commit
						ccb1c31a7a
					
				
					 4 changed files with 17 additions and 7 deletions
				
			
		| 
						 | 
					@ -163,6 +163,9 @@ struct br_port_msg {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct br_mdb_entry {
 | 
					struct br_mdb_entry {
 | 
				
			||||||
	__u32 ifindex;
 | 
						__u32 ifindex;
 | 
				
			||||||
 | 
					#define MDB_TEMPORARY 0
 | 
				
			||||||
 | 
					#define MDB_PERMANENT 1
 | 
				
			||||||
 | 
						__u8 state;
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		union {
 | 
							union {
 | 
				
			||||||
			__be32	ip4;
 | 
								__be32	ip4;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
 | 
				
			||||||
				if (port) {
 | 
									if (port) {
 | 
				
			||||||
					struct br_mdb_entry e;
 | 
										struct br_mdb_entry e;
 | 
				
			||||||
					e.ifindex = port->dev->ifindex;
 | 
										e.ifindex = port->dev->ifindex;
 | 
				
			||||||
 | 
										e.state = p->state;
 | 
				
			||||||
					e.addr.u.ip4 = p->addr.u.ip4;
 | 
										e.addr.u.ip4 = p->addr.u.ip4;
 | 
				
			||||||
#if IS_ENABLED(CONFIG_IPV6)
 | 
					#if IS_ENABLED(CONFIG_IPV6)
 | 
				
			||||||
					e.addr.u.ip6 = p->addr.u.ip6;
 | 
										e.addr.u.ip6 = p->addr.u.ip6;
 | 
				
			||||||
| 
						 | 
					@ -253,6 +254,8 @@ static bool is_valid_mdb_entry(struct br_mdb_entry *entry)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
 | 
						if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -310,7 +313,7 @@ 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_ip *group, unsigned char state)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_bridge_mdb_entry *mp;
 | 
						struct net_bridge_mdb_entry *mp;
 | 
				
			||||||
	struct net_bridge_port_group *p;
 | 
						struct net_bridge_port_group *p;
 | 
				
			||||||
| 
						 | 
					@ -336,7 +339,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p = br_multicast_new_port_group(port, group, *pp);
 | 
						p = br_multicast_new_port_group(port, group, *pp, state);
 | 
				
			||||||
	if (unlikely(!p))
 | 
						if (unlikely(!p))
 | 
				
			||||||
		return -ENOMEM;
 | 
							return -ENOMEM;
 | 
				
			||||||
	rcu_assign_pointer(*pp, p);
 | 
						rcu_assign_pointer(*pp, p);
 | 
				
			||||||
| 
						 | 
					@ -373,7 +376,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock_bh(&br->multicast_lock);
 | 
						spin_lock_bh(&br->multicast_lock);
 | 
				
			||||||
	ret = br_mdb_add_group(br, p, &ip);
 | 
						ret = br_mdb_add_group(br, p, &ip, entry->state);
 | 
				
			||||||
	spin_unlock_bh(&br->multicast_lock);
 | 
						spin_unlock_bh(&br->multicast_lock);
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -279,7 +279,7 @@ static void br_multicast_port_group_expired(unsigned long data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spin_lock(&br->multicast_lock);
 | 
						spin_lock(&br->multicast_lock);
 | 
				
			||||||
	if (!netif_running(br->dev) || timer_pending(&pg->timer) ||
 | 
						if (!netif_running(br->dev) || timer_pending(&pg->timer) ||
 | 
				
			||||||
	    hlist_unhashed(&pg->mglist))
 | 
						    hlist_unhashed(&pg->mglist) || pg->state & MDB_PERMANENT)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	br_multicast_del_pg(br, pg);
 | 
						br_multicast_del_pg(br, pg);
 | 
				
			||||||
| 
						 | 
					@ -622,7 +622,8 @@ struct net_bridge_mdb_entry *br_multicast_new_group(struct net_bridge *br,
 | 
				
			||||||
struct net_bridge_port_group *br_multicast_new_port_group(
 | 
					struct net_bridge_port_group *br_multicast_new_port_group(
 | 
				
			||||||
			struct net_bridge_port *port,
 | 
								struct net_bridge_port *port,
 | 
				
			||||||
			struct br_ip *group,
 | 
								struct br_ip *group,
 | 
				
			||||||
			struct net_bridge_port_group __rcu *next)
 | 
								struct net_bridge_port_group __rcu *next,
 | 
				
			||||||
 | 
								unsigned char state)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct net_bridge_port_group *p;
 | 
						struct net_bridge_port_group *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -632,6 +633,7 @@ struct net_bridge_port_group *br_multicast_new_port_group(
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p->addr = *group;
 | 
						p->addr = *group;
 | 
				
			||||||
	p->port = port;
 | 
						p->port = port;
 | 
				
			||||||
 | 
						p->state = state;
 | 
				
			||||||
	rcu_assign_pointer(p->next, next);
 | 
						rcu_assign_pointer(p->next, next);
 | 
				
			||||||
	hlist_add_head(&p->mglist, &port->mglist);
 | 
						hlist_add_head(&p->mglist, &port->mglist);
 | 
				
			||||||
	setup_timer(&p->timer, br_multicast_port_group_expired,
 | 
						setup_timer(&p->timer, br_multicast_port_group_expired,
 | 
				
			||||||
| 
						 | 
					@ -674,7 +676,7 @@ static int br_multicast_add_group(struct net_bridge *br,
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p = br_multicast_new_port_group(port, group, *pp);
 | 
						p = br_multicast_new_port_group(port, group, *pp, MDB_TEMPORARY);
 | 
				
			||||||
	if (unlikely(!p))
 | 
						if (unlikely(!p))
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
	rcu_assign_pointer(*pp, p);
 | 
						rcu_assign_pointer(*pp, p);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,7 @@ struct net_bridge_port_group {
 | 
				
			||||||
	struct rcu_head			rcu;
 | 
						struct rcu_head			rcu;
 | 
				
			||||||
	struct timer_list		timer;
 | 
						struct timer_list		timer;
 | 
				
			||||||
	struct br_ip			addr;
 | 
						struct br_ip			addr;
 | 
				
			||||||
 | 
						unsigned char			state;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct net_bridge_mdb_entry
 | 
					struct net_bridge_mdb_entry
 | 
				
			||||||
| 
						 | 
					@ -443,7 +444,8 @@ extern void br_multicast_free_pg(struct rcu_head *head);
 | 
				
			||||||
extern struct net_bridge_port_group *br_multicast_new_port_group(
 | 
					extern struct net_bridge_port_group *br_multicast_new_port_group(
 | 
				
			||||||
				struct net_bridge_port *port,
 | 
									struct net_bridge_port *port,
 | 
				
			||||||
				struct br_ip *group,
 | 
									struct br_ip *group,
 | 
				
			||||||
				struct net_bridge_port_group *next);
 | 
									struct net_bridge_port_group *next,
 | 
				
			||||||
 | 
									unsigned char state);
 | 
				
			||||||
extern void br_mdb_init(void);
 | 
					extern void br_mdb_init(void);
 | 
				
			||||||
extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 | 
					extern void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 | 
				
			||||||
			  struct br_ip *group, int type);
 | 
								  struct br_ip *group, int type);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue