Commit 59fc137e authored by David S. Miller's avatar David S. Miller

Merge branch 'vxlan-Various-fixes'

Petr Machata says:

====================
vxlan: Various fixes

This patch set contains three fixes for the vxlan driver.

Patch #1 fixes handling of offload mark on replaced VXLAN FDB entries. A
way to trigger this is to replace the FDB entry with one that can not be
offloaded. A future patch set should make it possible to veto such FDB
changes. However the FDB might still fail to be offloaded due to another
issue, and the offload mark should reflect that.

Patch #2 fixes problems in __vxlan_dev_create() when a call to
rtnl_configure_link() fails. These failures would be tricky to hit on a
real system, the most likely vector is through an error in vxlan_open().
However, with the abovementioned vetoing patchset, vetoing the created
entry would trigger the same problems (and be easier to reproduce).

Patch #3 fixes a problem in vxlan_changelink(). In situations where the
default remote configured in the FDB table (if any) does not exactly
match the remote address configured at the VXLAN device, changing the
remote address breaks the default FDB entry. Patch #4 is then a self
test for this issue.

v3:
- Patch #2:
    - Reuse the same errout block for both cleanup paths. Use a bool to
      decide whether the unregister_netdevice() call should be made.

v2:
- Drop former patch #3
- Patch #2:
    - Delete the default entry before calling unregister_netdevice(). That
      takes care of former patch #3, hence tweak the commit message to
      mention that problem as well.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a9d6d897 55cbe079
...@@ -568,6 +568,7 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f, ...@@ -568,6 +568,7 @@ static int vxlan_fdb_replace(struct vxlan_fdb *f,
rd->remote_port = port; rd->remote_port = port;
rd->remote_vni = vni; rd->remote_vni = vni;
rd->remote_ifindex = ifindex; rd->remote_ifindex = ifindex;
rd->offloaded = false;
return 1; return 1;
} }
...@@ -3258,6 +3259,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, ...@@ -3258,6 +3259,7 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
struct vxlan_net *vn = net_generic(net, vxlan_net_id); struct vxlan_net *vn = net_generic(net, vxlan_net_id);
struct vxlan_dev *vxlan = netdev_priv(dev); struct vxlan_dev *vxlan = netdev_priv(dev);
struct vxlan_fdb *f = NULL; struct vxlan_fdb *f = NULL;
bool unregister = false;
int err; int err;
err = vxlan_dev_configure(net, dev, conf, false, extack); err = vxlan_dev_configure(net, dev, conf, false, extack);
...@@ -3283,12 +3285,11 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, ...@@ -3283,12 +3285,11 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
err = register_netdevice(dev); err = register_netdevice(dev);
if (err) if (err)
goto errout; goto errout;
unregister = true;
err = rtnl_configure_link(dev, NULL); err = rtnl_configure_link(dev, NULL);
if (err) { if (err)
unregister_netdevice(dev);
goto errout; goto errout;
}
/* notify default fdb entry */ /* notify default fdb entry */
if (f) if (f)
...@@ -3296,9 +3297,16 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev, ...@@ -3296,9 +3297,16 @@ static int __vxlan_dev_create(struct net *net, struct net_device *dev,
list_add(&vxlan->next, &vn->vxlan_list); list_add(&vxlan->next, &vn->vxlan_list);
return 0; return 0;
errout: errout:
/* unregister_netdevice() destroys the default FDB entry with deletion
* notification. But the addition notification was not sent yet, so
* destroy the entry by hand here.
*/
if (f) if (f)
vxlan_fdb_destroy(vxlan, f, false); vxlan_fdb_destroy(vxlan, f, false);
if (unregister)
unregister_netdevice(dev);
return err; return err;
} }
...@@ -3534,7 +3542,6 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -3534,7 +3542,6 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
struct vxlan_rdst *dst = &vxlan->default_dst; struct vxlan_rdst *dst = &vxlan->default_dst;
struct vxlan_rdst old_dst; struct vxlan_rdst old_dst;
struct vxlan_config conf; struct vxlan_config conf;
struct vxlan_fdb *f = NULL;
int err; int err;
err = vxlan_nl2conf(tb, data, err = vxlan_nl2conf(tb, data,
...@@ -3560,19 +3567,19 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -3560,19 +3567,19 @@ static int vxlan_changelink(struct net_device *dev, struct nlattr *tb[],
old_dst.remote_ifindex, 0); old_dst.remote_ifindex, 0);
if (!vxlan_addr_any(&dst->remote_ip)) { if (!vxlan_addr_any(&dst->remote_ip)) {
err = vxlan_fdb_create(vxlan, all_zeros_mac, err = vxlan_fdb_update(vxlan, all_zeros_mac,
&dst->remote_ip, &dst->remote_ip,
NUD_REACHABLE | NUD_PERMANENT, NUD_REACHABLE | NUD_PERMANENT,
NLM_F_APPEND | NLM_F_CREATE,
vxlan->cfg.dst_port, vxlan->cfg.dst_port,
dst->remote_vni, dst->remote_vni,
dst->remote_vni, dst->remote_vni,
dst->remote_ifindex, dst->remote_ifindex,
NTF_SELF, &f); NTF_SELF);
if (err) { if (err) {
spin_unlock_bh(&vxlan->hash_lock); spin_unlock_bh(&vxlan->hash_lock);
return err; return err;
} }
vxlan_fdb_notify(vxlan, f, first_remote_rtnl(f), RTM_NEWNEIGH);
} }
spin_unlock_bh(&vxlan->hash_lock); spin_unlock_bh(&vxlan->hash_lock);
} }
......
...@@ -7,6 +7,7 @@ CFLAGS += -I../../../../usr/include/ ...@@ -7,6 +7,7 @@ CFLAGS += -I../../../../usr/include/
TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh udpgso.sh ip_defrag.sh
TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh TEST_PROGS += udpgso_bench.sh fib_rule_tests.sh msg_zerocopy.sh psock_snd.sh
TEST_PROGS += test_vxlan_fdb_changelink.sh
TEST_PROGS_EXTENDED := in_netns.sh TEST_PROGS_EXTENDED := in_netns.sh
TEST_GEN_FILES = socket TEST_GEN_FILES = socket
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Check FDB default-remote handling across "ip link set".
check_remotes()
{
local what=$1; shift
local N=$(bridge fdb sh dev vx | grep 00:00:00:00:00:00 | wc -l)
echo -ne "expected two remotes after $what\t"
if [[ $N != 2 ]]; then
echo "[FAIL]"
EXIT_STATUS=1
else
echo "[ OK ]"
fi
}
ip link add name vx up type vxlan id 2000 dstport 4789
bridge fdb ap dev vx 00:00:00:00:00:00 dst 192.0.2.20 self permanent
bridge fdb ap dev vx 00:00:00:00:00:00 dst 192.0.2.30 self permanent
check_remotes "fdb append"
ip link set dev vx type vxlan remote 192.0.2.30
check_remotes "link set"
ip link del dev vx
exit $EXIT_STATUS
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment