Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'bridge-mdb-bulk-delete'

Ido Schimmel says:

====================
Add MDB bulk deletion support

This patchset adds MDB bulk deletion support, allowing user space to
request the deletion of matching entries instead of dumping the entire
MDB and issuing a separate deletion request for each matching entry.
Support is added in both the bridge and VXLAN drivers in a similar
fashion to the existing FDB bulk deletion support.

The parameters according to which bulk deletion can be performed are
similar to the FDB ones, namely: Destination port, VLAN ID, state (e.g.,
"permanent"), routing protocol, source / destination VNI, destination IP
and UDP port. Flushing based on flags (e.g., "offload", "fast_leave",
"added_by_star_ex", "blocked") is not currently supported, but can be
added in the future, if a use case arises.

Patch #1 adds a new uAPI attribute to allow specifying the state mask
according to which bulk deletion will be performed, if any.

Patch #2 adds a new policy according to which bulk deletion requests
(with 'NLM_F_BULK' flag set) will be parsed.

Patches #3-#4 add a new NDO for MDB bulk deletion and invoke it from the
rtnetlink code when a bulk deletion request is made.

Patches #5-#6 implement the MDB bulk deletion NDO in the bridge and
VXLAN drivers, respectively.

Patch #7 allows user space to issue MDB bulk deletion requests by no
longer rejecting the 'NLM_F_BULK' flag when it is set in 'RTM_DELMDB'
requests.

Patches #8-#9 add selftests for both drivers, for both good and bad
flows.

iproute2 changes can be found here [1].

https://github.com/idosch/iproute2/tree/submit/mdb_flush_v1
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+749 -31
+1
drivers/net/vxlan/vxlan_core.c
··· 3235 3235 .ndo_fdb_get = vxlan_fdb_get, 3236 3236 .ndo_mdb_add = vxlan_mdb_add, 3237 3237 .ndo_mdb_del = vxlan_mdb_del, 3238 + .ndo_mdb_del_bulk = vxlan_mdb_del_bulk, 3238 3239 .ndo_mdb_dump = vxlan_mdb_dump, 3239 3240 .ndo_mdb_get = vxlan_mdb_get, 3240 3241 .ndo_fill_metadata_dst = vxlan_fill_metadata_dst,
+150 -24
drivers/net/vxlan/vxlan_mdb.c
··· 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), ··· 1314 1306 return err; 1315 1307 } 1316 1308 1309 + static const struct nla_policy 1310 + vxlan_mdbe_attrs_del_bulk_pol[MDBE_ATTR_MAX + 1] = { 1311 + [MDBE_ATTR_RTPROT] = NLA_POLICY_MIN(NLA_U8, RTPROT_STATIC), 1312 + [MDBE_ATTR_DST] = NLA_POLICY_RANGE(NLA_BINARY, 1313 + sizeof(struct in_addr), 1314 + sizeof(struct in6_addr)), 1315 + [MDBE_ATTR_DST_PORT] = { .type = NLA_U16 }, 1316 + [MDBE_ATTR_VNI] = NLA_POLICY_FULL_RANGE(NLA_U32, &vni_range), 1317 + [MDBE_ATTR_SRC_VNI] = NLA_POLICY_FULL_RANGE(NLA_U32, &vni_range), 1318 + [MDBE_ATTR_STATE_MASK] = NLA_POLICY_MASK(NLA_U8, MDB_PERMANENT), 1319 + }; 1320 + 1321 + static int vxlan_mdb_flush_desc_init(struct vxlan_dev *vxlan, 1322 + struct vxlan_mdb_flush_desc *desc, 1323 + struct nlattr *tb[], 1324 + struct netlink_ext_ack *extack) 1325 + { 1326 + struct br_mdb_entry *entry = nla_data(tb[MDBA_SET_ENTRY]); 1327 + struct nlattr *mdbe_attrs[MDBE_ATTR_MAX + 1]; 1328 + int err; 1329 + 1330 + if (entry->ifindex && entry->ifindex != vxlan->dev->ifindex) { 1331 + NL_SET_ERR_MSG_MOD(extack, "Invalid port net device"); 1332 + return -EINVAL; 1333 + } 1334 + 1335 + if (entry->vid) { 1336 + NL_SET_ERR_MSG_MOD(extack, "VID must not be specified"); 1337 + return -EINVAL; 1338 + } 1339 + 1340 + if (!tb[MDBA_SET_ENTRY_ATTRS]) 1341 + return 0; 1342 + 1343 + err = nla_parse_nested(mdbe_attrs, MDBE_ATTR_MAX, 1344 + tb[MDBA_SET_ENTRY_ATTRS], 1345 + vxlan_mdbe_attrs_del_bulk_pol, extack); 1346 + if (err) 1347 + return err; 1348 + 1349 + if (mdbe_attrs[MDBE_ATTR_STATE_MASK]) { 1350 + u8 state_mask = nla_get_u8(mdbe_attrs[MDBE_ATTR_STATE_MASK]); 1351 + 1352 + if ((state_mask & MDB_PERMANENT) && !(entry->state & MDB_PERMANENT)) { 1353 + NL_SET_ERR_MSG_MOD(extack, "Only permanent MDB entries are supported"); 1354 + return -EINVAL; 1355 + } 1356 + } 1357 + 1358 + if (mdbe_attrs[MDBE_ATTR_RTPROT]) 1359 + desc->rt_protocol = nla_get_u8(mdbe_attrs[MDBE_ATTR_RTPROT]); 1360 + 1361 + if (mdbe_attrs[MDBE_ATTR_DST]) 1362 + vxlan_nla_get_addr(&desc->remote_ip, mdbe_attrs[MDBE_ATTR_DST]); 1363 + 1364 + if (mdbe_attrs[MDBE_ATTR_DST_PORT]) 1365 + desc->remote_port = 1366 + cpu_to_be16(nla_get_u16(mdbe_attrs[MDBE_ATTR_DST_PORT])); 1367 + 1368 + if (mdbe_attrs[MDBE_ATTR_VNI]) 1369 + desc->remote_vni = 1370 + cpu_to_be32(nla_get_u32(mdbe_attrs[MDBE_ATTR_VNI])); 1371 + 1372 + if (mdbe_attrs[MDBE_ATTR_SRC_VNI]) 1373 + desc->src_vni = 1374 + cpu_to_be32(nla_get_u32(mdbe_attrs[MDBE_ATTR_SRC_VNI])); 1375 + 1376 + return 0; 1377 + } 1378 + 1379 + static void vxlan_mdb_remotes_flush(struct vxlan_dev *vxlan, 1380 + struct vxlan_mdb_entry *mdb_entry, 1381 + const struct vxlan_mdb_flush_desc *desc) 1382 + { 1383 + struct vxlan_mdb_remote *remote, *tmp; 1384 + 1385 + list_for_each_entry_safe(remote, tmp, &mdb_entry->remotes, list) { 1386 + struct vxlan_rdst *rd = rtnl_dereference(remote->rd); 1387 + __be32 remote_vni; 1388 + 1389 + if (desc->remote_ip.sa.sa_family && 1390 + !vxlan_addr_equal(&desc->remote_ip, &rd->remote_ip)) 1391 + continue; 1392 + 1393 + /* Encapsulation is performed with source VNI if remote VNI 1394 + * is not set. 1395 + */ 1396 + remote_vni = rd->remote_vni ? : mdb_entry->key.vni; 1397 + if (desc->remote_vni && desc->remote_vni != remote_vni) 1398 + continue; 1399 + 1400 + if (desc->remote_port && desc->remote_port != rd->remote_port) 1401 + continue; 1402 + 1403 + if (desc->rt_protocol && 1404 + desc->rt_protocol != remote->rt_protocol) 1405 + continue; 1406 + 1407 + vxlan_mdb_remote_del(vxlan, mdb_entry, remote); 1408 + } 1409 + } 1410 + 1411 + static void vxlan_mdb_flush(struct vxlan_dev *vxlan, 1412 + const struct vxlan_mdb_flush_desc *desc) 1413 + { 1414 + struct vxlan_mdb_entry *mdb_entry; 1415 + struct hlist_node *tmp; 1416 + 1417 + /* The removal of an entry cannot trigger the removal of another entry 1418 + * since entries are always added to the head of the list. 1419 + */ 1420 + hlist_for_each_entry_safe(mdb_entry, tmp, &vxlan->mdb_list, mdb_node) { 1421 + if (desc->src_vni && desc->src_vni != mdb_entry->key.vni) 1422 + continue; 1423 + 1424 + vxlan_mdb_remotes_flush(vxlan, mdb_entry, desc); 1425 + /* Entry will only be removed if its remotes list is empty. */ 1426 + vxlan_mdb_entry_put(vxlan, mdb_entry); 1427 + } 1428 + } 1429 + 1430 + int vxlan_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[], 1431 + struct netlink_ext_ack *extack) 1432 + { 1433 + struct vxlan_dev *vxlan = netdev_priv(dev); 1434 + struct vxlan_mdb_flush_desc desc = {}; 1435 + int err; 1436 + 1437 + ASSERT_RTNL(); 1438 + 1439 + err = vxlan_mdb_flush_desc_init(vxlan, &desc, tb, extack); 1440 + if (err) 1441 + return err; 1442 + 1443 + vxlan_mdb_flush(vxlan, &desc); 1444 + 1445 + return 0; 1446 + } 1447 + 1317 1448 static const struct nla_policy vxlan_mdbe_attrs_get_pol[MDBE_ATTR_MAX + 1] = { 1318 1449 [MDBE_ATTR_SOURCE] = NLA_POLICY_RANGE(NLA_BINARY, 1319 1450 sizeof(struct in_addr), ··· 1722 1575 WARN_ON_ONCE(1); 1723 1576 } 1724 1577 1725 - static void vxlan_mdb_remotes_flush(struct vxlan_dev *vxlan, 1726 - struct vxlan_mdb_entry *mdb_entry) 1727 - { 1728 - struct vxlan_mdb_remote *remote, *tmp; 1729 - 1730 - list_for_each_entry_safe(remote, tmp, &mdb_entry->remotes, list) 1731 - vxlan_mdb_remote_del(vxlan, mdb_entry, remote); 1732 - } 1733 - 1734 - static void vxlan_mdb_entries_flush(struct vxlan_dev *vxlan) 1735 - { 1736 - struct vxlan_mdb_entry *mdb_entry; 1737 - struct hlist_node *tmp; 1738 - 1739 - /* The removal of an entry cannot trigger the removal of another entry 1740 - * since entries are always added to the head of the list. 1741 - */ 1742 - hlist_for_each_entry_safe(mdb_entry, tmp, &vxlan->mdb_list, mdb_node) { 1743 - vxlan_mdb_remotes_flush(vxlan, mdb_entry); 1744 - vxlan_mdb_entry_put(vxlan, mdb_entry); 1745 - } 1746 - } 1747 - 1748 1578 int vxlan_mdb_init(struct vxlan_dev *vxlan) 1749 1579 { 1750 1580 int err; ··· 1737 1613 1738 1614 void vxlan_mdb_fini(struct vxlan_dev *vxlan) 1739 1615 { 1740 - vxlan_mdb_entries_flush(vxlan); 1616 + struct vxlan_mdb_flush_desc desc = {}; 1617 + 1618 + vxlan_mdb_flush(vxlan, &desc); 1741 1619 WARN_ON_ONCE(vxlan->cfg.flags & VXLAN_F_MDB); 1742 1620 rhashtable_free_and_destroy(&vxlan->mdb_tbl, vxlan_mdb_check_empty, 1743 1621 NULL);
+2
drivers/net/vxlan/vxlan_private.h
··· 235 235 struct netlink_ext_ack *extack); 236 236 int vxlan_mdb_del(struct net_device *dev, struct nlattr *tb[], 237 237 struct netlink_ext_ack *extack); 238 + int vxlan_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[], 239 + struct netlink_ext_ack *extack); 238 240 int vxlan_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid, 239 241 u32 seq, struct netlink_ext_ack *extack); 240 242 struct vxlan_mdb_entry *vxlan_mdb_entry_skb_get(struct vxlan_dev *vxlan,
+6
include/linux/netdevice.h
··· 1329 1329 * int (*ndo_mdb_del)(struct net_device *dev, struct nlattr *tb[], 1330 1330 * struct netlink_ext_ack *extack); 1331 1331 * Deletes the MDB entry from dev. 1332 + * int (*ndo_mdb_del_bulk)(struct net_device *dev, struct nlattr *tb[], 1333 + * struct netlink_ext_ack *extack); 1334 + * Bulk deletes MDB entries from dev. 1332 1335 * int (*ndo_mdb_dump)(struct net_device *dev, struct sk_buff *skb, 1333 1336 * struct netlink_callback *cb); 1334 1337 * Dumps MDB entries from dev. The first argument (marker) in the netlink ··· 1614 1611 int (*ndo_mdb_del)(struct net_device *dev, 1615 1612 struct nlattr *tb[], 1616 1613 struct netlink_ext_ack *extack); 1614 + int (*ndo_mdb_del_bulk)(struct net_device *dev, 1615 + struct nlattr *tb[], 1616 + struct netlink_ext_ack *extack); 1617 1617 int (*ndo_mdb_dump)(struct net_device *dev, 1618 1618 struct sk_buff *skb, 1619 1619 struct netlink_callback *cb);
+1
include/uapi/linux/if_bridge.h
··· 757 757 MDBE_ATTR_VNI, 758 758 MDBE_ATTR_IFINDEX, 759 759 MDBE_ATTR_SRC_VNI, 760 + MDBE_ATTR_STATE_MASK, 760 761 __MDBE_ATTR_MAX, 761 762 }; 762 763 #define MDBE_ATTR_MAX (__MDBE_ATTR_MAX - 1)
+1
net/bridge/br_device.c
··· 471 471 .ndo_fdb_get = br_fdb_get, 472 472 .ndo_mdb_add = br_mdb_add, 473 473 .ndo_mdb_del = br_mdb_del, 474 + .ndo_mdb_del_bulk = br_mdb_del_bulk, 474 475 .ndo_mdb_dump = br_mdb_dump, 475 476 .ndo_mdb_get = br_mdb_get, 476 477 .ndo_bridge_getlink = br_getlink,
+133
net/bridge/br_mdb.c
··· 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),
+8
net/bridge/br_private.h
··· 1022 1022 struct netlink_ext_ack *extack); 1023 1023 int br_mdb_del(struct net_device *dev, struct nlattr *tb[], 1024 1024 struct netlink_ext_ack *extack); 1025 + int br_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[], 1026 + struct netlink_ext_ack *extack); 1025 1027 int br_mdb_dump(struct net_device *dev, struct sk_buff *skb, 1026 1028 struct netlink_callback *cb); 1027 1029 int br_mdb_get(struct net_device *dev, struct nlattr *tb[], u32 portid, u32 seq, ··· 1428 1426 1429 1427 static inline int br_mdb_del(struct net_device *dev, struct nlattr *tb[], 1430 1428 struct netlink_ext_ack *extack) 1429 + { 1430 + return -EOPNOTSUPP; 1431 + } 1432 + 1433 + static inline int br_mdb_del_bulk(struct net_device *dev, struct nlattr *tb[], 1434 + struct netlink_ext_ack *extack) 1431 1435 { 1432 1436 return -EOPNOTSUPP; 1433 1437 }
+59 -3
net/core/rtnetlink.c
··· 6410 6410 return dev->netdev_ops->ndo_mdb_add(dev, tb, nlh->nlmsg_flags, extack); 6411 6411 } 6412 6412 6413 + static int rtnl_validate_mdb_entry_del_bulk(const struct nlattr *attr, 6414 + struct netlink_ext_ack *extack) 6415 + { 6416 + struct br_mdb_entry *entry = nla_data(attr); 6417 + struct br_mdb_entry zero_entry = {}; 6418 + 6419 + if (nla_len(attr) != sizeof(struct br_mdb_entry)) { 6420 + NL_SET_ERR_MSG_ATTR(extack, attr, "Invalid attribute length"); 6421 + return -EINVAL; 6422 + } 6423 + 6424 + if (entry->state != MDB_PERMANENT && entry->state != MDB_TEMPORARY) { 6425 + NL_SET_ERR_MSG(extack, "Unknown entry state"); 6426 + return -EINVAL; 6427 + } 6428 + 6429 + if (entry->flags) { 6430 + NL_SET_ERR_MSG(extack, "Entry flags cannot be set"); 6431 + return -EINVAL; 6432 + } 6433 + 6434 + if (entry->vid >= VLAN_N_VID - 1) { 6435 + NL_SET_ERR_MSG(extack, "Invalid entry VLAN id"); 6436 + return -EINVAL; 6437 + } 6438 + 6439 + if (memcmp(&entry->addr, &zero_entry.addr, sizeof(entry->addr))) { 6440 + NL_SET_ERR_MSG(extack, "Entry address cannot be set"); 6441 + return -EINVAL; 6442 + } 6443 + 6444 + return 0; 6445 + } 6446 + 6447 + static const struct nla_policy mdba_del_bulk_policy[MDBA_SET_ENTRY_MAX + 1] = { 6448 + [MDBA_SET_ENTRY] = NLA_POLICY_VALIDATE_FN(NLA_BINARY, 6449 + rtnl_validate_mdb_entry_del_bulk, 6450 + sizeof(struct br_mdb_entry)), 6451 + [MDBA_SET_ENTRY_ATTRS] = { .type = NLA_NESTED }, 6452 + }; 6453 + 6413 6454 static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, 6414 6455 struct netlink_ext_ack *extack) 6415 6456 { 6457 + bool del_bulk = !!(nlh->nlmsg_flags & NLM_F_BULK); 6416 6458 struct nlattr *tb[MDBA_SET_ENTRY_MAX + 1]; 6417 6459 struct net *net = sock_net(skb->sk); 6418 6460 struct br_port_msg *bpm; 6419 6461 struct net_device *dev; 6420 6462 int err; 6421 6463 6422 - err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb, 6423 - MDBA_SET_ENTRY_MAX, mdba_policy, extack); 6464 + if (!del_bulk) 6465 + err = nlmsg_parse_deprecated(nlh, sizeof(*bpm), tb, 6466 + MDBA_SET_ENTRY_MAX, mdba_policy, 6467 + extack); 6468 + else 6469 + err = nlmsg_parse(nlh, sizeof(*bpm), tb, MDBA_SET_ENTRY_MAX, 6470 + mdba_del_bulk_policy, extack); 6424 6471 if (err) 6425 6472 return err; 6426 6473 ··· 6486 6439 if (NL_REQ_ATTR_CHECK(extack, NULL, tb, MDBA_SET_ENTRY)) { 6487 6440 NL_SET_ERR_MSG(extack, "Missing MDBA_SET_ENTRY attribute"); 6488 6441 return -EINVAL; 6442 + } 6443 + 6444 + if (del_bulk) { 6445 + if (!dev->netdev_ops->ndo_mdb_del_bulk) { 6446 + NL_SET_ERR_MSG(extack, "Device does not support MDB bulk deletion"); 6447 + return -EOPNOTSUPP; 6448 + } 6449 + return dev->netdev_ops->ndo_mdb_del_bulk(dev, tb, extack); 6489 6450 } 6490 6451 6491 6452 if (!dev->netdev_ops->ndo_mdb_del) { ··· 6741 6686 6742 6687 rtnl_register(PF_BRIDGE, RTM_GETMDB, rtnl_mdb_get, rtnl_mdb_dump, 0); 6743 6688 rtnl_register(PF_BRIDGE, RTM_NEWMDB, rtnl_mdb_add, NULL, 0); 6744 - rtnl_register(PF_BRIDGE, RTM_DELMDB, rtnl_mdb_del, NULL, 0); 6689 + rtnl_register(PF_BRIDGE, RTM_DELMDB, rtnl_mdb_del, NULL, 6690 + RTNL_FLAG_BULK_DEL_SUPPORTED); 6745 6691 }
+189 -2
tools/testing/selftests/net/forwarding/bridge_mdb.sh
··· 803 803 cfg_test_dump_common "L2" l2_grps_get 804 804 } 805 805 806 + # Check flush functionality with different parameters. 807 + cfg_test_flush() 808 + { 809 + local num_entries 810 + 811 + # Add entries with different attributes and check that they are all 812 + # flushed when the flush command is given with no parameters. 813 + 814 + # Different port. 815 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 vid 10 816 + bridge mdb add dev br0 port $swp2 grp 239.1.1.2 vid 10 817 + 818 + # Different VLAN ID. 819 + bridge mdb add dev br0 port $swp1 grp 239.1.1.3 vid 10 820 + bridge mdb add dev br0 port $swp1 grp 239.1.1.4 vid 20 821 + 822 + # Different routing protocol. 823 + bridge mdb add dev br0 port $swp1 grp 239.1.1.5 vid 10 proto bgp 824 + bridge mdb add dev br0 port $swp1 grp 239.1.1.6 vid 10 proto zebra 825 + 826 + # Different state. 827 + bridge mdb add dev br0 port $swp1 grp 239.1.1.7 vid 10 permanent 828 + bridge mdb add dev br0 port $swp1 grp 239.1.1.8 vid 10 temp 829 + 830 + bridge mdb flush dev br0 831 + num_entries=$(bridge mdb show dev br0 | wc -l) 832 + [[ $num_entries -eq 0 ]] 833 + check_err $? 0 "Not all entries flushed after flush all" 834 + 835 + # Check that when flushing by port only entries programmed with the 836 + # specified port are flushed and the rest are not. 837 + 838 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 vid 10 839 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 vid 10 840 + bridge mdb add dev br0 port br0 grp 239.1.1.1 vid 10 841 + 842 + bridge mdb flush dev br0 port $swp1 843 + 844 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1" 845 + check_fail $? "Entry not flushed by specified port" 846 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp2" 847 + check_err $? "Entry flushed by wrong port" 848 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port br0" 849 + check_err $? "Host entry flushed by wrong port" 850 + 851 + bridge mdb flush dev br0 port br0 852 + 853 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port br0" 854 + check_fail $? "Host entry not flushed by specified port" 855 + 856 + bridge mdb flush dev br0 857 + 858 + # Check that when flushing by VLAN ID only entries programmed with the 859 + # specified VLAN ID are flushed and the rest are not. 860 + 861 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 vid 10 862 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 vid 10 863 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 vid 20 864 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 vid 20 865 + 866 + bridge mdb flush dev br0 vid 10 867 + 868 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null 869 + check_fail $? "Entry not flushed by specified VLAN ID" 870 + bridge mdb get dev br0 grp 239.1.1.1 vid 20 &> /dev/null 871 + check_err $? "Entry flushed by wrong VLAN ID" 872 + 873 + bridge mdb flush dev br0 874 + 875 + # Check that all permanent entries are flushed when "permanent" is 876 + # specified and that temporary entries are not. 877 + 878 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 permanent vid 10 879 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 temp vid 10 880 + 881 + bridge mdb flush dev br0 permanent 882 + 883 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1" 884 + check_fail $? "Entry not flushed by \"permanent\" state" 885 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp2" 886 + check_err $? "Entry flushed by wrong state (\"permanent\")" 887 + 888 + bridge mdb flush dev br0 889 + 890 + # Check that all temporary entries are flushed when "nopermanent" is 891 + # specified and that permanent entries are not. 892 + 893 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 permanent vid 10 894 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 temp vid 10 895 + 896 + bridge mdb flush dev br0 nopermanent 897 + 898 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1" 899 + check_err $? "Entry flushed by wrong state (\"nopermanent\")" 900 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp2" 901 + check_fail $? "Entry not flushed by \"nopermanent\" state" 902 + 903 + bridge mdb flush dev br0 904 + 905 + # Check that L2 host entries are not flushed when "nopermanent" is 906 + # specified, but flushed when "permanent" is specified. 907 + 908 + bridge mdb add dev br0 port br0 grp 01:02:03:04:05:06 permanent vid 10 909 + 910 + bridge mdb flush dev br0 nopermanent 911 + 912 + bridge mdb get dev br0 grp 01:02:03:04:05:06 vid 10 &> /dev/null 913 + check_err $? "L2 host entry flushed by wrong state (\"nopermanent\")" 914 + 915 + bridge mdb flush dev br0 permanent 916 + 917 + bridge mdb get dev br0 grp 01:02:03:04:05:06 vid 10 &> /dev/null 918 + check_fail $? "L2 host entry not flushed by \"permanent\" state" 919 + 920 + bridge mdb flush dev br0 921 + 922 + # Check that IPv4 host entries are not flushed when "permanent" is 923 + # specified, but flushed when "nopermanent" is specified. 924 + 925 + bridge mdb add dev br0 port br0 grp 239.1.1.1 temp vid 10 926 + 927 + bridge mdb flush dev br0 permanent 928 + 929 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null 930 + check_err $? "IPv4 host entry flushed by wrong state (\"permanent\")" 931 + 932 + bridge mdb flush dev br0 nopermanent 933 + 934 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 &> /dev/null 935 + check_fail $? "IPv4 host entry not flushed by \"nopermanent\" state" 936 + 937 + bridge mdb flush dev br0 938 + 939 + # Check that IPv6 host entries are not flushed when "permanent" is 940 + # specified, but flushed when "nopermanent" is specified. 941 + 942 + bridge mdb add dev br0 port br0 grp ff0e::1 temp vid 10 943 + 944 + bridge mdb flush dev br0 permanent 945 + 946 + bridge mdb get dev br0 grp ff0e::1 vid 10 &> /dev/null 947 + check_err $? "IPv6 host entry flushed by wrong state (\"permanent\")" 948 + 949 + bridge mdb flush dev br0 nopermanent 950 + 951 + bridge mdb get dev br0 grp ff0e::1 vid 10 &> /dev/null 952 + check_fail $? "IPv6 host entry not flushed by \"nopermanent\" state" 953 + 954 + bridge mdb flush dev br0 955 + 956 + # Check that when flushing by routing protocol only entries programmed 957 + # with the specified routing protocol are flushed and the rest are not. 958 + 959 + bridge mdb add dev br0 port $swp1 grp 239.1.1.1 vid 10 proto bgp 960 + bridge mdb add dev br0 port $swp2 grp 239.1.1.1 vid 10 proto zebra 961 + bridge mdb add dev br0 port br0 grp 239.1.1.1 vid 10 962 + 963 + bridge mdb flush dev br0 proto bgp 964 + 965 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp1" 966 + check_fail $? "Entry not flushed by specified routing protocol" 967 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port $swp2" 968 + check_err $? "Entry flushed by wrong routing protocol" 969 + bridge mdb get dev br0 grp 239.1.1.1 vid 10 | grep -q "port br0" 970 + check_err $? "Host entry flushed by wrong routing protocol" 971 + 972 + bridge mdb flush dev br0 973 + 974 + # Test that an error is returned when trying to flush using unsupported 975 + # parameters. 976 + 977 + bridge mdb flush dev br0 src_vni 10 &> /dev/null 978 + check_fail $? "Managed to flush by source VNI" 979 + 980 + bridge mdb flush dev br0 dst 198.51.100.1 &> /dev/null 981 + check_fail $? "Managed to flush by destination IP" 982 + 983 + bridge mdb flush dev br0 dst_port 4789 &> /dev/null 984 + check_fail $? "Managed to flush by UDP destination port" 985 + 986 + bridge mdb flush dev br0 vni 10 &> /dev/null 987 + check_fail $? "Managed to flush by destination VNI" 988 + 989 + log_test "Flush tests" 990 + } 991 + 806 992 cfg_test() 807 993 { 808 994 cfg_test_host 809 995 cfg_test_port 810 996 cfg_test_dump 997 + cfg_test_flush 811 998 } 812 999 813 1000 __fwd_test_host_ip() ··· 1353 1166 ctrl_mldv2_is_in_test 1354 1167 } 1355 1168 1356 - if ! bridge mdb help 2>&1 | grep -q "get"; then 1357 - echo "SKIP: iproute2 too old, missing bridge mdb get support" 1169 + if ! bridge mdb help 2>&1 | grep -q "flush"; then 1170 + echo "SKIP: iproute2 too old, missing bridge mdb flush support" 1358 1171 exit $ksft_skip 1359 1172 fi 1360 1173
+199 -2
tools/testing/selftests/net/test_vxlan_mdb.sh
··· 79 79 dump_ipv6_ipv4 80 80 dump_ipv4_ipv6 81 81 dump_ipv6_ipv6 82 + flush 82 83 " 83 84 84 85 DATA_PATH_TESTS=" ··· 967 966 echo "-----------------------------------------------------------------" 968 967 969 968 dump_common $ns1 $local_addr $remote_prefix $fn 969 + } 970 + 971 + flush() 972 + { 973 + local num_entries 974 + 975 + echo 976 + echo "Control path: Flush" 977 + echo "-------------------" 978 + 979 + # Add entries with different attributes and check that they are all 980 + # flushed when the flush command is given with no parameters. 981 + 982 + # Different source VNI. 983 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 984 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.2 permanent dst 198.51.100.1 src_vni 10011" 985 + 986 + # Different routing protocol. 987 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.3 permanent proto bgp dst 198.51.100.1 src_vni 10010" 988 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.4 permanent proto zebra dst 198.51.100.1 src_vni 10010" 989 + 990 + # Different destination IP. 991 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.5 permanent dst 198.51.100.1 src_vni 10010" 992 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.6 permanent dst 198.51.100.2 src_vni 10010" 993 + 994 + # Different destination port. 995 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.7 permanent dst 198.51.100.1 dst_port 11111 src_vni 10010" 996 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.8 permanent dst 198.51.100.1 dst_port 22222 src_vni 10010" 997 + 998 + # Different VNI. 999 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.9 permanent dst 198.51.100.1 vni 10010 src_vni 10010" 1000 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.10 permanent dst 198.51.100.1 vni 10020 src_vni 10010" 1001 + 1002 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1003 + num_entries=$(bridge -n $ns1_v4 mdb show dev vx0 | wc -l) 1004 + [[ $num_entries -eq 0 ]] 1005 + log_test $? 0 "Flush all" 1006 + 1007 + # Check that entries are flushed when port is specified as the VXLAN 1008 + # device and that an error is returned when port is specified as a 1009 + # different net device. 1010 + 1011 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1012 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.2 src_vni 10010" 1013 + 1014 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 port vx0" 1015 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010" 1016 + log_test $? 254 "Flush by port" 1017 + 1018 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 port veth0" 1019 + log_test $? 255 "Flush by wrong port" 1020 + 1021 + # Check that when flushing by source VNI only entries programmed with 1022 + # the specified source VNI are flushed and the rest are not. 1023 + 1024 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1025 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.2 src_vni 10010" 1026 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10011" 1027 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.2 src_vni 10011" 1028 + 1029 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 src_vni 10010" 1030 + 1031 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010" 1032 + log_test $? 254 "Flush by specified source VNI" 1033 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10011" 1034 + log_test $? 0 "Flush by unspecified source VNI" 1035 + 1036 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1037 + 1038 + # Check that all entries are flushed when "permanent" is specified and 1039 + # that an error is returned when "nopermanent" is specified. 1040 + 1041 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1042 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.2 src_vni 10010" 1043 + 1044 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 permanent" 1045 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010" 1046 + log_test $? 254 "Flush by \"permanent\" state" 1047 + 1048 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 nopermanent" 1049 + log_test $? 255 "Flush by \"nopermanent\" state" 1050 + 1051 + # Check that when flushing by routing protocol only entries programmed 1052 + # with the specified routing protocol are flushed and the rest are not. 1053 + 1054 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent proto bgp dst 198.51.100.1 src_vni 10010" 1055 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent proto zebra dst 198.51.100.2 src_vni 10010" 1056 + 1057 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 proto bgp" 1058 + 1059 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \"proto bgp\"" 1060 + log_test $? 1 "Flush by specified routing protocol" 1061 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \"proto zebra\"" 1062 + log_test $? 0 "Flush by unspecified routing protocol" 1063 + 1064 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1065 + 1066 + # Check that when flushing by destination IP only entries programmed 1067 + # with the specified destination IP are flushed and the rest are not. 1068 + 1069 + # IPv4. 1070 + 1071 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1072 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.2 src_vni 10010" 1073 + 1074 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 dst 198.51.100.2" 1075 + 1076 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.2" 1077 + log_test $? 1 "Flush by specified destination IP - IPv4" 1078 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.1" 1079 + log_test $? 0 "Flush by unspecified destination IP - IPv4" 1080 + 1081 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1082 + 1083 + # IPv6. 1084 + 1085 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 2001:db8:1000::1 src_vni 10010" 1086 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 2001:db8:1000::2 src_vni 10010" 1087 + 1088 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 dst 2001:db8:1000::2" 1089 + 1090 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 2001:db8:1000::2" 1091 + log_test $? 1 "Flush by specified destination IP - IPv6" 1092 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 2001:db8:1000::1" 1093 + log_test $? 0 "Flush by unspecified destination IP - IPv6" 1094 + 1095 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1096 + 1097 + # Check that when flushing by UDP destination port only entries 1098 + # programmed with the specified port are flushed and the rest are not. 1099 + 1100 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst_port 11111 dst 198.51.100.1 src_vni 10010" 1101 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst_port 22222 dst 198.51.100.2 src_vni 10010" 1102 + 1103 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 dst_port 11111" 1104 + 1105 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \"dst_port 11111\"" 1106 + log_test $? 1 "Flush by specified UDP destination port" 1107 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \"dst_port 22222\"" 1108 + log_test $? 0 "Flush by unspecified UDP destination port" 1109 + 1110 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1111 + 1112 + # When not specifying a UDP destination port for an entry, traffic is 1113 + # encapsulated with the device's UDP destination port. Check that when 1114 + # flushing by the device's UDP destination port only entries programmed 1115 + # with this port are flushed and the rest are not. 1116 + 1117 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1118 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst_port 22222 dst 198.51.100.2 src_vni 10010" 1119 + 1120 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 dst_port 4789" 1121 + 1122 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.1" 1123 + log_test $? 1 "Flush by device's UDP destination port" 1124 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.2" 1125 + log_test $? 0 "Flush by unspecified UDP destination port" 1126 + 1127 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1128 + 1129 + # Check that when flushing by destination VNI only entries programmed 1130 + # with the specified destination VNI are flushed and the rest are not. 1131 + 1132 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent vni 20010 dst 198.51.100.1 src_vni 10010" 1133 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent vni 20011 dst 198.51.100.2 src_vni 10010" 1134 + 1135 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 vni 20010" 1136 + 1137 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \" vni 20010\"" 1138 + log_test $? 1 "Flush by specified destination VNI" 1139 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep \" vni 20011\"" 1140 + log_test $? 0 "Flush by unspecified destination VNI" 1141 + 1142 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1143 + 1144 + # When not specifying a destination VNI for an entry, traffic is 1145 + # encapsulated with the source VNI. Check that when flushing by a 1146 + # destination VNI that is equal to the source VNI only such entries are 1147 + # flushed and the rest are not. 1148 + 1149 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent dst 198.51.100.1 src_vni 10010" 1150 + run_cmd "bridge -n $ns1_v4 mdb add dev vx0 port vx0 grp 239.1.1.1 permanent vni 20010 dst 198.51.100.2 src_vni 10010" 1151 + 1152 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 vni 10010" 1153 + 1154 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.1" 1155 + log_test $? 1 "Flush by destination VNI equal to source VNI" 1156 + run_cmd "bridge -n $ns1_v4 -d -s mdb get dev vx0 grp 239.1.1.1 src_vni 10010 | grep 198.51.100.2" 1157 + log_test $? 0 "Flush by unspecified destination VNI" 1158 + 1159 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0" 1160 + 1161 + # Test that an error is returned when trying to flush using VLAN ID. 1162 + 1163 + run_cmd "bridge -n $ns1_v4 mdb flush dev vx0 vid 10" 1164 + log_test $? 255 "Flush by VLAN ID" 970 1165 } 971 1166 972 1167 ################################################################################ ··· 2489 2292 exit $ksft_skip 2490 2293 fi 2491 2294 2492 - bridge mdb help 2>&1 | grep -q "get" 2295 + bridge mdb help 2>&1 | grep -q "flush" 2493 2296 if [ $? -ne 0 ]; then 2494 - echo "SKIP: iproute2 bridge too old, missing VXLAN MDB get support" 2297 + echo "SKIP: iproute2 bridge too old, missing VXLAN MDB flush support" 2495 2298 exit $ksft_skip 2496 2299 fi 2497 2300