mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
net: bridge: avoid duplicate notification on up/down/change netdev events
While handling netdevice events, br_device_event() sometimes uses br_stp_(disable|enable)_port which unconditionally send a notification, but then a second notification for the same event is sent at the end of the br_device_event() function. To avoid sending duplicate notifications in such cases, check if one has already been sent (i.e. br_stp_enable/disable_port have been called). The patch is based on a change by Satish Ashok. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2e51855194
commit
faa1cd8298
@ -34,6 +34,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct net_bridge_port *p;
|
||||
struct net_bridge *br;
|
||||
bool notified = false;
|
||||
bool changed_addr;
|
||||
int err;
|
||||
|
||||
@ -67,7 +68,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||
break;
|
||||
|
||||
case NETDEV_CHANGE:
|
||||
br_port_carrier_check(p);
|
||||
br_port_carrier_check(p, ¬ified);
|
||||
break;
|
||||
|
||||
case NETDEV_FEAT_CHANGE:
|
||||
@ -76,8 +77,10 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||
|
||||
case NETDEV_DOWN:
|
||||
spin_lock_bh(&br->lock);
|
||||
if (br->dev->flags & IFF_UP)
|
||||
if (br->dev->flags & IFF_UP) {
|
||||
br_stp_disable_port(p);
|
||||
notified = true;
|
||||
}
|
||||
spin_unlock_bh(&br->lock);
|
||||
break;
|
||||
|
||||
@ -85,6 +88,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||
if (netif_running(br->dev) && netif_oper_up(dev)) {
|
||||
spin_lock_bh(&br->lock);
|
||||
br_stp_enable_port(p);
|
||||
notified = true;
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
break;
|
||||
@ -110,8 +114,8 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
|
||||
}
|
||||
|
||||
/* Events that may cause spanning tree to refresh */
|
||||
if (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
|
||||
event == NETDEV_CHANGE || event == NETDEV_DOWN)
|
||||
if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
|
||||
event == NETDEV_CHANGE || event == NETDEV_DOWN))
|
||||
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
|
@ -64,7 +64,7 @@ static int port_cost(struct net_device *dev)
|
||||
|
||||
|
||||
/* Check for port carrier transitions. */
|
||||
void br_port_carrier_check(struct net_bridge_port *p)
|
||||
void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
|
||||
{
|
||||
struct net_device *dev = p->dev;
|
||||
struct net_bridge *br = p->br;
|
||||
@ -73,16 +73,21 @@ void br_port_carrier_check(struct net_bridge_port *p)
|
||||
netif_running(dev) && netif_oper_up(dev))
|
||||
p->path_cost = port_cost(dev);
|
||||
|
||||
*notified = false;
|
||||
if (!netif_running(br->dev))
|
||||
return;
|
||||
|
||||
spin_lock_bh(&br->lock);
|
||||
if (netif_running(dev) && netif_oper_up(dev)) {
|
||||
if (p->state == BR_STATE_DISABLED)
|
||||
if (p->state == BR_STATE_DISABLED) {
|
||||
br_stp_enable_port(p);
|
||||
*notified = true;
|
||||
}
|
||||
} else {
|
||||
if (p->state != BR_STATE_DISABLED)
|
||||
if (p->state != BR_STATE_DISABLED) {
|
||||
br_stp_disable_port(p);
|
||||
*notified = true;
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
|
@ -573,7 +573,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
|
||||
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig);
|
||||
|
||||
/* br_if.c */
|
||||
void br_port_carrier_check(struct net_bridge_port *p);
|
||||
void br_port_carrier_check(struct net_bridge_port *p, bool *notified);
|
||||
int br_add_bridge(struct net *net, const char *name);
|
||||
int br_del_bridge(struct net *net, const char *name);
|
||||
int br_add_if(struct net_bridge *br, struct net_device *dev,
|
||||
|
Loading…
Reference in New Issue
Block a user