Skip to content

Commit faa1cd8

Browse files
Nikolay Aleksandrovdavem330
authored andcommitted
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>
1 parent 2e51855 commit faa1cd8

File tree

3 files changed

+17
-8
lines changed

3 files changed

+17
-8
lines changed

net/bridge/br.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
3434
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
3535
struct net_bridge_port *p;
3636
struct net_bridge *br;
37+
bool notified = false;
3738
bool changed_addr;
3839
int err;
3940

@@ -67,7 +68,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
6768
break;
6869

6970
case NETDEV_CHANGE:
70-
br_port_carrier_check(p);
71+
br_port_carrier_check(p, &notified);
7172
break;
7273

7374
case NETDEV_FEAT_CHANGE:
@@ -76,15 +77,18 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
7677

7778
case NETDEV_DOWN:
7879
spin_lock_bh(&br->lock);
79-
if (br->dev->flags & IFF_UP)
80+
if (br->dev->flags & IFF_UP) {
8081
br_stp_disable_port(p);
82+
notified = true;
83+
}
8184
spin_unlock_bh(&br->lock);
8285
break;
8386

8487
case NETDEV_UP:
8588
if (netif_running(br->dev) && netif_oper_up(dev)) {
8689
spin_lock_bh(&br->lock);
8790
br_stp_enable_port(p);
91+
notified = true;
8892
spin_unlock_bh(&br->lock);
8993
}
9094
break;
@@ -110,8 +114,8 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
110114
}
111115

112116
/* Events that may cause spanning tree to refresh */
113-
if (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
114-
event == NETDEV_CHANGE || event == NETDEV_DOWN)
117+
if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
118+
event == NETDEV_CHANGE || event == NETDEV_DOWN))
115119
br_ifinfo_notify(RTM_NEWLINK, NULL, p);
116120

117121
return NOTIFY_DONE;

net/bridge/br_if.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ static int port_cost(struct net_device *dev)
6464

6565

6666
/* Check for port carrier transitions. */
67-
void br_port_carrier_check(struct net_bridge_port *p)
67+
void br_port_carrier_check(struct net_bridge_port *p, bool *notified)
6868
{
6969
struct net_device *dev = p->dev;
7070
struct net_bridge *br = p->br;
@@ -73,16 +73,21 @@ void br_port_carrier_check(struct net_bridge_port *p)
7373
netif_running(dev) && netif_oper_up(dev))
7474
p->path_cost = port_cost(dev);
7575

76+
*notified = false;
7677
if (!netif_running(br->dev))
7778
return;
7879

7980
spin_lock_bh(&br->lock);
8081
if (netif_running(dev) && netif_oper_up(dev)) {
81-
if (p->state == BR_STATE_DISABLED)
82+
if (p->state == BR_STATE_DISABLED) {
8283
br_stp_enable_port(p);
84+
*notified = true;
85+
}
8386
} else {
84-
if (p->state != BR_STATE_DISABLED)
87+
if (p->state != BR_STATE_DISABLED) {
8588
br_stp_disable_port(p);
89+
*notified = true;
90+
}
8691
}
8792
spin_unlock_bh(&br->lock);
8893
}

net/bridge/br_private.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
573573
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig);
574574

575575
/* br_if.c */
576-
void br_port_carrier_check(struct net_bridge_port *p);
576+
void br_port_carrier_check(struct net_bridge_port *p, bool *notified);
577577
int br_add_bridge(struct net *net, const char *name);
578578
int br_del_bridge(struct net *net, const char *name);
579579
int br_add_if(struct net_bridge *br, struct net_device *dev,

0 commit comments

Comments
 (0)