netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction
@ 2015-10-30  8:23 Julian Anastasov
  2015-10-30  8:23 ` [PATCHv3 net 1/2] ipv4: fix to not remove local route on link down Julian Anastasov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Julian Anastasov @ 2015-10-30  8:23 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Andy Gospodarek

Fix two problems from the change that introduced RTNH_F_LINKDOWN
flag. The first patch deals with the removal of local route on
DOWN event. The second patch makes sure the RTNH_F_LINKDOWN
flag is properly updated on UP event because the DOWN event
sets it in all cases.

v2->v3:
- use bool for force var

v1->v2:
- forgot to add ifconfig dummy0 down in the test case
- split to 2 patches

Julian Anastasov (2):
  ipv4: fix to not remove local route on link down
  ipv4: update RTNH_F_LINKDOWN flag on UP event

 include/net/ip_fib.h     |  2 +-
 net/ipv4/fib_frontend.c  | 13 +++++++------
 net/ipv4/fib_semantics.c | 18 +++++++++++++++---
 3 files changed, 23 insertions(+), 10 deletions(-)

-- 
1.9.3

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCHv3 net 1/2] ipv4: fix to not remove local route on link down
  2015-10-30  8:23 [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Julian Anastasov
@ 2015-10-30  8:23 ` Julian Anastasov
  2015-10-30  8:23 ` [PATCHv3 net 2/2] ipv4: update RTNH_F_LINKDOWN flag on UP event Julian Anastasov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Julian Anastasov @ 2015-10-30  8:23 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Andy Gospodarek

When fib_netdev_event calls fib_disable_ip on NETDEV_DOWN event
we should not delete the local routes if the local address
is still present. The confusion comes from the fact that both
fib_netdev_event and fib_inetaddr_event use the NETDEV_DOWN
constant. Fix it by returning back the variable 'force'.

Steps to reproduce:
modprobe dummy
ifconfig dummy0 192.168.168.1 up
ifconfig dummy0 down
ip route list table local | grep dummy | grep host
local 192.168.168.1 dev dummy0  proto kernel  scope host  src 192.168.168.1

Fixes: 8a3d03166f19 ("net: track link-status of ipv4 nexthops")
Signed-off-by: Julian Anastasov <ja@ssi.bg>
---
 include/net/ip_fib.h     |  2 +-
 net/ipv4/fib_frontend.c  | 13 +++++++------
 net/ipv4/fib_semantics.c | 11 ++++++++---
 3 files changed, 16 insertions(+), 10 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 727d6e9..965fa5b 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -317,7 +317,7 @@ void fib_flush_external(struct net *net);
 
 /* Exported by fib_semantics.c */
 int ip_fib_check_default(__be32 gw, struct net_device *dev);
-int fib_sync_down_dev(struct net_device *dev, unsigned long event);
+int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
 int fib_sync_down_addr(struct net *net, __be32 local);
 int fib_sync_up(struct net_device *dev, unsigned int nh_flags);
 void fib_select_multipath(struct fib_result *res);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 690bcbc..457b2cd 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -1110,9 +1110,10 @@ static void nl_fib_lookup_exit(struct net *net)
 	net->ipv4.fibnl = NULL;
 }
 
-static void fib_disable_ip(struct net_device *dev, unsigned long event)
+static void fib_disable_ip(struct net_device *dev, unsigned long event,
+			   bool force)
 {
-	if (fib_sync_down_dev(dev, event))
+	if (fib_sync_down_dev(dev, event, force))
 		fib_flush(dev_net(dev));
 	rt_cache_flush(dev_net(dev));
 	arp_ifdown(dev);
@@ -1140,7 +1141,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
 			/* Last address was deleted from this interface.
 			 * Disable IP.
 			 */
-			fib_disable_ip(dev, event);
+			fib_disable_ip(dev, event, true);
 		} else {
 			rt_cache_flush(dev_net(dev));
 		}
@@ -1157,7 +1158,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
 	unsigned int flags;
 
 	if (event == NETDEV_UNREGISTER) {
-		fib_disable_ip(dev, event);
+		fib_disable_ip(dev, event, true);
 		rt_flush_dev(dev);
 		return NOTIFY_DONE;
 	}
@@ -1178,14 +1179,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
 		rt_cache_flush(net);
 		break;
 	case NETDEV_DOWN:
-		fib_disable_ip(dev, event);
+		fib_disable_ip(dev, event, false);
 		break;
 	case NETDEV_CHANGE:
 		flags = dev_get_flags(dev);
 		if (flags & (IFF_RUNNING | IFF_LOWER_UP))
 			fib_sync_up(dev, RTNH_F_LINKDOWN);
 		else
-			fib_sync_down_dev(dev, event);
+			fib_sync_down_dev(dev, event, false);
 		/* fall through */
 	case NETDEV_CHANGEMTU:
 		rt_cache_flush(net);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 064bd3c..2aa5b5e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1281,7 +1281,13 @@ int fib_sync_down_addr(struct net *net, __be32 local)
 	return ret;
 }
 
-int fib_sync_down_dev(struct net_device *dev, unsigned long event)
+/* Event              force Flags           Description
+ * NETDEV_CHANGE      0     LINKDOWN        Carrier OFF, not for scope host
+ * NETDEV_DOWN        0     LINKDOWN|DEAD   Link down, not for scope host
+ * NETDEV_DOWN        1     LINKDOWN|DEAD   Last address removed
+ * NETDEV_UNREGISTER  1     LINKDOWN|DEAD   Device removed
+ */
+int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force)
 {
 	int ret = 0;
 	int scope = RT_SCOPE_NOWHERE;
@@ -1290,8 +1296,7 @@ int fib_sync_down_dev(struct net_device *dev, unsigned long event)
 	struct hlist_head *head = &fib_info_devhash[hash];
 	struct fib_nh *nh;
 
-	if (event == NETDEV_UNREGISTER ||
-	    event == NETDEV_DOWN)
+	if (force)
 		scope = -1;
 
 	hlist_for_each_entry(nh, head, nh_hash) {
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCHv3 net 2/2] ipv4: update RTNH_F_LINKDOWN flag on UP event
  2015-10-30  8:23 [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Julian Anastasov
  2015-10-30  8:23 ` [PATCHv3 net 1/2] ipv4: fix to not remove local route on link down Julian Anastasov
@ 2015-10-30  8:23 ` Julian Anastasov
  2015-10-30 16:53 ` [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Andy Gospodarek
  2015-11-01 21:58 ` David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Julian Anastasov @ 2015-10-30  8:23 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, Andy Gospodarek

When nexthop is part of multipath route we should clear the
LINKDOWN flag when link goes UP or when first address is added.
This is needed because we always set LINKDOWN flag when DEAD flag
was set but now on UP the nexthop is not dead anymore. Examples when
LINKDOWN bit can be forgotten when no NETDEV_CHANGE is delivered:

- link goes down (LINKDOWN is set), then link goes UP and device
shows carrier OK but LINKDOWN remains set

- last address is deleted (LINKDOWN is set), then address is
added and device shows carrier OK but LINKDOWN remains set

Steps to reproduce:
modprobe dummy
ifconfig dummy0 192.168.168.1 up

here add a multipath route where one nexthop is for dummy0:

ip route add 1.2.3.4 nexthop dummy0 nexthop SOME_OTHER_DEVICE
ifconfig dummy0 down
ifconfig dummy0 up

now ip route shows nexthop that is not dead. Now set the sysctl var:

echo 1 > /proc/sys/net/ipv4/conf/dummy0/ignore_routes_with_linkdown

now ip route will show a dead nexthop because the forgotten
RTNH_F_LINKDOWN is propagated as RTNH_F_DEAD.

Fixes: 8a3d03166f19 ("net: track link-status of ipv4 nexthops")
Signed-off-by: Julian Anastasov <ja@ssi.bg>
---
 net/ipv4/fib_semantics.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 2aa5b5e..e966f85 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1445,6 +1445,13 @@ int fib_sync_up(struct net_device *dev, unsigned int nh_flags)
 	if (!(dev->flags & IFF_UP))
 		return 0;
 
+	if (nh_flags & RTNH_F_DEAD) {
+		unsigned int flags = dev_get_flags(dev);
+
+		if (flags & (IFF_RUNNING | IFF_LOWER_UP))
+			nh_flags |= RTNH_F_LINKDOWN;
+	}
+
 	prev_fi = NULL;
 	hash = fib_devindex_hashfn(dev->ifindex);
 	head = &fib_info_devhash[hash];
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction
  2015-10-30  8:23 [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Julian Anastasov
  2015-10-30  8:23 ` [PATCHv3 net 1/2] ipv4: fix to not remove local route on link down Julian Anastasov
  2015-10-30  8:23 ` [PATCHv3 net 2/2] ipv4: update RTNH_F_LINKDOWN flag on UP event Julian Anastasov
@ 2015-10-30 16:53 ` Andy Gospodarek
  2015-11-01 21:58 ` David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Andy Gospodarek @ 2015-10-30 16:53 UTC (permalink / raw)
  To: Julian Anastasov; +Cc: David Miller, netdev

On Fri, Oct 30, 2015 at 10:23:32AM +0200, Julian Anastasov wrote:
> Fix two problems from the change that introduced RTNH_F_LINKDOWN
> flag. The first patch deals with the removal of local route on
> DOWN event. The second patch makes sure the RTNH_F_LINKDOWN
> flag is properly updated on UP event because the DOWN event
> sets it in all cases.
> 
> v2->v3:
> - use bool for force var
> 
> v1->v2:
> - forgot to add ifconfig dummy0 down in the test case
> - split to 2 patches
> 
> Julian Anastasov (2):
>   ipv4: fix to not remove local route on link down
>   ipv4: update RTNH_F_LINKDOWN flag on UP event

I had a chance to test both of these this morning and they look good.
Sorry for the delay.  Thanks for making force a bool to cover the single
case -- good suggestion by DaveM.

Reviewed-by: Andy Gospodarek <gospo@cumulusnetworks.com>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction
  2015-10-30  8:23 [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Julian Anastasov
                   ` (2 preceding siblings ...)
  2015-10-30 16:53 ` [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Andy Gospodarek
@ 2015-11-01 21:58 ` David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2015-11-01 21:58 UTC (permalink / raw)
  To: ja; +Cc: netdev, gospo

From: Julian Anastasov <ja@ssi.bg>
Date: Fri, 30 Oct 2015 10:23:32 +0200

> Fix two problems from the change that introduced RTNH_F_LINKDOWN
> flag. The first patch deals with the removal of local route on
> DOWN event. The second patch makes sure the RTNH_F_LINKDOWN
> flag is properly updated on UP event because the DOWN event
> sets it in all cases.

Series applied and queued up for -stable, thanks Julian.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2015-11-01 21:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-30  8:23 [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Julian Anastasov
2015-10-30  8:23 ` [PATCHv3 net 1/2] ipv4: fix to not remove local route on link down Julian Anastasov
2015-10-30  8:23 ` [PATCHv3 net 2/2] ipv4: update RTNH_F_LINKDOWN flag on UP event Julian Anastasov
2015-10-30 16:53 ` [PATCHv3 net 0/2] ipv4: fix problems from the RTNH_F_LINKDOWN introduction Andy Gospodarek
2015-11-01 21:58 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).