summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMike Manning <mmanning@vyatta.att-mail.com>2019-04-18 13:35:35 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-19 16:58:17 -0400
commit8e1acd4fc552f5590e9d5ff6e5cb5eeafd638d30 (patch)
treeba9d30159bb848eb705fa8d3c88e31b819e3921f /net
parent80900acd3a30ed32d65ec591ded5d527d6ba373f (diff)
bridge: update vlan dev link state for bridge netdev changes
If vlan bridge binding is enabled, then the link state of a vlan device that is an upper device of the bridge tracks the state of bridge ports that are members of that vlan. But this can only be done when the link state of the bridge is up. If it is down, then the link state of the vlan devices must also be down. This is to maintain existing behavior for when STP is enabled and there are no live ports, in which case the link state for the bridge and any vlan devices is down. Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com> Acked-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_vlan.c50
1 files changed, 47 insertions, 3 deletions
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 89146a5f0c23..2db63997f313 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1343,6 +1343,11 @@ static void br_vlan_set_vlan_dev_state(const struct net_bridge *br,
1343 struct net_bridge_port *p; 1343 struct net_bridge_port *p;
1344 bool has_carrier = false; 1344 bool has_carrier = false;
1345 1345
1346 if (!netif_carrier_ok(br->dev)) {
1347 netif_carrier_off(vlan_dev);
1348 return;
1349 }
1350
1346 list_for_each_entry(p, &br->port_list, list) { 1351 list_for_each_entry(p, &br->port_list, list) {
1347 vg = nbp_vlan_group(p); 1352 vg = nbp_vlan_group(p);
1348 if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) { 1353 if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) {
@@ -1367,10 +1372,12 @@ static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p)
1367 vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, 1372 vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev,
1368 vlan->vid); 1373 vlan->vid);
1369 if (vlan_dev) { 1374 if (vlan_dev) {
1370 if (br_vlan_is_dev_up(p->dev)) 1375 if (br_vlan_is_dev_up(p->dev)) {
1371 netif_carrier_on(vlan_dev); 1376 if (netif_carrier_ok(p->br->dev))
1372 else 1377 netif_carrier_on(vlan_dev);
1378 } else {
1373 br_vlan_set_vlan_dev_state(p->br, vlan_dev); 1379 br_vlan_set_vlan_dev_state(p->br, vlan_dev);
1380 }
1374 } 1381 }
1375 } 1382 }
1376} 1383}
@@ -1393,6 +1400,34 @@ static void br_vlan_upper_change(struct net_device *dev,
1393 } 1400 }
1394} 1401}
1395 1402
1403struct br_vlan_link_state_walk_data {
1404 struct net_bridge *br;
1405};
1406
1407static int br_vlan_link_state_change_fn(struct net_device *vlan_dev,
1408 void *data_in)
1409{
1410 struct br_vlan_link_state_walk_data *data = data_in;
1411
1412 if (br_vlan_is_bind_vlan_dev(vlan_dev))
1413 br_vlan_set_vlan_dev_state(data->br, vlan_dev);
1414
1415 return 0;
1416}
1417
1418static void br_vlan_link_state_change(struct net_device *dev,
1419 struct net_bridge *br)
1420{
1421 struct br_vlan_link_state_walk_data data = {
1422 .br = br
1423 };
1424
1425 rcu_read_lock();
1426 netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn,
1427 &data);
1428 rcu_read_unlock();
1429}
1430
1396/* Must be protected by RTNL. */ 1431/* Must be protected by RTNL. */
1397static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) 1432static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid)
1398{ 1433{
@@ -1411,12 +1446,21 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event,
1411 void *ptr) 1446 void *ptr)
1412{ 1447{
1413 struct netdev_notifier_changeupper_info *info; 1448 struct netdev_notifier_changeupper_info *info;
1449 struct net_bridge *br;
1414 1450
1415 switch (event) { 1451 switch (event) {
1416 case NETDEV_CHANGEUPPER: 1452 case NETDEV_CHANGEUPPER:
1417 info = ptr; 1453 info = ptr;
1418 br_vlan_upper_change(dev, info->upper_dev, info->linking); 1454 br_vlan_upper_change(dev, info->upper_dev, info->linking);
1419 break; 1455 break;
1456
1457 case NETDEV_CHANGE:
1458 case NETDEV_UP:
1459 br = netdev_priv(dev);
1460 if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING))
1461 return;
1462 br_vlan_link_state_change(dev, br);
1463 break;
1420 } 1464 }
1421} 1465}
1422 1466