summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorIdo Schimmel <idosch@nvidia.com>2021-03-04 10:57:53 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-17 17:03:35 +0100
commit3e66c16388f5e59ba73dd05e0667c10bc04ac29b (patch)
tree445d5109848e1927de6e4ed61e63c841d233bc0c /net
parent7f101d035deb1fdc71e6e433ea798017cee4b085 (diff)
downloadlinux-3e66c16388f5e59ba73dd05e0667c10bc04ac29b.tar.gz
linux-3e66c16388f5e59ba73dd05e0667c10bc04ac29b.tar.bz2
linux-3e66c16388f5e59ba73dd05e0667c10bc04ac29b.zip
nexthop: Do not flush blackhole nexthops when loopback goes down
commit 76c03bf8e2624076b88d93542d78e22d5345c88e upstream. As far as user space is concerned, blackhole nexthops do not have a nexthop device and therefore should not be affected by the administrative or carrier state of any netdev. However, when the loopback netdev goes down all the blackhole nexthops are flushed. This happens because internally the kernel associates blackhole nexthops with the loopback netdev. This behavior is both confusing to those not familiar with kernel internals and also diverges from the legacy API where blackhole IPv4 routes are not flushed when the loopback netdev goes down: # ip route add blackhole 198.51.100.0/24 # ip link set dev lo down # ip route show 198.51.100.0/24 blackhole 198.51.100.0/24 Blackhole IPv6 routes are flushed, but at least user space knows that they are associated with the loopback netdev: # ip -6 route show 2001:db8:1::/64 blackhole 2001:db8:1::/64 dev lo metric 1024 pref medium Fix this by only flushing blackhole nexthops when the loopback netdev is unregistered. Fixes: ab84be7e54fc ("net: Initial nexthop code") Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reported-by: Donald Sharp <sharpd@nvidia.com> Reviewed-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/nexthop.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c
index c2b7d43d92b0..f5f4369c131c 100644
--- a/net/ipv4/nexthop.c
+++ b/net/ipv4/nexthop.c
@@ -1065,7 +1065,7 @@ out:
/* rtnl */
/* remove all nexthops tied to a device being deleted */
-static void nexthop_flush_dev(struct net_device *dev)
+static void nexthop_flush_dev(struct net_device *dev, unsigned long event)
{
unsigned int hash = nh_dev_hashfn(dev->ifindex);
struct net *net = dev_net(dev);
@@ -1077,6 +1077,10 @@ static void nexthop_flush_dev(struct net_device *dev)
if (nhi->fib_nhc.nhc_dev != dev)
continue;
+ if (nhi->reject_nh &&
+ (event == NETDEV_DOWN || event == NETDEV_CHANGE))
+ continue;
+
remove_nexthop(net, nhi->nh_parent, NULL);
}
}
@@ -1794,11 +1798,11 @@ static int nh_netdev_event(struct notifier_block *this,
switch (event) {
case NETDEV_DOWN:
case NETDEV_UNREGISTER:
- nexthop_flush_dev(dev);
+ nexthop_flush_dev(dev, event);
break;
case NETDEV_CHANGE:
if (!(dev_get_flags(dev) & (IFF_RUNNING | IFF_LOWER_UP)))
- nexthop_flush_dev(dev);
+ nexthop_flush_dev(dev, event);
break;
case NETDEV_CHANGEMTU:
info_ext = ptr;