@@ -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+
14151548static 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 ),
0 commit comments