Skip to content

Commit 4cde72f

Browse files
idoschdavem330
authored andcommitted
vxlan: mdb: Add MDB bulk deletion support
Implement MDB bulk deletion support in the VXLAN 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 a6acb53 commit 4cde72f

File tree

3 files changed

+153
-24
lines changed

3 files changed

+153
-24
lines changed

drivers/net/vxlan/vxlan_core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3235,6 +3235,7 @@ static const struct net_device_ops vxlan_netdev_ether_ops = {
32353235
.ndo_fdb_get = vxlan_fdb_get,
32363236
.ndo_mdb_add = vxlan_mdb_add,
32373237
.ndo_mdb_del = vxlan_mdb_del,
3238+
.ndo_mdb_del_bulk = vxlan_mdb_del_bulk,
32383239
.ndo_mdb_dump = vxlan_mdb_dump,
32393240
.ndo_mdb_get = vxlan_mdb_get,
32403241
.ndo_fill_metadata_dst = vxlan_fill_metadata_dst,

drivers/net/vxlan/vxlan_mdb.c

Lines changed: 150 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ struct vxlan_mdb_config {
7474
u8 rt_protocol;
7575
};
7676

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+
7785
static const struct rhashtable_params vxlan_mdb_rht_params = {
7886
.head_offset = offsetof(struct vxlan_mdb_entry, rhnode),
7987
.key_offset = offsetof(struct vxlan_mdb_entry, key),
@@ -1306,6 +1314,145 @@ int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[],
13061314
return err;
13071315
}
13081316

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+
13091456
static const struct nla_policy vxlan_mdbe_attrs_get_pol[MDBE_ATTR_MAX + 1] = {
13101457
[MDBE_ATTR_SOURCE] = NLA_POLICY_RANGE(NLA_BINARY,
13111458
sizeof(struct in_addr),
@@ -1575,29 +1722,6 @@ static void vxlan_mdb_check_empty(void *ptr, void *arg)
15751722
WARN_ON_ONCE(1);
15761723
}
15771724

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-
16011725
int vxlan_mdb_init(struct vxlan_dev *vxlan)
16021726
{
16031727
int err;
@@ -1613,7 +1737,9 @@ int vxlan_mdb_init(struct vxlan_dev *vxlan)
16131737

16141738
void vxlan_mdb_fini(struct vxlan_dev *vxlan)
16151739
{
1616-
vxlan_mdb_entries_flush(vxlan);
1740+
struct vxlan_mdb_flush_desc desc = {};
1741+
1742+
vxlan_mdb_flush(vxlan, &desc);
16171743
WARN_ON_ONCE(vxlan->cfg.flags & VXLAN_F_MDB);
16181744
rhashtable_free_and_destroy(&vxlan->mdb_tbl, vxlan_mdb_check_empty,
16191745
NULL);

drivers/net/vxlan/vxlan_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ int vxlan_mdb_add(struct net_device *dev, struct nlattr *tb[], u16 nlmsg_flags,
235235
struct netlink_ext_ack *extack);
236236
int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[],
237237
struct netlink_ext_ack *extack);
238+
int vxlan_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[],
239+
struct netlink_ext_ack *extack);
238240
int vxlan_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid,
239241
u32 seq, struct netlink_ext_ack *extack);
240242
struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,

0 commit comments

Comments
 (0)