@@ -74,6 +74,14 @@ struct vxlan_mdb_config {
74
74
u8 rt_protocol ;
75
75
};
76
76
77
+ struct vxlan_mdb_flush_desc {
78
+ union vxlan_addr remote_ip ;
79
+ __be32 src_vni ;
80
+ __be32 remote_vni ;
81
+ __be16 remote_port ;
82
+ u8 rt_protocol ;
83
+ };
84
+
77
85
static const struct rhashtable_params vxlan_mdb_rht_params = {
78
86
.head_offset = offsetof(struct vxlan_mdb_entry , rhnode ),
79
87
.key_offset = offsetof(struct vxlan_mdb_entry , key ),
@@ -1306,6 +1314,145 @@ int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[],
1306
1314
return err ;
1307
1315
}
1308
1316
1317
+ static const struct nla_policy
1318
+ vxlan_mdbe_attrs_del_bulk_pol [MDBE_ATTR_MAX + 1 ] = {
1319
+ [MDBE_ATTR_RTPROT ] = NLA_POLICY_MIN (NLA_U8 , RTPROT_STATIC ),
1320
+ [MDBE_ATTR_DST ] = NLA_POLICY_RANGE (NLA_BINARY ,
1321
+ sizeof (struct in_addr ),
1322
+ sizeof (struct in6_addr )),
1323
+ [MDBE_ATTR_DST_PORT ] = { .type = NLA_U16 },
1324
+ [MDBE_ATTR_VNI ] = NLA_POLICY_FULL_RANGE (NLA_U32 , & vni_range ),
1325
+ [MDBE_ATTR_SRC_VNI ] = NLA_POLICY_FULL_RANGE (NLA_U32 , & vni_range ),
1326
+ [MDBE_ATTR_STATE_MASK ] = NLA_POLICY_MASK (NLA_U8 , MDB_PERMANENT ),
1327
+ };
1328
+
1329
+ static int vxlan_mdb_flush_desc_init (struct vxlan_dev * vxlan ,
1330
+ struct vxlan_mdb_flush_desc * desc ,
1331
+ struct nlattr * tb [],
1332
+ struct netlink_ext_ack * extack )
1333
+ {
1334
+ struct br_mdb_entry * entry = nla_data (tb [MDBA_SET_ENTRY ]);
1335
+ struct nlattr * mdbe_attrs [MDBE_ATTR_MAX + 1 ];
1336
+ int err ;
1337
+
1338
+ if (entry -> ifindex && entry -> ifindex != vxlan -> dev -> ifindex ) {
1339
+ NL_SET_ERR_MSG_MOD (extack , "Invalid port net device" );
1340
+ return - EINVAL ;
1341
+ }
1342
+
1343
+ if (entry -> vid ) {
1344
+ NL_SET_ERR_MSG_MOD (extack , "VID must not be specified" );
1345
+ return - EINVAL ;
1346
+ }
1347
+
1348
+ if (!tb [MDBA_SET_ENTRY_ATTRS ])
1349
+ return 0 ;
1350
+
1351
+ err = nla_parse_nested (mdbe_attrs , MDBE_ATTR_MAX ,
1352
+ tb [MDBA_SET_ENTRY_ATTRS ],
1353
+ vxlan_mdbe_attrs_del_bulk_pol , extack );
1354
+ if (err )
1355
+ return err ;
1356
+
1357
+ if (mdbe_attrs [MDBE_ATTR_STATE_MASK ]) {
1358
+ u8 state_mask = nla_get_u8 (mdbe_attrs [MDBE_ATTR_STATE_MASK ]);
1359
+
1360
+ if ((state_mask & MDB_PERMANENT ) && !(entry -> state & MDB_PERMANENT )) {
1361
+ NL_SET_ERR_MSG_MOD (extack , "Only permanent MDB entries are supported" );
1362
+ return - EINVAL ;
1363
+ }
1364
+ }
1365
+
1366
+ if (mdbe_attrs [MDBE_ATTR_RTPROT ])
1367
+ desc -> rt_protocol = nla_get_u8 (mdbe_attrs [MDBE_ATTR_RTPROT ]);
1368
+
1369
+ if (mdbe_attrs [MDBE_ATTR_DST ])
1370
+ vxlan_nla_get_addr (& desc -> remote_ip , mdbe_attrs [MDBE_ATTR_DST ]);
1371
+
1372
+ if (mdbe_attrs [MDBE_ATTR_DST_PORT ])
1373
+ desc -> remote_port =
1374
+ cpu_to_be16 (nla_get_u16 (mdbe_attrs [MDBE_ATTR_DST_PORT ]));
1375
+
1376
+ if (mdbe_attrs [MDBE_ATTR_VNI ])
1377
+ desc -> remote_vni =
1378
+ cpu_to_be32 (nla_get_u32 (mdbe_attrs [MDBE_ATTR_VNI ]));
1379
+
1380
+ if (mdbe_attrs [MDBE_ATTR_SRC_VNI ])
1381
+ desc -> src_vni =
1382
+ cpu_to_be32 (nla_get_u32 (mdbe_attrs [MDBE_ATTR_SRC_VNI ]));
1383
+
1384
+ return 0 ;
1385
+ }
1386
+
1387
+ static void vxlan_mdb_remotes_flush (struct vxlan_dev * vxlan ,
1388
+ struct vxlan_mdb_entry * mdb_entry ,
1389
+ const struct vxlan_mdb_flush_desc * desc )
1390
+ {
1391
+ struct vxlan_mdb_remote * remote , * tmp ;
1392
+
1393
+ list_for_each_entry_safe (remote , tmp , & mdb_entry -> remotes , list ) {
1394
+ struct vxlan_rdst * rd = rtnl_dereference (remote -> rd );
1395
+ __be32 remote_vni ;
1396
+
1397
+ if (desc -> remote_ip .sa .sa_family &&
1398
+ !vxlan_addr_equal (& desc -> remote_ip , & rd -> remote_ip ))
1399
+ continue ;
1400
+
1401
+ /* Encapsulation is performed with source VNI if remote VNI
1402
+ * is not set.
1403
+ */
1404
+ remote_vni = rd -> remote_vni ? : mdb_entry -> key .vni ;
1405
+ if (desc -> remote_vni && desc -> remote_vni != remote_vni )
1406
+ continue ;
1407
+
1408
+ if (desc -> remote_port && desc -> remote_port != rd -> remote_port )
1409
+ continue ;
1410
+
1411
+ if (desc -> rt_protocol &&
1412
+ desc -> rt_protocol != remote -> rt_protocol )
1413
+ continue ;
1414
+
1415
+ vxlan_mdb_remote_del (vxlan , mdb_entry , remote );
1416
+ }
1417
+ }
1418
+
1419
+ static void vxlan_mdb_flush (struct vxlan_dev * vxlan ,
1420
+ const struct vxlan_mdb_flush_desc * desc )
1421
+ {
1422
+ struct vxlan_mdb_entry * mdb_entry ;
1423
+ struct hlist_node * tmp ;
1424
+
1425
+ /* The removal of an entry cannot trigger the removal of another entry
1426
+ * since entries are always added to the head of the list.
1427
+ */
1428
+ hlist_for_each_entry_safe (mdb_entry , tmp , & vxlan -> mdb_list , mdb_node ) {
1429
+ if (desc -> src_vni && desc -> src_vni != mdb_entry -> key .vni )
1430
+ continue ;
1431
+
1432
+ vxlan_mdb_remotes_flush (vxlan , mdb_entry , desc );
1433
+ /* Entry will only be removed if its remotes list is empty. */
1434
+ vxlan_mdb_entry_put (vxlan , mdb_entry );
1435
+ }
1436
+ }
1437
+
1438
+ int vxlan_mdb_del_bulk (struct net_device * dev , struct nlattr * tb [],
1439
+ struct netlink_ext_ack * extack )
1440
+ {
1441
+ struct vxlan_dev * vxlan = netdev_priv (dev );
1442
+ struct vxlan_mdb_flush_desc desc = {};
1443
+ int err ;
1444
+
1445
+ ASSERT_RTNL ();
1446
+
1447
+ err = vxlan_mdb_flush_desc_init (vxlan , & desc , tb , extack );
1448
+ if (err )
1449
+ return err ;
1450
+
1451
+ vxlan_mdb_flush (vxlan , & desc );
1452
+
1453
+ return 0 ;
1454
+ }
1455
+
1309
1456
static const struct nla_policy vxlan_mdbe_attrs_get_pol [MDBE_ATTR_MAX + 1 ] = {
1310
1457
[MDBE_ATTR_SOURCE ] = NLA_POLICY_RANGE (NLA_BINARY ,
1311
1458
sizeof (struct in_addr ),
@@ -1575,29 +1722,6 @@ static void vxlan_mdb_check_empty(void *ptr, void *arg)
1575
1722
WARN_ON_ONCE (1 );
1576
1723
}
1577
1724
1578
- static void vxlan_mdb_remotes_flush (struct vxlan_dev * vxlan ,
1579
- struct vxlan_mdb_entry * mdb_entry )
1580
- {
1581
- struct vxlan_mdb_remote * remote , * tmp ;
1582
-
1583
- list_for_each_entry_safe (remote , tmp , & mdb_entry -> remotes , list )
1584
- vxlan_mdb_remote_del (vxlan , mdb_entry , remote );
1585
- }
1586
-
1587
- static void vxlan_mdb_entries_flush (struct vxlan_dev * vxlan )
1588
- {
1589
- struct vxlan_mdb_entry * mdb_entry ;
1590
- struct hlist_node * tmp ;
1591
-
1592
- /* The removal of an entry cannot trigger the removal of another entry
1593
- * since entries are always added to the head of the list.
1594
- */
1595
- hlist_for_each_entry_safe (mdb_entry , tmp , & vxlan -> mdb_list , mdb_node ) {
1596
- vxlan_mdb_remotes_flush (vxlan , mdb_entry );
1597
- vxlan_mdb_entry_put (vxlan , mdb_entry );
1598
- }
1599
- }
1600
-
1601
1725
int vxlan_mdb_init (struct vxlan_dev * vxlan )
1602
1726
{
1603
1727
int err ;
@@ -1613,7 +1737,9 @@ int vxlan_mdb_init(struct vxlan_dev *vxlan)
1613
1737
1614
1738
void vxlan_mdb_fini (struct vxlan_dev * vxlan )
1615
1739
{
1616
- vxlan_mdb_entries_flush (vxlan );
1740
+ struct vxlan_mdb_flush_desc desc = {};
1741
+
1742
+ vxlan_mdb_flush (vxlan , & desc );
1617
1743
WARN_ON_ONCE (vxlan -> cfg .flags & VXLAN_F_MDB );
1618
1744
rhashtable_free_and_destroy (& vxlan -> mdb_tbl , vxlan_mdb_check_empty ,
1619
1745
NULL );
0 commit comments