Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-support-binding-vlan-dev-link-state-to-vlan-member-bridge-ports'

Mike Manning says:

====================
net: support binding vlan dev link state to vlan member bridge ports

For vlan filtering on bridges, the bridge may also have vlan devices
as upper devices. For switches, these are used to provide L3 packet
processing for ports that are members of a given vlan.

While it is correct that the admin state for these vlan devices is
either set directly for the device or inherited from the lower device,
the link state is also transferred from the lower device. So this is
always up if the bridge is in admin up state and there is at least one
bridge port that is up, regardless of the vlan that the port is in.

The link state of the vlan device may need to track only the state of
the subset of ports that are also members of the corresponding vlan,
rather than that of all ports.

This series provides an optional vlan flag so that the link state of
the vlan device is only up if there is at least one bridge port that is
up AND is a member of the corresponding vlan.

v2:
- Address review comments from Nikolay Aleksandrov
in patches 3 & 4 and add patch 5 to address bridge link down due to STP
v3:
- Address review comment from Nikolay Aleksandrov
in patch 4 so as to remove unnecessary inline #ifdef
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+272 -21
+5 -4
include/uapi/linux/if_vlan.h
··· 32 32 }; 33 33 34 34 enum vlan_flags { 35 - VLAN_FLAG_REORDER_HDR = 0x1, 36 - VLAN_FLAG_GVRP = 0x2, 37 - VLAN_FLAG_LOOSE_BINDING = 0x4, 38 - VLAN_FLAG_MVRP = 0x8, 35 + VLAN_FLAG_REORDER_HDR = 0x1, 36 + VLAN_FLAG_GVRP = 0x2, 37 + VLAN_FLAG_LOOSE_BINDING = 0x4, 38 + VLAN_FLAG_MVRP = 0x8, 39 + VLAN_FLAG_BRIDGE_BINDING = 0x10, 39 40 }; 40 41 41 42 enum vlan_name_types {
+14 -4
net/8021q/vlan.c
··· 75 75 return 0; 76 76 } 77 77 78 + static void vlan_stacked_transfer_operstate(const struct net_device *rootdev, 79 + struct net_device *dev, 80 + struct vlan_dev_priv *vlan) 81 + { 82 + if (!(vlan->flags & VLAN_FLAG_BRIDGE_BINDING)) 83 + netif_stacked_transfer_operstate(rootdev, dev); 84 + } 85 + 78 86 void unregister_vlan_dev(struct net_device *dev, struct list_head *head) 79 87 { 80 88 struct vlan_dev_priv *vlan = vlan_dev_priv(dev); ··· 188 180 /* Account for reference in struct vlan_dev_priv */ 189 181 dev_hold(real_dev); 190 182 191 - netif_stacked_transfer_operstate(real_dev, dev); 183 + vlan_stacked_transfer_operstate(real_dev, dev, vlan); 192 184 linkwatch_fire_event(dev); /* _MUST_ call rfc2863_policy() */ 193 185 194 186 /* So, got the sucker initialized, now lets place ··· 407 399 case NETDEV_CHANGE: 408 400 /* Propagate real device state to vlan devices */ 409 401 vlan_group_for_each_dev(grp, i, vlandev) 410 - netif_stacked_transfer_operstate(dev, vlandev); 402 + vlan_stacked_transfer_operstate(dev, vlandev, 403 + vlan_dev_priv(vlandev)); 411 404 break; 412 405 413 406 case NETDEV_CHANGEADDR: ··· 455 446 dev_close_many(&close_list, false); 456 447 457 448 list_for_each_entry_safe(vlandev, tmp, &close_list, close_list) { 458 - netif_stacked_transfer_operstate(dev, vlandev); 449 + vlan_stacked_transfer_operstate(dev, vlandev, 450 + vlan_dev_priv(vlandev)); 459 451 list_del_init(&vlandev->close_list); 460 452 } 461 453 list_del(&close_list); ··· 473 463 if (!(vlan->flags & VLAN_FLAG_LOOSE_BINDING)) 474 464 dev_change_flags(vlandev, flgs | IFF_UP, 475 465 extack); 476 - netif_stacked_transfer_operstate(dev, vlandev); 466 + vlan_stacked_transfer_operstate(dev, vlandev, vlan); 477 467 } 478 468 break; 479 469
+14 -8
net/8021q/vlan_dev.c
··· 223 223 u32 old_flags = vlan->flags; 224 224 225 225 if (mask & ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | 226 - VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP)) 226 + VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP | 227 + VLAN_FLAG_BRIDGE_BINDING)) 227 228 return -EINVAL; 228 229 229 230 vlan->flags = (old_flags & ~mask) | (flags & mask); ··· 297 296 if (vlan->flags & VLAN_FLAG_MVRP) 298 297 vlan_mvrp_request_join(dev); 299 298 300 - if (netif_carrier_ok(real_dev)) 299 + if (netif_carrier_ok(real_dev) && 300 + !(vlan->flags & VLAN_FLAG_BRIDGE_BINDING)) 301 301 netif_carrier_on(dev); 302 302 return 0; 303 303 ··· 328 326 if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) 329 327 dev_uc_del(real_dev, dev->dev_addr); 330 328 331 - netif_carrier_off(dev); 329 + if (!(vlan->flags & VLAN_FLAG_BRIDGE_BINDING)) 330 + netif_carrier_off(dev); 332 331 return 0; 333 332 } 334 333 ··· 553 550 554 551 static int vlan_dev_init(struct net_device *dev) 555 552 { 556 - struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; 553 + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); 554 + struct net_device *real_dev = vlan->real_dev; 557 555 558 556 netif_carrier_off(dev); 559 557 ··· 564 560 dev->state = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) | 565 561 (1<<__LINK_STATE_DORMANT))) | 566 562 (1<<__LINK_STATE_PRESENT); 563 + 564 + if (vlan->flags & VLAN_FLAG_BRIDGE_BINDING) 565 + dev->state |= (1 << __LINK_STATE_NOCARRIER); 567 566 568 567 dev->hw_features = NETIF_F_HW_CSUM | NETIF_F_SG | 569 568 NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | ··· 598 591 #endif 599 592 600 593 dev->needed_headroom = real_dev->needed_headroom; 601 - if (vlan_hw_offload_capable(real_dev->features, 602 - vlan_dev_priv(dev)->vlan_proto)) { 594 + if (vlan_hw_offload_capable(real_dev->features, vlan->vlan_proto)) { 603 595 dev->header_ops = &vlan_passthru_header_ops; 604 596 dev->hard_header_len = real_dev->hard_header_len; 605 597 } else { ··· 612 606 613 607 vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev)); 614 608 615 - vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); 616 - if (!vlan_dev_priv(dev)->vlan_pcpu_stats) 609 + vlan->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); 610 + if (!vlan->vlan_pcpu_stats) 617 611 return -ENOMEM; 618 612 619 613 return 0;
+2 -1
net/8021q/vlan_netlink.c
··· 84 84 flags = nla_data(data[IFLA_VLAN_FLAGS]); 85 85 if ((flags->flags & flags->mask) & 86 86 ~(VLAN_FLAG_REORDER_HDR | VLAN_FLAG_GVRP | 87 - VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP)) { 87 + VLAN_FLAG_LOOSE_BINDING | VLAN_FLAG_MVRP | 88 + VLAN_FLAG_BRIDGE_BINDING)) { 88 89 NL_SET_ERR_MSG_MOD(extack, "Invalid VLAN flags"); 89 90 return -EINVAL; 90 91 }
+9 -4
net/bridge/br.c
··· 40 40 bool changed_addr; 41 41 int err; 42 42 43 - /* register of bridge completed, add sysfs entries */ 44 - if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) { 45 - br_sysfs_addbr(dev); 46 - return NOTIFY_DONE; 43 + if (dev->priv_flags & IFF_EBRIDGE) { 44 + if (event == NETDEV_REGISTER) { 45 + /* register of bridge completed, add sysfs entries */ 46 + br_sysfs_addbr(dev); 47 + return NOTIFY_DONE; 48 + } 49 + br_vlan_bridge_event(dev, event, ptr); 47 50 } 48 51 49 52 /* not a port of a bridge */ ··· 128 125 call_netdevice_notifiers(event, br->dev); 129 126 break; 130 127 } 128 + 129 + br_vlan_port_event(p, event); 131 130 132 131 /* Events that may cause spanning tree to refresh */ 133 132 if (!notified && (event == NETDEV_CHANGEADDR || event == NETDEV_UP ||
+14
net/bridge/br_private.h
··· 321 321 BROPT_MTU_SET_BY_USER, 322 322 BROPT_VLAN_STATS_PER_PORT, 323 323 BROPT_NO_LL_LEARN, 324 + BROPT_VLAN_BRIDGE_BINDING, 324 325 }; 325 326 326 327 struct net_bridge { ··· 896 895 int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask); 897 896 void br_vlan_get_stats(const struct net_bridge_vlan *v, 898 897 struct br_vlan_stats *stats); 898 + void br_vlan_port_event(struct net_bridge_port *p, unsigned long event); 899 + void br_vlan_bridge_event(struct net_device *dev, unsigned long event, 900 + void *ptr); 899 901 900 902 static inline struct net_bridge_vlan_group *br_vlan_group( 901 903 const struct net_bridge *br) ··· 1080 1076 1081 1077 static inline void br_vlan_get_stats(const struct net_bridge_vlan *v, 1082 1078 struct br_vlan_stats *stats) 1079 + { 1080 + } 1081 + 1082 + static inline void br_vlan_port_event(struct net_bridge_port *p, 1083 + unsigned long event) 1084 + { 1085 + } 1086 + 1087 + static inline void br_vlan_bridge_event(struct net_device *dev, 1088 + unsigned long event, void *ptr) 1083 1089 { 1084 1090 } 1085 1091 #endif
+214
net/bridge/br_vlan.c
··· 7 7 #include "br_private.h" 8 8 #include "br_private_tunnel.h" 9 9 10 + static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid); 11 + 10 12 static inline int br_vlan_cmp(struct rhashtable_compare_arg *arg, 11 13 const void *ptr) 12 14 { ··· 295 293 296 294 __vlan_add_list(v); 297 295 __vlan_add_flags(v, flags); 296 + 297 + if (p) 298 + nbp_vlan_set_vlan_dev_state(p, v->vid); 298 299 out: 299 300 return err; 300 301 ··· 362 357 rhashtable_remove_fast(&vg->vlan_hash, &v->vnode, 363 358 br_vlan_rht_params); 364 359 __vlan_del_list(v); 360 + nbp_vlan_set_vlan_dev_state(p, v->vid); 365 361 call_rcu(&v->rcu, nbp_vlan_rcu_free); 366 362 } 367 363 ··· 1270 1264 return 0; 1271 1265 } 1272 1266 EXPORT_SYMBOL_GPL(br_vlan_get_info); 1267 + 1268 + static int br_vlan_is_bind_vlan_dev(const struct net_device *dev) 1269 + { 1270 + return is_vlan_dev(dev) && 1271 + !!(vlan_dev_priv(dev)->flags & VLAN_FLAG_BRIDGE_BINDING); 1272 + } 1273 + 1274 + static int br_vlan_is_bind_vlan_dev_fn(struct net_device *dev, 1275 + __always_unused void *data) 1276 + { 1277 + return br_vlan_is_bind_vlan_dev(dev); 1278 + } 1279 + 1280 + static bool br_vlan_has_upper_bind_vlan_dev(struct net_device *dev) 1281 + { 1282 + int found; 1283 + 1284 + rcu_read_lock(); 1285 + found = netdev_walk_all_upper_dev_rcu(dev, br_vlan_is_bind_vlan_dev_fn, 1286 + NULL); 1287 + rcu_read_unlock(); 1288 + 1289 + return !!found; 1290 + } 1291 + 1292 + struct br_vlan_bind_walk_data { 1293 + u16 vid; 1294 + struct net_device *result; 1295 + }; 1296 + 1297 + static int br_vlan_match_bind_vlan_dev_fn(struct net_device *dev, 1298 + void *data_in) 1299 + { 1300 + struct br_vlan_bind_walk_data *data = data_in; 1301 + int found = 0; 1302 + 1303 + if (br_vlan_is_bind_vlan_dev(dev) && 1304 + vlan_dev_priv(dev)->vlan_id == data->vid) { 1305 + data->result = dev; 1306 + found = 1; 1307 + } 1308 + 1309 + return found; 1310 + } 1311 + 1312 + static struct net_device * 1313 + br_vlan_get_upper_bind_vlan_dev(struct net_device *dev, u16 vid) 1314 + { 1315 + struct br_vlan_bind_walk_data data = { 1316 + .vid = vid, 1317 + }; 1318 + 1319 + rcu_read_lock(); 1320 + netdev_walk_all_upper_dev_rcu(dev, br_vlan_match_bind_vlan_dev_fn, 1321 + &data); 1322 + rcu_read_unlock(); 1323 + 1324 + return data.result; 1325 + } 1326 + 1327 + static bool br_vlan_is_dev_up(const struct net_device *dev) 1328 + { 1329 + return !!(dev->flags & IFF_UP) && netif_oper_up(dev); 1330 + } 1331 + 1332 + static void br_vlan_set_vlan_dev_state(const struct net_bridge *br, 1333 + struct net_device *vlan_dev) 1334 + { 1335 + u16 vid = vlan_dev_priv(vlan_dev)->vlan_id; 1336 + struct net_bridge_vlan_group *vg; 1337 + struct net_bridge_port *p; 1338 + bool has_carrier = false; 1339 + 1340 + if (!netif_carrier_ok(br->dev)) { 1341 + netif_carrier_off(vlan_dev); 1342 + return; 1343 + } 1344 + 1345 + list_for_each_entry(p, &br->port_list, list) { 1346 + vg = nbp_vlan_group(p); 1347 + if (br_vlan_find(vg, vid) && br_vlan_is_dev_up(p->dev)) { 1348 + has_carrier = true; 1349 + break; 1350 + } 1351 + } 1352 + 1353 + if (has_carrier) 1354 + netif_carrier_on(vlan_dev); 1355 + else 1356 + netif_carrier_off(vlan_dev); 1357 + } 1358 + 1359 + static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p) 1360 + { 1361 + struct net_bridge_vlan_group *vg = nbp_vlan_group(p); 1362 + struct net_bridge_vlan *vlan; 1363 + struct net_device *vlan_dev; 1364 + 1365 + list_for_each_entry(vlan, &vg->vlan_list, vlist) { 1366 + vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, 1367 + vlan->vid); 1368 + if (vlan_dev) { 1369 + if (br_vlan_is_dev_up(p->dev)) { 1370 + if (netif_carrier_ok(p->br->dev)) 1371 + netif_carrier_on(vlan_dev); 1372 + } else { 1373 + br_vlan_set_vlan_dev_state(p->br, vlan_dev); 1374 + } 1375 + } 1376 + } 1377 + } 1378 + 1379 + static void br_vlan_upper_change(struct net_device *dev, 1380 + struct net_device *upper_dev, 1381 + bool linking) 1382 + { 1383 + struct net_bridge *br = netdev_priv(dev); 1384 + 1385 + if (!br_vlan_is_bind_vlan_dev(upper_dev)) 1386 + return; 1387 + 1388 + if (linking) { 1389 + br_vlan_set_vlan_dev_state(br, upper_dev); 1390 + br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true); 1391 + } else { 1392 + br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, 1393 + br_vlan_has_upper_bind_vlan_dev(dev)); 1394 + } 1395 + } 1396 + 1397 + struct br_vlan_link_state_walk_data { 1398 + struct net_bridge *br; 1399 + }; 1400 + 1401 + static int br_vlan_link_state_change_fn(struct net_device *vlan_dev, 1402 + void *data_in) 1403 + { 1404 + struct br_vlan_link_state_walk_data *data = data_in; 1405 + 1406 + if (br_vlan_is_bind_vlan_dev(vlan_dev)) 1407 + br_vlan_set_vlan_dev_state(data->br, vlan_dev); 1408 + 1409 + return 0; 1410 + } 1411 + 1412 + static void br_vlan_link_state_change(struct net_device *dev, 1413 + struct net_bridge *br) 1414 + { 1415 + struct br_vlan_link_state_walk_data data = { 1416 + .br = br 1417 + }; 1418 + 1419 + rcu_read_lock(); 1420 + netdev_walk_all_upper_dev_rcu(dev, br_vlan_link_state_change_fn, 1421 + &data); 1422 + rcu_read_unlock(); 1423 + } 1424 + 1425 + /* Must be protected by RTNL. */ 1426 + static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) 1427 + { 1428 + struct net_device *vlan_dev; 1429 + 1430 + if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 1431 + return; 1432 + 1433 + vlan_dev = br_vlan_get_upper_bind_vlan_dev(p->br->dev, vid); 1434 + if (vlan_dev) 1435 + br_vlan_set_vlan_dev_state(p->br, vlan_dev); 1436 + } 1437 + 1438 + /* Must be protected by RTNL. */ 1439 + void br_vlan_bridge_event(struct net_device *dev, unsigned long event, 1440 + void *ptr) 1441 + { 1442 + struct netdev_notifier_changeupper_info *info; 1443 + struct net_bridge *br; 1444 + 1445 + switch (event) { 1446 + case NETDEV_CHANGEUPPER: 1447 + info = ptr; 1448 + br_vlan_upper_change(dev, info->upper_dev, info->linking); 1449 + break; 1450 + 1451 + case NETDEV_CHANGE: 1452 + case NETDEV_UP: 1453 + br = netdev_priv(dev); 1454 + if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) 1455 + return; 1456 + br_vlan_link_state_change(dev, br); 1457 + break; 1458 + } 1459 + } 1460 + 1461 + /* Must be protected by RTNL. */ 1462 + void br_vlan_port_event(struct net_bridge_port *p, unsigned long event) 1463 + { 1464 + if (!br_opt_get(p->br, BROPT_VLAN_BRIDGE_BINDING)) 1465 + return; 1466 + 1467 + switch (event) { 1468 + case NETDEV_CHANGE: 1469 + case NETDEV_DOWN: 1470 + case NETDEV_UP: 1471 + br_vlan_set_all_vlan_dev_state(p); 1472 + break; 1473 + } 1474 + }