Skip to content

Commit a6acb53

Browse files
idoschdavem330
authored andcommitted
bridge: mdb: Add MDB bulk deletion support
Implement MDB bulk deletion support in the bridge driver, allowing MDB entries to be deleted in bulk according to provided parameters. Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Petr Machata <[email protected]> Acked-by: Nikolay Aleksandrov <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d8e81f1 commit a6acb53

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

net/bridge/br_device.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ static const struct net_device_ops br_netdev_ops = {
471471
.ndo_fdb_get = br_fdb_get,
472472
.ndo_mdb_add = br_mdb_add,
473473
.ndo_mdb_del = br_mdb_del,
474+
.ndo_mdb_del_bulk = br_mdb_del_bulk,
474475
.ndo_mdb_dump = br_mdb_dump,
475476
.ndo_mdb_get = br_mdb_get,
476477
.ndo_bridge_getlink = br_getlink,

net/bridge/br_mdb.c

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,139 @@ int br_mdb_del(struct net_device *dev, struct nlattr *tb[],
14121412
return err;
14131413
}
14141414

1415+
struct br_mdb_flush_desc {
1416+
u32 port_ifindex;
1417+
u16 vid;
1418+
u8 rt_protocol;
1419+
u8 state;
1420+
u8 state_mask;
1421+
};
1422+
1423+
static const struct nla_policy br_mdbe_attrs_del_bulk_pol[MDBE_ATTR_MAX + 1] = {
1424+
[MDBE_ATTR_RTPROT] = NLA_POLICY_MIN(NLA_U8, RTPROT_STATIC),
1425+
[MDBE_ATTR_STATE_MASK] = NLA_POLICY_MASK(NLA_U8, MDB_PERMANENT),
1426+
};
1427+
1428+
static int br_mdb_flush_desc_init(struct br_mdb_flush_desc *desc,
1429+
struct nlattr *tb[],
1430+
struct netlink_ext_ack *extack)
1431+
{
1432+
struct br_mdb_entry *entry = nla_data(tb[MDBA_SET_ENTRY]);
1433+
struct nlattr *mdbe_attrs[MDBE_ATTR_MAX + 1];
1434+
int err;
1435+
1436+
desc->port_ifindex = entry->ifindex;
1437+
desc->vid = entry->vid;
1438+
desc->state = entry->state;
1439+
1440+
if (!tb[MDBA_SET_ENTRY_ATTRS])
1441+
return 0;
1442+
1443+
err = nla_parse_nested(mdbe_attrs, MDBE_ATTR_MAX,
1444+
tb[MDBA_SET_ENTRY_ATTRS],
1445+
br_mdbe_attrs_del_bulk_pol, extack);
1446+
if (err)
1447+
return err;
1448+
1449+
if (mdbe_attrs[MDBE_ATTR_STATE_MASK])
1450+
desc->state_mask = nla_get_u8(mdbe_attrs[MDBE_ATTR_STATE_MASK]);
1451+
1452+
if (mdbe_attrs[MDBE_ATTR_RTPROT])
1453+
desc->rt_protocol = nla_get_u8(mdbe_attrs[MDBE_ATTR_RTPROT]);
1454+
1455+
return 0;
1456+
}
1457+
1458+
static void br_mdb_flush_host(struct net_bridge *br,
1459+
struct net_bridge_mdb_entry *mp,
1460+
const struct br_mdb_flush_desc *desc)
1461+
{
1462+
u8 state;
1463+
1464+
if (desc->port_ifindex && desc->port_ifindex != br->dev->ifindex)
1465+
return;
1466+
1467+
if (desc->rt_protocol)
1468+
return;
1469+
1470+
state = br_group_is_l2(&mp->addr) ? MDB_PERMANENT : 0;
1471+
if (desc->state_mask && (state & desc->state_mask) != desc->state)
1472+
return;
1473+
1474+
br_multicast_host_leave(mp, true);
1475+
if (!mp->ports && netif_running(br->dev))
1476+
mod_timer(&mp->timer, jiffies);
1477+
}
1478+
1479+
static void br_mdb_flush_pgs(struct net_bridge *br,
1480+
struct net_bridge_mdb_entry *mp,
1481+
const struct br_mdb_flush_desc *desc)
1482+
{
1483+
struct net_bridge_port_group __rcu **pp;
1484+
struct net_bridge_port_group *p;
1485+
1486+
for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL;) {
1487+
u8 state;
1488+
1489+
if (desc->port_ifindex &&
1490+
desc->port_ifindex != p->key.port->dev->ifindex) {
1491+
pp = &p->next;
1492+
continue;
1493+
}
1494+
1495+
if (desc->rt_protocol && desc->rt_protocol != p->rt_protocol) {
1496+
pp = &p->next;
1497+
continue;
1498+
}
1499+
1500+
state = p->flags & MDB_PG_FLAGS_PERMANENT ? MDB_PERMANENT : 0;
1501+
if (desc->state_mask &&
1502+
(state & desc->state_mask) != desc->state) {
1503+
pp = &p->next;
1504+
continue;
1505+
}
1506+
1507+
br_multicast_del_pg(mp, p, pp);
1508+
}
1509+
}
1510+
1511+
static void br_mdb_flush(struct net_bridge *br,
1512+
const struct br_mdb_flush_desc *desc)
1513+
{
1514+
struct net_bridge_mdb_entry *mp;
1515+
1516+
spin_lock_bh(&br->multicast_lock);
1517+
1518+
/* Safe variant is not needed because entries are removed from the list
1519+
* upon group timer expiration or bridge deletion.
1520+
*/
1521+
hlist_for_each_entry(mp, &br->mdb_list, mdb_node) {
1522+
if (desc->vid && desc->vid != mp->addr.vid)
1523+
continue;
1524+
1525+
br_mdb_flush_host(br, mp, desc);
1526+
br_mdb_flush_pgs(br, mp, desc);
1527+
}
1528+
1529+
spin_unlock_bh(&br->multicast_lock);
1530+
}
1531+
1532+
int br_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[],
1533+
struct netlink_ext_ack *extack)
1534+
{
1535+
struct net_bridge *br = netdev_priv(dev);
1536+
struct br_mdb_flush_desc desc = {};
1537+
int err;
1538+
1539+
err = br_mdb_flush_desc_init(&desc, tb, extack);
1540+
if (err)
1541+
return err;
1542+
1543+
br_mdb_flush(br, &desc);
1544+
1545+
return 0;
1546+
}
1547+
14151548
static const struct nla_policy br_mdbe_attrs_get_pol[MDBE_ATTR_MAX + 1] = {
14161549
[MDBE_ATTR_SOURCE] = NLA_POLICY_RANGE(NLA_BINARY,
14171550
sizeof(struct in_addr),

net/bridge/br_private.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,6 +1022,8 @@ int br_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags,
10221022
struct netlink_ext_ack *extack);
10231023
int br_mdb_del(struct net_device *dev, struct nlattr *tb[],
10241024
struct netlink_ext_ack *extack);
1025+
int br_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[],
1026+
struct netlink_ext_ack *extack);
10251027
int br_mdb_dump(struct net_device *dev, struct sk_buff *skb,
10261028
struct netlink_callback *cb);
10271029
int br_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid, u32 seq,
@@ -1430,6 +1432,12 @@ static inline int br_mdb_del(struct net_device *dev, struct nlattr *tb[],
14301432
return -EOPNOTSUPP;
14311433
}
14321434

1435+
static inline int br_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[],
1436+
struct netlink_ext_ack *extack)
1437+
{
1438+
return -EOPNOTSUPP;
1439+
}
1440+
14331441
static inline int br_mdb_dump(struct net_device *dev, struct sk_buff *skb,
14341442
struct netlink_callback *cb)
14351443
{

0 commit comments

Comments
 (0)