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

bridge: mcast: Implement MDB net device operations

Implement the previously added MDB net device operations in the bridge
driver so that they could be invoked by core rtnetlink code in the next
patch.

The operations are identical to the existing br_mdb_{dump,add,del}
functions. The '_new' suffix will be removed in the next patch. The
functions are re-implemented in this patch to make the conversion in the
next patch easier to review.

Add dummy implementations when 'CONFIG_BRIDGE_IGMP_SNOOPING' is
disabled, so that an error will be returned to user space when it is
trying to add or delete an MDB entry. This is consistent with existing
behavior where the bridge driver does not even register rtnetlink
handlers for RTM_{NEW,DEL,GET}MDB messages when this Kconfig option is
disabled.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ido Schimmel and committed by
David S. Miller
c009de10 8c44fa12

+152
+3
net/bridge/br_device.c
··· 468 468 .ndo_fdb_del_bulk = br_fdb_delete_bulk, 469 469 .ndo_fdb_dump = br_fdb_dump, 470 470 .ndo_fdb_get = br_fdb_get, 471 + .ndo_mdb_add = br_mdb_add_new, 472 + .ndo_mdb_del = br_mdb_del_new, 473 + .ndo_mdb_dump = br_mdb_dump_new, 471 474 .ndo_bridge_getlink = br_getlink, 472 475 .ndo_bridge_setlink = br_setlink, 473 476 .ndo_bridge_dellink = br_dellink,
+124
net/bridge/br_mdb.c
··· 458 458 return skb->len; 459 459 } 460 460 461 + int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 462 + struct netlink_callback *cb) 463 + { 464 + struct net_bridge *br = netdev_priv(dev); 465 + struct br_port_msg *bpm; 466 + struct nlmsghdr *nlh; 467 + int err; 468 + 469 + nlh = nlmsg_put(skb, NETLINK_CB(cb->skb).portid, 470 + cb->nlh->nlmsg_seq, RTM_GETMDB, sizeof(*bpm), 471 + NLM_F_MULTI); 472 + if (!nlh) 473 + return -EMSGSIZE; 474 + 475 + bpm = nlmsg_data(nlh); 476 + memset(bpm, 0, sizeof(*bpm)); 477 + bpm->ifindex = dev->ifindex; 478 + 479 + rcu_read_lock(); 480 + 481 + err = br_mdb_fill_info(skb, cb, dev); 482 + if (err) 483 + goto out; 484 + err = br_rports_fill_info(skb, &br->multicast_ctx); 485 + if (err) 486 + goto out; 487 + 488 + out: 489 + rcu_read_unlock(); 490 + nlmsg_end(skb, nlh); 491 + return err; 492 + } 493 + 461 494 static int nlmsg_populate_mdb_fill(struct sk_buff *skb, 462 495 struct net_device *dev, 463 496 struct net_bridge_mdb_entry *mp, ··· 1492 1459 return err; 1493 1460 } 1494 1461 1462 + int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 1463 + struct netlink_ext_ack *extack) 1464 + { 1465 + struct net_bridge_vlan_group *vg; 1466 + struct br_mdb_config cfg = {}; 1467 + struct net_bridge_vlan *v; 1468 + int err; 1469 + 1470 + /* Configuration structure will be initialized here. */ 1471 + 1472 + err = -EINVAL; 1473 + /* host join errors which can happen before creating the group */ 1474 + if (!cfg.p && !br_group_is_l2(&cfg.group)) { 1475 + /* don't allow any flags for host-joined IP groups */ 1476 + if (cfg.entry->state) { 1477 + NL_SET_ERR_MSG_MOD(extack, "Flags are not allowed for host groups"); 1478 + goto out; 1479 + } 1480 + if (!br_multicast_is_star_g(&cfg.group)) { 1481 + NL_SET_ERR_MSG_MOD(extack, "Groups with sources cannot be manually host joined"); 1482 + goto out; 1483 + } 1484 + } 1485 + 1486 + if (br_group_is_l2(&cfg.group) && cfg.entry->state != MDB_PERMANENT) { 1487 + NL_SET_ERR_MSG_MOD(extack, "Only permanent L2 entries allowed"); 1488 + goto out; 1489 + } 1490 + 1491 + if (cfg.p) { 1492 + if (cfg.p->state == BR_STATE_DISABLED && cfg.entry->state != MDB_PERMANENT) { 1493 + NL_SET_ERR_MSG_MOD(extack, "Port is in disabled state and entry is not permanent"); 1494 + goto out; 1495 + } 1496 + vg = nbp_vlan_group(cfg.p); 1497 + } else { 1498 + vg = br_vlan_group(cfg.br); 1499 + } 1500 + 1501 + /* If vlan filtering is enabled and VLAN is not specified 1502 + * install mdb entry on all vlans configured on the port. 1503 + */ 1504 + if (br_vlan_enabled(cfg.br->dev) && vg && cfg.entry->vid == 0) { 1505 + list_for_each_entry(v, &vg->vlan_list, vlist) { 1506 + cfg.entry->vid = v->vid; 1507 + cfg.group.vid = v->vid; 1508 + err = __br_mdb_add(&cfg, extack); 1509 + if (err) 1510 + break; 1511 + } 1512 + } else { 1513 + err = __br_mdb_add(&cfg, extack); 1514 + } 1515 + 1516 + out: 1517 + br_mdb_config_fini(&cfg); 1518 + return err; 1519 + } 1520 + 1495 1521 static int __br_mdb_del(const struct br_mdb_config *cfg) 1496 1522 { 1497 1523 struct br_mdb_entry *entry = cfg->entry; ··· 1604 1512 err = br_mdb_config_init(net, nlh, &cfg, extack); 1605 1513 if (err) 1606 1514 return err; 1515 + 1516 + if (cfg.p) 1517 + vg = nbp_vlan_group(cfg.p); 1518 + else 1519 + vg = br_vlan_group(cfg.br); 1520 + 1521 + /* If vlan filtering is enabled and VLAN is not specified 1522 + * delete mdb entry on all vlans configured on the port. 1523 + */ 1524 + if (br_vlan_enabled(cfg.br->dev) && vg && cfg.entry->vid == 0) { 1525 + list_for_each_entry(v, &vg->vlan_list, vlist) { 1526 + cfg.entry->vid = v->vid; 1527 + cfg.group.vid = v->vid; 1528 + err = __br_mdb_del(&cfg); 1529 + } 1530 + } else { 1531 + err = __br_mdb_del(&cfg); 1532 + } 1533 + 1534 + br_mdb_config_fini(&cfg); 1535 + return err; 1536 + } 1537 + 1538 + int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 1539 + struct netlink_ext_ack *extack) 1540 + { 1541 + struct net_bridge_vlan_group *vg; 1542 + struct br_mdb_config cfg = {}; 1543 + struct net_bridge_vlan *v; 1544 + int err = 0; 1545 + 1546 + /* Configuration structure will be initialized here. */ 1607 1547 1608 1548 if (cfg.p) 1609 1549 vg = nbp_vlan_group(cfg.p);
+25
net/bridge/br_private.h
··· 981 981 u32 br_multicast_ngroups_get(const struct net_bridge_mcast_port *pmctx); 982 982 void br_multicast_ngroups_set_max(struct net_bridge_mcast_port *pmctx, u32 max); 983 983 u32 br_multicast_ngroups_get_max(const struct net_bridge_mcast_port *pmctx); 984 + int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags, 985 + struct netlink_ext_ack *extack); 986 + int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 987 + struct netlink_ext_ack *extack); 988 + int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 989 + struct netlink_callback *cb); 984 990 void br_mdb_init(void); 985 991 void br_mdb_uninit(void); 986 992 void br_multicast_host_join(const struct net_bridge_mcast *brmctx, ··· 1378 1372 const struct net_bridge_mdb_entry *mdb) 1379 1373 { 1380 1374 return false; 1375 + } 1376 + 1377 + static inline int br_mdb_add_new(struct net_device *dev, struct nlattr *tb[], 1378 + u16 nlmsg_flags, 1379 + struct netlink_ext_ack *extack) 1380 + { 1381 + return -EOPNOTSUPP; 1382 + } 1383 + 1384 + static inline int br_mdb_del_new(struct net_device *dev, struct nlattr *tb[], 1385 + struct netlink_ext_ack *extack) 1386 + { 1387 + return -EOPNOTSUPP; 1388 + } 1389 + 1390 + static inline int br_mdb_dump_new(struct net_device *dev, struct sk_buff *skb, 1391 + struct netlink_callback *cb) 1392 + { 1393 + return 0; 1381 1394 } 1382 1395 1383 1396 static inline void br_mdb_init(void)