Skip to contentSkip to conversation

Fix routing metrics

PATCH Applied Steffen Klassert 2 participants 5 messages Mar 7, 2012 – Mar 8, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v3 cover Fix routing metrics

At the moment we initialize the routing metrics with the, on the inetpeer cached values in rt_init_metrics(). So if we have the metrics cached on the inetpeer, we ignore the user configured fib_metrics. This leads to the fact that we can't configure the mtu, hoplimit etc. if we have learned metrics cached.

The first patch invalidates the inetpeer tree along routing cache. This is done by replacing the old tree with a fresh initialized inet_peer_base when rt_cache_invalidate() is invoked. The old tree is added to a garbage collector list and destroyed later with a delayed work queue. I use a delay of 60 seconds, so rt_check_expire() ran at least on time before on a default configuration.

The second patch removes the redirect_genid handling. We don't need this any more because we remove the whole inetpeer tree when the redirects are invalidated.

Changes from v2:

- Fix possible null pointer dereference in ip_rt_redirect()

#1 lore raw

PATCH v3 1/2 inetpeer: Invalidate the inetpeer tree along with the routing cache

We initialize the routing metrics with the values cached on the inetpeer in rt_init_metrics(). So if we have the metrics cached on the inetpeer, we ignore the user configured fib_metrics.

To fix this issue, we replace the old tree with a fresh initialized inet_peer_base. The old tree is removed later with a delayed work queue.

---
 include/net/inetpeer.h |    3 ++
 net/ipv4/inetpeer.c    |   80 +++++++++++++++++++++++++++++++++++++++++++++++-
 net/ipv4/route.c       |    1 +
 3 files changed, 83 insertions(+), 1 deletions(-)
include/net/inetpeer.h +3 -0
index 06b795d..ff04a33 100644
@@ -41,6 +41,7 @@ struct inet_peer {
 	u32			pmtu_orig;
 	u32			pmtu_learned;
 	struct inetpeer_addr_base redirect_learned;
+	struct list_head	gc_list;
 	/*
 	 * Once inet_peer is queued for deletion (refcnt == -1), following fields
 	 * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp
@@ -96,6 +97,8 @@ static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr,
 extern void inet_putpeer(struct inet_peer *p);
 extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout);
 
+extern void inetpeer_invalidate_tree(int family);
+
 /*
  * temporary check to make sure we dont access rid, ip_id_count, tcp_ts,
  * tcp_ts_stamp if no refcount is taken on inet_peer
net/ipv4/inetpeer.c +79 -1

113 lines not on this page · raw message

net/ipv4/route.c +1 -0
index bcacf54..23ce0c1 100644
@@ -938,6 +938,7 @@ static void rt_cache_invalidate(struct net *net)
 	get_random_bytes(&shuffle, sizeof(shuffle));
 	atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
 	redirect_genid++;
+	inetpeer_invalidate_tree(AF_INET);
 }
 
 /*
Signature · 1 line
1.7.0.4
maintainer Applied
#2 lore raw

Re: [PATCH 1/2] inetpeer: Invalidate the inetpeer tree along with the routing cache

From: Steffen Klassert <[email protected]>
Date: Wed, 7 Mar 2012 08:20:26 +0100

Quoted 8 lines

We initialize the routing metrics with the values cached on the inetpeer in rt_init_metrics(). So if we have the metrics cached on the inetpeer, we ignore the user configured fib_metrics.

To fix this issue, we replace the old tree with a fresh initialized inet_peer_base. The old tree is removed later with a delayed work queue.

Applied, but I had to fixup trailing whitespace:

Review

Quoted 1 line
(quoted diff) +1 -0
+	spin_lock_bh(&gc_lock);	

at the end of that line.

#3 lore raw

PATCH v3 2/2 route: Remove redirect_genid

In reply to Steffen Klassert

As we invalidate the inetpeer tree along with the routing cache now, we don't need a genid to reset the redirect handling when the routing cache is flushed.

---
 include/net/inetpeer.h |    1 -
 net/ipv4/inetpeer.c    |    1 -
 net/ipv4/route.c       |   11 ++---------
 3 files changed, 2 insertions(+), 11 deletions(-)
include/net/inetpeer.h +0 -1
index ff04a33..b94765e 100644
@@ -35,7 +35,6 @@ struct inet_peer {
 
 	u32			metrics[RTAX_MAX];
 	u32			rate_tokens;	/* rate limiting for ICMP */
-	int			redirect_genid;
 	unsigned long		rate_last;
 	unsigned long		pmtu_expires;
 	u32			pmtu_orig;
net/ipv4/inetpeer.c +0 -1
index 897953d..4b7c16a 100644
@@ -498,7 +498,6 @@ relookup:
 		p->rate_last = 0;
 		p->pmtu_expires = 0;
 		p->pmtu_orig = 0;
-		p->redirect_genid = 0;
 		memset(&p->redirect_learned, 0, sizeof(p->redirect_learned));
 		INIT_LIST_HEAD(&p->gc_list);
 
net/ipv4/route.c +2 -9
index 23ce0c1..0197747 100644
@@ -132,7 +132,6 @@ static int ip_rt_mtu_expires __read_mostly	= 10 * 60 * HZ;
 static int ip_rt_min_pmtu __read_mostly		= 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly	= 256;
 static int rt_chain_length_max __read_mostly	= 20;
-static int redirect_genid;
 
 static struct delayed_work expires_work;
 static unsigned long expires_ljiffies;
@@ -937,7 +936,6 @@ static void rt_cache_invalidate(struct net *net)
 
 	get_random_bytes(&shuffle, sizeof(shuffle));
 	atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
-	redirect_genid++;
 	inetpeer_invalidate_tree(AF_INET);
 }
 
@@ -1486,10 +1484,8 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
 
 				peer = rt->peer;
 				if (peer) {
-					if (peer->redirect_learned.a4 != new_gw ||
-					    peer->redirect_genid != redirect_genid) {
+					if (peer->redirect_learned.a4 != new_gw) {
 						peer->redirect_learned.a4 = new_gw;
-						peer->redirect_genid = redirect_genid;
 						atomic_inc(&__rt_peer_genid);
 					}
 					check_peer_redir(&rt->dst, peer);
@@ -1794,8 +1790,6 @@ static void ipv4_validate_peer(struct rtable *rt)
 		if (peer) {
 			check_peer_pmtu(&rt->dst, peer);
 
-			if (peer->redirect_genid != redirect_genid)
-				peer->redirect_learned.a4 = 0;
 			if (peer->redirect_learned.a4 &&
 			    peer->redirect_learned.a4 != rt->rt_gateway)
 				check_peer_redir(&rt->dst, peer);
@@ -1959,8 +1953,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
 		dst_init_metrics(&rt->dst, peer->metrics, false);
 
 		check_peer_pmtu(&rt->dst, peer);
-		if (peer->redirect_genid != redirect_genid)
-			peer->redirect_learned.a4 = 0;
+
 		if (peer->redirect_learned.a4 &&
 		    peer->redirect_learned.a4 != rt->rt_gateway) {
 			rt->rt_gateway = peer->redirect_learned.a4;
Signature · 1 line
1.7.0.4
maintainer Applied
#4 lore raw

Re: [PATCH 2/2] route: Remove redirect_genid

From: Steffen Klassert <[email protected]>
Date: Wed, 7 Mar 2012 08:21:10 +0100

Quoted 5 lines

As we invalidate the inetpeer tree along with the routing cache now, we don't need a genid to reset the redirect handling when the routing cache is flushed.

Applied.