@@ -1412,6 +1412,139 @@ int br_mdb_del(struct net_device *dev, struct nlattr *tb[],
1412
1412
return err ;
1413
1413
}
1414
1414
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
+
1415
1548
static const struct nla_policy br_mdbe_attrs_get_pol [MDBE_ATTR_MAX + 1 ] = {
1416
1549
[MDBE_ATTR_SOURCE ] = NLA_POLICY_RANGE (NLA_BINARY ,
1417
1550
sizeof (struct in_addr ),
0 commit comments