mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 00:53:34 +02:00
Merge branch 'vxlan-age-fdb-entries-based-on-rx-traffic'
Ido Schimmel says: ==================== vxlan: Age FDB entries based on Rx traffic tl;dr - This patchset prevents VXLAN FDB entries from lingering if traffic is only forwarded to a silent host. The VXLAN driver maintains two timestamps for each FDB entry: 'used' and 'updated'. The first is refreshed by both the Rx and Tx paths and the second is refreshed upon migration. The driver ages out entries according to their 'used' time which means that an entry can linger when traffic is only forwarded to a silent host that might have migrated to a different remote. This patchset solves the problem by adjusting the above semantics and aligning them to those of the bridge driver. That is, 'used' time is refreshed by the Tx path, 'updated' time is refresh by Rx path or user space updates and entries are aged out according to their 'updated' time. Patches #1-#2 perform small changes in how the 'used' and 'updated' fields are accessed. Patches #3-#5 refresh the 'updated' time where needed. Patch #6 flips the driver to age out FDB entries according to their 'updated' time. Patch #7 removes unnecessary updates to the 'used' time. Patch #8 extends a test case to cover aging of FDB entries in the presence of Tx traffic. ==================== Link: https://patch.msgid.link/20250204145549.1216254-1-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
3924fa995c
|
|
@ -227,9 +227,9 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan,
|
|||
be32_to_cpu(fdb->vni)))
|
||||
goto nla_put_failure;
|
||||
|
||||
ci.ndm_used = jiffies_to_clock_t(now - fdb->used);
|
||||
ci.ndm_used = jiffies_to_clock_t(now - READ_ONCE(fdb->used));
|
||||
ci.ndm_confirmed = 0;
|
||||
ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated);
|
||||
ci.ndm_updated = jiffies_to_clock_t(now - READ_ONCE(fdb->updated));
|
||||
ci.ndm_refcnt = 0;
|
||||
|
||||
if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
|
||||
|
|
@ -434,8 +434,12 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan,
|
|||
struct vxlan_fdb *f;
|
||||
|
||||
f = __vxlan_find_mac(vxlan, mac, vni);
|
||||
if (f && f->used != jiffies)
|
||||
f->used = jiffies;
|
||||
if (f) {
|
||||
unsigned long now = jiffies;
|
||||
|
||||
if (READ_ONCE(f->used) != now)
|
||||
WRITE_ONCE(f->used, now);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
|
@ -1009,12 +1013,10 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
|
|||
!(f->flags & NTF_VXLAN_ADDED_BY_USER)) {
|
||||
if (f->state != state) {
|
||||
f->state = state;
|
||||
f->updated = jiffies;
|
||||
notify = 1;
|
||||
}
|
||||
if (f->flags != fdb_flags) {
|
||||
f->flags = fdb_flags;
|
||||
f->updated = jiffies;
|
||||
notify = 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1048,12 +1050,13 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan,
|
|||
}
|
||||
|
||||
if (ndm_flags & NTF_USE)
|
||||
f->used = jiffies;
|
||||
WRITE_ONCE(f->updated, jiffies);
|
||||
|
||||
if (notify) {
|
||||
if (rd == NULL)
|
||||
rd = first_remote_rtnl(f);
|
||||
|
||||
WRITE_ONCE(f->updated, jiffies);
|
||||
err = vxlan_fdb_notify(vxlan, f, rd, RTM_NEWNEIGH,
|
||||
swdev_notify, extack);
|
||||
if (err)
|
||||
|
|
@ -1292,7 +1295,7 @@ int __vxlan_fdb_delete(struct vxlan_dev *vxlan,
|
|||
struct vxlan_fdb *f;
|
||||
int err = -ENOENT;
|
||||
|
||||
f = vxlan_find_mac(vxlan, addr, src_vni);
|
||||
f = __vxlan_find_mac(vxlan, addr, src_vni);
|
||||
if (!f)
|
||||
return err;
|
||||
|
||||
|
|
@ -1459,9 +1462,13 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
|
|||
ifindex = src_ifindex;
|
||||
#endif
|
||||
|
||||
f = vxlan_find_mac(vxlan, src_mac, vni);
|
||||
f = __vxlan_find_mac(vxlan, src_mac, vni);
|
||||
if (likely(f)) {
|
||||
struct vxlan_rdst *rdst = first_remote_rcu(f);
|
||||
unsigned long now = jiffies;
|
||||
|
||||
if (READ_ONCE(f->updated) != now)
|
||||
WRITE_ONCE(f->updated, now);
|
||||
|
||||
if (likely(vxlan_addr_equal(&rdst->remote_ip, src_ip) &&
|
||||
rdst->remote_ifindex == ifindex))
|
||||
|
|
@ -1481,7 +1488,6 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev,
|
|||
src_mac, &rdst->remote_ip.sa, &src_ip->sa);
|
||||
|
||||
rdst->remote_ip = *src_ip;
|
||||
f->updated = jiffies;
|
||||
vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL);
|
||||
} else {
|
||||
u32 hash_index = fdb_head_index(vxlan, src_mac, vni);
|
||||
|
|
@ -2852,7 +2858,7 @@ static void vxlan_cleanup(struct timer_list *t)
|
|||
if (f->flags & NTF_EXT_LEARNED)
|
||||
continue;
|
||||
|
||||
timeout = f->used + vxlan->cfg.age_interval * HZ;
|
||||
timeout = READ_ONCE(f->updated) + vxlan->cfg.age_interval * HZ;
|
||||
if (time_before_eq(timeout, jiffies)) {
|
||||
netdev_dbg(vxlan->dev,
|
||||
"garbage collect %pM\n",
|
||||
|
|
@ -4765,7 +4771,7 @@ vxlan_fdb_offloaded_set(struct net_device *dev,
|
|||
|
||||
spin_lock_bh(&vxlan->hash_lock[hash_index]);
|
||||
|
||||
f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
|
||||
f = __vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
|
||||
if (!f)
|
||||
goto out;
|
||||
|
||||
|
|
@ -4821,7 +4827,7 @@ vxlan_fdb_external_learn_del(struct net_device *dev,
|
|||
hash_index = fdb_head_index(vxlan, fdb_info->eth_addr, fdb_info->vni);
|
||||
spin_lock_bh(&vxlan->hash_lock[hash_index]);
|
||||
|
||||
f = vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
|
||||
f = __vxlan_find_mac(vxlan, fdb_info->eth_addr, fdb_info->vni);
|
||||
if (!f)
|
||||
err = -ENOENT;
|
||||
else if (f->flags & NTF_EXT_LEARNED)
|
||||
|
|
|
|||
|
|
@ -740,6 +740,8 @@ test_learning()
|
|||
|
||||
vxlan_flood_test $mac $dst 0 10 0
|
||||
|
||||
# The entry should age out when it only forwards traffic
|
||||
$MZ $h1 -c 50 -d 1sec -p 64 -b $mac -B $dst -t icmp -q &
|
||||
sleep 60
|
||||
|
||||
bridge fdb show brport vx1 | grep $mac | grep -q self
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user