Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH net-next] GRE over IPv6
From: Dmitry Kozlov @ 2012-07-28  7:17 UTC (permalink / raw)
  To: David Miller; +Cc: netdev

>Why have you submitted these patches two times?
Sorry, that was a mistake...

^ permalink raw reply

* Re: [PATCH 0/7] Deconstruct struct fib_result
From: David Miller @ 2012-07-28  6:55 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev
In-Reply-To: <CAKgT0UcuvFGJTCxMwVa+rEnQHaNg0V6EH4XpO29fXuFADSBpAQ@mail.gmail.com>

From: Alexander Duyck <alexander.duyck@gmail.com>
Date: Fri, 27 Jul 2012 23:41:50 -0700

> I was wondering why you couldn't wrap the tclassid value in result
> with an #ifdef CONFIG_IP_ROUTE_CLASSID so that it is stripped if you
> don't have that defined?

I am so over these feature ifdefs in the routing code, because
realistically everyone turns all the crap on.  Therefore we have to be
optimal when it's all on.

^ permalink raw reply

* Re: [PATCH 0/7] Deconstruct struct fib_result
From: Alexander Duyck @ 2012-07-28  6:41 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, netdev
In-Reply-To: <20120727.211814.1628871775065221675.davem@davemloft.net>

On Fri, Jul 27, 2012 at 9:18 PM, David Miller <davem@davemloft.net> wrote:
>
> This patch set tries to move towards reducing struct fib_result down
> to it's absolute minimum.
>
> The eventual idea is to make it so that fib_lookup() simply
> returns a "struct fib_nh *" and pointer encoded errnos, instead
> of writing into a complicated structure as the return value on
> the stack as is done now.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>

I was wondering why you couldn't wrap the tclassid value in result
with an #ifdef CONFIG_IP_ROUTE_CLASSID so that it is stripped if you
don't have that defined?  I did a quick grep through the kernel and it
seems like there are only a few spots that are accessing it without
the define being checked and most of those are just setting it to 0.

Also is there any specific reason to be passing the trie pointer to
check_leaf?  From what I can tell it looks like that it is just used
for updating the trie stats that are stripped if we want performance,
and the trie pointer should be retrievable via the fib table pointer
if we really wanted it anyway.

Thanks,

Alex

^ permalink raw reply

* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: Alexander Duyck @ 2012-07-28  5:45 UTC (permalink / raw)
  To: David Miller; +Cc: eric.dumazet, netdev
In-Reply-To: <20120727.211528.1280331721532176100.davem@davemloft.net>

On Fri, Jul 27, 2012 at 9:15 PM, David Miller <davem@davemloft.net> wrote:
> From: David Miller <davem@davemloft.net>
> Date: Thu, 26 Jul 2012 23:02:46 -0700 (PDT)
>
>> Therefore one area of simplification would be to just return a pointer
>> to the FIB nexthop, rather than the fib_info pointer and the nexthop
>> index.  We can get to the fib_info, if we need to, via the nh_parent
>> pointer of the nexthop.
>
> So I'm about to post an RFC set of patches which show this kind
> of simplification.  It gets fib_result down to two members:
>
>         u32             tclassid;
>         struct fib_nh   *nh;
>
> If I could get rid of that tclassid it would be really nice.  But
> that's hard because the tclassid is fetched from the fib_rule and
> all of that lookup path is abstracted behind a common layer
> that's shared between ipv4 and ipv6 so it's a bit of work changing
> arg conventions.
>
> These changes help, but only ever so slightly, in my testing.

I probably won't be able to do any real testing for the patches until
Monday, or at least I may let somebody else test the patches first
just to make sure they don't panic the system before I do anything
with them.

Thanks,

Alex

^ permalink raw reply

* Re: more interrupts (lower performance) in bare-metal compared with running VM
From: Eric Dumazet @ 2012-07-28  4:32 UTC (permalink / raw)
  To: sheng qiu; +Cc: kvm, linux-kernel, netdev
In-Reply-To: <CAB7xdi=DrE356=U1Jr1Z=ROo2X3XNM5uKcgiZJTKY+EdsTu7gw@mail.gmail.com>

On Fri, 2012-07-27 at 22:09 -0500, sheng qiu wrote:
> Hi all,
> 
> i am comparing network throughput performance under bare-metal case
> with that running VM with assigned-device (assigned NIC). i have two
> physical machines (each has a 10Gbit NIC), one is used as remote
> server (run netserver) and the other is used as the target tested one
> (run netperf with different send message size, TCP_STREAM test). the
> remote NIC is connected directly with the tested NIC, both are 10Gbit.
> fore bare-metal case, i enable 1 cpu core, for VM i also configure 1
> vcpu (the memory is sufficient for both bare-metal and VM case).  i
> run netperf for 120 seconds and got the following results:
> 
>                        send message    interrupts   throughput (mbit/s)
> bare-metal             256               10696290            1114.84
>                             512               10106786            1391.92
>                             1024              10071032           1508.09
>                             2048              4560857             3434.65
>                             4096              3292200             4762.26
>                             8192              3169801             4733.89
>                             16384            2780529              4892.6
> 

Are these interrupt counts taken on the receiver ?

> VM(assigned NIC)   256               3817904              2249.35
>                              512               3599007              4342.81
>                             1024              3005601              4134.69
>                              2048             2952122              4484
>                              4096             2682874              4566.34
>                              8192             2786719              4734.39
>                              16384           2603835              4540.47
> 
> as shown, the interrupts for bare-metal case is much more than the VM
> case for some message size. we also see the throughput for those
> situations is lower than VM case. it's strange that the bare-metal has
> lower performance than the VM case. Does anyone have comments on this?
> i am very confused.

Well, I think you answered to your question. High interrupt rates
are not good for throughput. They might be good for latencies.

Using a VM adds delays and several frames might be delivered per
interrupt.

Using bare metal is faster and only one frame is delivered by NIC per
interrupt.

Try TCP_RR instead of TCP_STREAM for example.

What NIC is it exactly ? It seems it has no coalescing or LRO strategy.

ethtool -k eth0
ethtool -c eth0

What kernel version as used, because 4892 Mbits is not line rate.



^ permalink raw reply

* [PATCH 7/7] ipv4: Perform multihop and default route resolution in check_leaf().
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


And thus eliminate two more members of fib_result.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h |    2 --
 net/ipv4/fib_trie.c  |   11 +++++++++--
 net/ipv4/route.c     |   17 -----------------
 3 files changed, 9 insertions(+), 21 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 66f5365..400c1a7 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -128,8 +128,6 @@ struct fib_table;
 struct fib_result {
 	u32			tclassid;
 	struct fib_nh		*nh;
-	struct fib_table	*table;
-	struct list_head	*fa_head;
 };
 
 struct fib_result_nl {
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 3d1d450..afd5048 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1391,9 +1391,16 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 				t->stats.semantic_match_passed++;
 #endif
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+				if (fi->fib_nhs > 1 && !flp->flowi4_oif)
+					nh = fib_select_multipath(nh);
+				else
+#endif
+				if (!li->plen && tb->tb_num_default > 1 &&
+				    fi->fib_type == RTN_UNICAST &&
+				    !flp->flowi4_oif)
+					nh = fib_select_default(nh, &li->falh, tb);
 				res->nh = nh;
-				res->table = tb;
-				res->fa_head = &li->falh;
 				if (!(fib_flags & FIB_LOOKUP_NOREF))
 					atomic_inc(&fi->fib_clntref);
 				return 0;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6b54323..2d1ede9 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1459,11 +1459,6 @@ static int ip_mkroute_input(struct sk_buff *skb,
 			    struct in_device *in_dev,
 			    __be32 daddr, __be32 saddr, u32 tos)
 {
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res->nh->nh_parent->fib_nhs > 1)
-		res->nh = fib_select_multipath(res->nh);
-#endif
-
 	/* create a routing cache entry */
 	return __mkroute_input(skb, res, in_dev, daddr, saddr, tos);
 }
@@ -1814,7 +1809,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 	res.tclassid	= 0;
 	res.nh		= NULL;
-	res.table	= NULL;
 
 	orig_oif = fl4->flowi4_oif;
 
@@ -1916,7 +1910,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 	if (fib_lookup(net, fl4, &res)) {
 		res.nh = NULL;
-		res.table = NULL;
 		if (fl4->flowi4_oif) {
 			/* Apparently, routing tables are wrong. Assume,
 			   that the destination is on link.
@@ -1962,16 +1955,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 		goto make_route;
 	}
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res.nh->nh_parent->fib_nhs > 1 && fl4->flowi4_oif == 0)
-		res.nh = fib_select_multipath(res.nh);
-	else
-#endif
-	if (!res.nh->nh_parent->fib_prefixlen &&
-	    res.table->tb_num_default > 1 &&
-	    type == RTN_UNICAST && !fl4->flowi4_oif)
-		res.nh = fib_select_default(res.nh, res.fa_head, res.table);
-
 	if (!fl4->saddr)
 		fl4->saddr = fib_res_prefsrc(net, &res);
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 6/7] ipv4: Make fib_select_multipath() not depend upon fib_result.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


Pass the arguments and return the result explicitly.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |    2 +-
 net/ipv4/fib_semantics.c |   15 +++++++--------
 net/ipv4/route.c         |    4 ++--
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 8a57513..66f5365 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -287,7 +287,7 @@ extern int fib_sync_down_dev(struct net_device *dev, int force);
 extern int fib_sync_down_addr(struct net *net, __be32 local);
 extern void fib_update_nh_saddrs(struct net_device *dev);
 extern int fib_sync_up(struct net_device *dev);
-extern void fib_select_multipath(struct fib_result *res);
+extern struct fib_nh *fib_select_multipath(struct fib_nh *res_nh);
 
 /* Exported by fib_trie.c */
 extern void fib_trie_init(void);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 4c7b55c..f83bef3 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1254,9 +1254,9 @@ int fib_sync_up(struct net_device *dev)
  * The algorithm is suboptimal, but it provides really
  * fair weighted route distribution.
  */
-void fib_select_multipath(struct fib_result *res)
+struct fib_nh *fib_select_multipath(struct fib_nh *res_nh)
 {
-	struct fib_info *fi = res->nh->nh_parent;
+	struct fib_info *fi = res_nh->nh_parent;
 	int w;
 
 	spin_lock_bh(&fib_multipath_lock);
@@ -1272,8 +1272,7 @@ void fib_select_multipath(struct fib_result *res)
 		if (power <= 0) {
 			spin_unlock_bh(&fib_multipath_lock);
 			/* Race condition: route has just become dead. */
-			res->nh = &fi->fib_nh[0];
-			return;
+			return &fi->fib_nh[0];
 		}
 	}
 
@@ -1291,15 +1290,15 @@ void fib_select_multipath(struct fib_result *res)
 			if (w <= 0) {
 				nexthop_nh->nh_power--;
 				fi->fib_power--;
-				res->nh = &fi->fib_nh[nhsel];
 				spin_unlock_bh(&fib_multipath_lock);
-				return;
+				return &fi->fib_nh[nhsel];
 			}
 		}
 	} endfor_nexthops(fi);
 
-	/* Race condition: route has just become dead. */
-	res->nh = &fi->fib_nh[0];
 	spin_unlock_bh(&fib_multipath_lock);
+
+	/* Race condition: route has just become dead. */
+	return &fi->fib_nh[0];
 }
 #endif
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9a247ff..6b54323 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1461,7 +1461,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
 {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	if (res->nh->nh_parent->fib_nhs > 1)
-		fib_select_multipath(res);
+		res->nh = fib_select_multipath(res->nh);
 #endif
 
 	/* create a routing cache entry */
@@ -1964,7 +1964,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 	if (res.nh->nh_parent->fib_nhs > 1 && fl4->flowi4_oif == 0)
-		fib_select_multipath(&res);
+		res.nh = fib_select_multipath(res.nh);
 	else
 #endif
 	if (!res.nh->nh_parent->fib_prefixlen &&
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 5/7] ipv4: Make fib_select_default() not depend upon fib_result.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


Pass the arguments and return the result explicitly.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |    3 ++-
 net/ipv4/fib_semantics.c |   19 +++++++++----------
 net/ipv4/route.c         |    2 +-
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 43be7230..8a57513 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -267,7 +267,8 @@ extern __be32 fib_compute_spec_dst(struct sk_buff *skb);
 extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 			       u8 tos, int oif, struct net_device *dev,
 			       struct in_device *idev, u32 *itag);
-extern void fib_select_default(struct fib_result *res);
+extern struct fib_nh *fib_select_default(struct fib_nh *nh, struct list_head *fa_head,
+					 struct fib_table *tb);
 #ifdef CONFIG_IP_ROUTE_CLASSID
 static inline int fib_num_tclassid_users(struct net *net)
 {
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index bf4c809..4c7b55c 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1134,11 +1134,10 @@ int fib_sync_down_dev(struct net_device *dev, int force)
 }
 
 /* Must be invoked inside of an RCU protected region.  */
-void fib_select_default(struct fib_result *res)
+struct fib_nh *fib_select_default(struct fib_nh *res_nh, struct list_head *fa_head,
+				  struct fib_table *tb)
 {
 	struct fib_nh *nh = NULL, *last_resort = NULL;
-	struct list_head *fa_head = res->fa_head;
-	struct fib_table *tb = res->table;
 	int order = -1, last_idx = -1;
 	struct fib_alias *fa;
 
@@ -1146,12 +1145,12 @@ void fib_select_default(struct fib_result *res)
 		struct fib_nh *next_nh = &fa->fa_info->fib_nh[0];
 
 		if ((next_nh->nh_parent->fib_scope !=
-		     res->nh->nh_parent->fib_scope) ||
+		     res_nh->nh_parent->fib_scope) ||
 		    next_nh->nh_parent->fib_type != RTN_UNICAST)
 			continue;
 
 		if (next_nh->nh_parent->fib_priority >
-		    res->nh->nh_parent->fib_priority)
+		    res_nh->nh_parent->fib_priority)
 			break;
 
 		if (!next_nh->nh_gw || next_nh->nh_scope != RT_SCOPE_LINK)
@@ -1160,11 +1159,11 @@ void fib_select_default(struct fib_result *res)
 		fib_alias_accessed(fa);
 
 		if (nh == NULL) {
-			if (next_nh != res->nh)
+			if (next_nh != res_nh)
 				break;
 		} else if (!fib_detect_death(nh, order, &last_resort,
 					     &last_idx, tb->tb_default)) {
-			res->nh = nh;
+			res_nh = nh;
 			tb->tb_default = order;
 			goto out;
 		}
@@ -1179,16 +1178,16 @@ void fib_select_default(struct fib_result *res)
 
 	if (!fib_detect_death(nh, order, &last_resort, &last_idx,
 			      tb->tb_default)) {
-		res->nh = nh;
+		res_nh = nh;
 		tb->tb_default = order;
 		goto out;
 	}
 
 	if (last_idx >= 0)
-		res->nh = last_resort;
+		res_nh = last_resort;
 	tb->tb_default = last_idx;
 out:
-	return;
+	return res_nh;
 }
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 597fbc0..9a247ff 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1970,7 +1970,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	if (!res.nh->nh_parent->fib_prefixlen &&
 	    res.table->tb_num_default > 1 &&
 	    type == RTN_UNICAST && !fl4->flowi4_oif)
-		fib_select_default(&res);
+		res.nh = fib_select_default(res.nh, res.fa_head, res.table);
 
 	if (!fl4->saddr)
 		fl4->saddr = fib_res_prefsrc(net, &res);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 4/7] ipv4: Store prefixlen in fib_info.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


The shrinks fib_result by 4 bytes since we don't have to write
it there any longer.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |    8 +++-----
 net/ipv4/fib_frontend.c  |    2 +-
 net/ipv4/fib_semantics.c |    6 ++++--
 net/ipv4/fib_trie.c      |    1 -
 net/ipv4/route.c         |    4 ++--
 5 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 3cb9e45..43be7230 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -96,11 +96,13 @@ struct fib_info {
 	struct net		*fib_net;
 	int			fib_treeref;
 	atomic_t		fib_clntref;
-	unsigned int		fib_flags;
+	unsigned char		fib_flags;
 	unsigned char		fib_dead;
 	unsigned char		fib_protocol;
 	unsigned char		fib_scope;
 	unsigned char		fib_type;
+	unsigned char		fib_prefixlen;
+	unsigned short		__pad;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
 	u32			*fib_metrics;
@@ -124,10 +126,6 @@ struct fib_rule;
 
 struct fib_table;
 struct fib_result {
-	unsigned char		prefixlen;
-	unsigned char		__pad;
-	unsigned char		__pad2;
-	unsigned char		__pad3;
 	u32			tclassid;
 	struct fib_nh		*nh;
 	struct fib_table	*table;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 495b540..1e1907c 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -943,7 +943,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 			fi = nh->nh_parent;
 			nhsel = nh - &fi->fib_nh[0];
 
-			frn->prefixlen = res.prefixlen;
+			frn->prefixlen = fi->fib_prefixlen;
 			frn->nh_sel = nhsel;
 			frn->type = fi->fib_type;
 			frn->scope = fi->fib_scope;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 13b801a..bf4c809 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -252,8 +252,8 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
 	unsigned int mask = (fib_info_hash_size - 1);
 	unsigned int val = fi->fib_nhs;
 
-	val ^= ((fi->fib_protocol << 16) | (fi->fib_scope << 8) |
-		fi->fib_type);
+	val ^= ((fi->fib_protocol << 24) | (fi->fib_scope << 16) |
+		(fi->fib_type << 8) | fi->fib_prefixlen);
 	val ^= (__force u32)fi->fib_prefsrc;
 	val ^= fi->fib_priority;
 	for_nexthops(fi) {
@@ -281,6 +281,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_scope == fi->fib_scope &&
 		    nfi->fib_type == fi->fib_type &&
+		    nfi->fib_prefixlen == fi->fib_prefixlen &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
 		    memcmp(nfi->fib_metrics, fi->fib_metrics,
@@ -801,6 +802,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 	fi->fib_protocol = cfg->fc_protocol;
 	fi->fib_scope = cfg->fc_scope;
 	fi->fib_type = cfg->fc_type;
+	fi->fib_prefixlen = cfg->fc_dst_len;
 	fi->fib_flags = cfg->fc_flags;
 	fi->fib_priority = cfg->fc_priority;
 	fi->fib_prefsrc = cfg->fc_prefsrc;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index f812f06..3d1d450 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1391,7 +1391,6 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 				t->stats.semantic_match_passed++;
 #endif
-				res->prefixlen = li->plen;
 				res->nh = nh;
 				res->table = tb;
 				res->fa_head = &li->falh;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6d4353b..597fbc0 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1740,7 +1740,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 		 * default one, but do not gateway in this case.
 		 * Yes, it is hack.
 		 */
-		if (nh && res->prefixlen < 4)
+		if (nh && nh->nh_parent->fib_prefixlen < 4)
 			nh = NULL;
 	}
 
@@ -1967,7 +1967,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 		fib_select_multipath(&res);
 	else
 #endif
-	if (!res.prefixlen &&
+	if (!res.nh->nh_parent->fib_prefixlen &&
 	    res.table->tb_num_default > 1 &&
 	    type == RTN_UNICAST && !fl4->flowi4_oif)
 		fib_select_default(&res);
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/7] ipv4: Store route type in fib_info.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


This removes another value recorded in the fib_result return struct.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |    3 ++-
 net/ipv4/devinet.c       |    2 +-
 net/ipv4/fib_frontend.c  |   10 +++++-----
 net/ipv4/fib_lookup.h    |    6 ++----
 net/ipv4/fib_semantics.c |   17 ++++++++++-------
 net/ipv4/fib_trie.c      |   20 ++++++++------------
 net/ipv4/route.c         |   36 ++++++++++++++++++++----------------
 7 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 847a46b..3cb9e45 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -100,6 +100,7 @@ struct fib_info {
 	unsigned char		fib_dead;
 	unsigned char		fib_protocol;
 	unsigned char		fib_scope;
+	unsigned char		fib_type;
 	__be32			fib_prefsrc;
 	u32			fib_priority;
 	u32			*fib_metrics;
@@ -125,8 +126,8 @@ struct fib_table;
 struct fib_result {
 	unsigned char		prefixlen;
 	unsigned char		__pad;
-	unsigned char		type;
 	unsigned char		__pad2;
+	unsigned char		__pad3;
 	u32			tclassid;
 	struct fib_nh		*nh;
 	struct fib_table	*table;
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 1baaa53..1595a67d 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -163,7 +163,7 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 		local = fib_get_table(net, RT_TABLE_LOCAL);
 		if (local &&
 		    !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
-		    res.type == RTN_LOCAL)
+		    res.nh->nh_parent->fib_type == RTN_LOCAL)
 			result = res.nh->nh_dev;
 	}
 	if (result && devref)
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index e02390d..495b540 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -175,7 +175,7 @@ static inline unsigned int __inet_dev_addr_type(struct net *net,
 		rcu_read_lock();
 		if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
 			if (!dev || dev == res.nh->nh_dev)
-				ret = res.type;
+				ret = res.nh->nh_parent->fib_type;
 		}
 		rcu_read_unlock();
 	}
@@ -267,8 +267,8 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 	net = dev_net(dev);
 	if (fib_lookup(net, &fl4, &res))
 		goto last_resort;
-	if (res.type != RTN_UNICAST) {
-		if (res.type != RTN_LOCAL || !accept_local)
+	if (res.nh->nh_parent->fib_type != RTN_UNICAST) {
+		if (res.nh->nh_parent->fib_type != RTN_LOCAL || !accept_local)
 			goto e_inval;
 	}
 	fib_combine_itag(itag, &res);
@@ -295,7 +295,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 
 	ret = 0;
 	if (fib_lookup(net, &fl4, &res) == 0) {
-		if (res.type == RTN_UNICAST)
+		if (res.nh->nh_parent->fib_type == RTN_UNICAST)
 			ret = res.nh->nh_scope >= RT_SCOPE_HOST;
 	}
 	return ret;
@@ -945,7 +945,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 
 			frn->prefixlen = res.prefixlen;
 			frn->nh_sel = nhsel;
-			frn->type = res.type;
+			frn->type = fi->fib_type;
 			frn->scope = fi->fib_scope;
 		}
 		rcu_read_unlock();
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index 5f110b6..3dd6b49 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -9,7 +9,6 @@ struct fib_alias {
 	struct list_head	fa_list;
 	struct fib_info		*fa_info;
 	u8			fa_tos;
-	u8			fa_type;
 	u8			fa_state;
 	struct rcu_head		rcu;
 };
@@ -28,9 +27,8 @@ extern void fib_release_info(struct fib_info *);
 extern struct fib_info *fib_create_info(struct fib_config *cfg);
 extern int fib_nh_match(struct fib_config *cfg, struct fib_info *fi);
 extern int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-			 u32 tb_id, u8 type, __be32 dst,
-			 int dst_len, u8 tos, struct fib_info *fi,
-			 unsigned int);
+			 u32 tb_id, __be32 dst, int dst_len, u8 tos,
+			 struct fib_info *fi, unsigned int);
 extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		      int dst_len, u32 tb_id, struct nl_info *info,
 		      unsigned int nlm_flags);
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 6f73403..13b801a 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -252,7 +252,8 @@ static inline unsigned int fib_info_hashfn(const struct fib_info *fi)
 	unsigned int mask = (fib_info_hash_size - 1);
 	unsigned int val = fi->fib_nhs;
 
-	val ^= (fi->fib_protocol << 8) | fi->fib_scope;
+	val ^= ((fi->fib_protocol << 16) | (fi->fib_scope << 8) |
+		fi->fib_type);
 	val ^= (__force u32)fi->fib_prefsrc;
 	val ^= fi->fib_priority;
 	for_nexthops(fi) {
@@ -279,6 +280,7 @@ static struct fib_info *fib_find_info(const struct fib_info *nfi)
 			continue;
 		if (nfi->fib_protocol == fi->fib_protocol &&
 		    nfi->fib_scope == fi->fib_scope &&
+		    nfi->fib_type == fi->fib_type &&
 		    nfi->fib_prefsrc == fi->fib_prefsrc &&
 		    nfi->fib_priority == fi->fib_priority &&
 		    memcmp(nfi->fib_metrics, fi->fib_metrics,
@@ -359,8 +361,7 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		goto errout;
 
 	err = fib_dump_info(skb, info->pid, seq, event, tb_id,
-			    fa->fa_type, key, dst_len,
-			    fa->fa_tos, fa->fa_info, nlm_flags);
+			    key, dst_len, fa->fa_tos, fa->fa_info, nlm_flags);
 	if (err < 0) {
 		/* -EMSGSIZE implies BUG in fib_nlmsg_size() */
 		WARN_ON(err == -EMSGSIZE);
@@ -610,7 +611,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 			}
 		}
 		err = -EINVAL;
-		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
+		if (res.nh->nh_parent->fib_type != RTN_UNICAST &&
+		    res.nh->nh_parent->fib_type != RTN_LOCAL)
 			goto out;
 		nh->nh_scope = res.nh->nh_parent->fib_scope;
 		nh->nh_oif = res.nh->nh_oif;
@@ -798,6 +800,7 @@ struct fib_info *fib_create_info(struct fib_config *cfg)
 	fi->fib_net = hold_net(net);
 	fi->fib_protocol = cfg->fc_protocol;
 	fi->fib_scope = cfg->fc_scope;
+	fi->fib_type = cfg->fc_type;
 	fi->fib_flags = cfg->fc_flags;
 	fi->fib_priority = cfg->fc_priority;
 	fi->fib_prefsrc = cfg->fc_prefsrc;
@@ -957,7 +960,7 @@ failure:
 }
 
 int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
-		  u32 tb_id, u8 type, __be32 dst, int dst_len, u8 tos,
+		  u32 tb_id, __be32 dst, int dst_len, u8 tos,
 		  struct fib_info *fi, unsigned int flags)
 {
 	struct nlmsghdr *nlh;
@@ -978,7 +981,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 		rtm->rtm_table = RT_TABLE_COMPAT;
 	if (nla_put_u32(skb, RTA_TABLE, tb_id))
 		goto nla_put_failure;
-	rtm->rtm_type = type;
+	rtm->rtm_type = fi->fib_type;
 	rtm->rtm_flags = fi->fib_flags;
 	rtm->rtm_scope = fi->fib_scope;
 	rtm->rtm_protocol = fi->fib_protocol;
@@ -1142,7 +1145,7 @@ void fib_select_default(struct fib_result *res)
 
 		if ((next_nh->nh_parent->fib_scope !=
 		     res->nh->nh_parent->fib_scope) ||
-		    fa->fa_type != RTN_UNICAST)
+		    next_nh->nh_parent->fib_type != RTN_UNICAST)
 			continue;
 
 		if (next_nh->nh_parent->fib_priority >
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 83cf215..f812f06 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1253,8 +1253,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 				break;
 			if (fa->fa_info->fib_priority != fi->fib_priority)
 				break;
-			if (fa->fa_type == cfg->fc_type &&
-			    fa->fa_info == fi) {
+			if (fa->fa_info == fi) {
 				fa_match = fa;
 				break;
 			}
@@ -1278,7 +1277,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 			fi_drop = fa->fa_info;
 			new_fa->fa_tos = fa->fa_tos;
 			new_fa->fa_info = fi;
-			new_fa->fa_type = cfg->fc_type;
 			state = fa->fa_state;
 			new_fa->fa_state = state & ~FA_S_ACCESSED;
 
@@ -1314,7 +1312,6 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 
 	new_fa->fa_info = fi;
 	new_fa->fa_tos = tos;
-	new_fa->fa_type = cfg->fc_type;
 	new_fa->fa_state = 0;
 	/*
 	 * Insert new entry to the list.
@@ -1374,7 +1371,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 			if (fa->fa_info->fib_scope < flp->flowi4_scope)
 				continue;
 			fib_alias_accessed(fa);
-			err = fib_props[fa->fa_type].error;
+			err = fib_props[fi->fib_type].error;
 			if (err) {
 #ifdef CONFIG_IP_FIB_TRIE_STATS
 				t->stats.semantic_match_passed++;
@@ -1395,7 +1392,6 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 				t->stats.semantic_match_passed++;
 #endif
 				res->prefixlen = li->plen;
-				res->type = fa->fa_type;
 				res->nh = nh;
 				res->table = tb;
 				res->fa_head = &li->falh;
@@ -1670,7 +1666,8 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
 		if (fa->fa_tos != tos)
 			break;
 
-		if ((!cfg->fc_type || fa->fa_type == cfg->fc_type) &&
+		if ((!cfg->fc_type ||
+		     fa->fa_info->fib_type == cfg->fc_type) &&
 		    (cfg->fc_scope == RT_SCOPE_NOWHERE ||
 		     fa->fa_info->fib_scope == cfg->fc_scope) &&
 		    (!cfg->fc_prefsrc ||
@@ -1873,7 +1870,6 @@ static int fn_trie_dump_fa(t_key key, int plen, struct list_head *fah,
 				  cb->nlh->nlmsg_seq,
 				  RTM_NEWROUTE,
 				  tb->tb_id,
-				  fa->fa_type,
 				  xkey,
 				  plen,
 				  fa->fa_tos,
@@ -2394,7 +2390,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
 					   rtn_scope(buf1, sizeof(buf1),
 						     fa->fa_info->fib_scope),
 					   rtn_type(buf2, sizeof(buf2),
-						    fa->fa_type));
+						    fa->fa_info->fib_type));
 				if (fa->fa_tos)
 					seq_printf(seq, " tos=%d", fa->fa_tos);
 				seq_putc(seq, '\n');
@@ -2546,11 +2542,11 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
 
 		list_for_each_entry_rcu(fa, &li->falh, fa_list) {
 			const struct fib_info *fi = fa->fa_info;
-			unsigned int flags = fib_flag_trans(fa->fa_type, mask, fi);
+			unsigned int flags = fib_flag_trans(fi->fib_type, mask, fi);
 			int len;
 
-			if (fa->fa_type == RTN_BROADCAST
-			    || fa->fa_type == RTN_MULTICAST)
+			if (fi->fib_type == RTN_BROADCAST ||
+			    fi->fib_type == RTN_MULTICAST)
 				continue;
 
 			if (fi)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 0b3277c..6d4353b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1436,7 +1436,7 @@ static int __mkroute_input(struct sk_buff *skb,
 
 	rth->rt_genid = rt_genid(dev_net(rth->dst.dev));
 	rth->rt_flags = flags;
-	rth->rt_type = res->type;
+	rth->rt_type = res->nh->nh_parent->fib_type;
 	rth->rt_is_input = 1;
 	rth->rt_iif 	= 0;
 	rth->rt_pmtu	= 0;
@@ -1445,7 +1445,7 @@ static int __mkroute_input(struct sk_buff *skb,
 	rth->dst.input = ip_forward;
 	rth->dst.output = ip_output;
 
-	rt_set_nexthop(rth, daddr, res, NULL, nh, res->type, itag);
+	rt_set_nexthop(rth, daddr, res, NULL, nh, rth->rt_type, itag);
 	skb_dst_set(skb, &rth->dst);
 out:
 	err = 0;
@@ -1491,6 +1491,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	int		err = -EINVAL;
 	struct net    *net = dev_net(dev);
 	bool do_cache;
+	u8 type;
 
 	/* IP on this device is disabled. */
 
@@ -1541,10 +1542,11 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	RT_CACHE_STAT_INC(in_slow_tot);
 
-	if (res.type == RTN_BROADCAST)
+	type = res.nh->nh_parent->fib_type;
+	if (type == RTN_BROADCAST)
 		goto brd_input;
 
-	if (res.type == RTN_LOCAL) {
+	if (type == RTN_LOCAL) {
 		err = fib_validate_source(skb, saddr, daddr, tos,
 					  net->loopback_dev->ifindex,
 					  dev, in_dev, &itag);
@@ -1555,7 +1557,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 	if (!IN_DEV_FORWARD(in_dev))
 		goto no_route;
-	if (res.type != RTN_UNICAST)
+	if (type != RTN_UNICAST)
 		goto martian_destination;
 
 	err = ip_mkroute_input(skb, &res, &fl4, in_dev, daddr, saddr, tos);
@@ -1572,7 +1574,7 @@ brd_input:
 			goto martian_source_keep_err;
 	}
 	flags |= RTCF_BROADCAST;
-	res.type = RTN_BROADCAST;
+	type = RTN_BROADCAST;
 	RT_CACHE_STAT_INC(in_brd);
 
 local_input:
@@ -1602,12 +1604,12 @@ local_input:
 
 	rth->rt_genid = rt_genid(net);
 	rth->rt_flags 	= flags|RTCF_LOCAL;
-	rth->rt_type	= res.type;
+	rth->rt_type	= type;
 	rth->rt_is_input = 1;
 	rth->rt_iif	= 0;
 	rth->rt_pmtu	= 0;
 	rth->rt_gateway	= 0;
-	if (res.type == RTN_UNREACHABLE) {
+	if (type == RTN_UNREACHABLE) {
 		rth->dst.input= ip_error;
 		rth->dst.error= -err;
 		rth->rt_flags 	&= ~RTCF_LOCAL;
@@ -1620,7 +1622,7 @@ local_input:
 
 no_route:
 	RT_CACHE_STAT_INC(in_no_route);
-	res.type = RTN_UNREACHABLE;
+	type = RTN_UNREACHABLE;
 	if (err == -ESRCH)
 		err = -ENETUNREACH;
 	goto local_input;
@@ -1700,13 +1702,12 @@ EXPORT_SYMBOL(ip_route_input_noref);
 /* called with rcu_read_lock() */
 static struct rtable *__mkroute_output(const struct fib_result *res,
 				       const struct flowi4 *fl4, int orig_oif,
-				       struct net_device *dev_out,
+				       struct net_device *dev_out, u8 type,
 				       unsigned int flags)
 {
 	struct fib_nh_exception *fnhe;
 	struct fib_nh *nh = res->nh;
 	struct in_device *in_dev;
-	u16 type = res->type;
 	struct rtable *rth;
 
 	in_dev = __in_dev_get_rcu(dev_out);
@@ -1809,6 +1810,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	struct fib_result res;
 	struct rtable *rth;
 	int orig_oif;
+	u8 type;
 
 	res.tclassid	= 0;
 	res.nh		= NULL;
@@ -1822,6 +1824,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			 RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
 
 	rcu_read_lock();
+	type = 0;
 	if (fl4->saddr) {
 		rth = ERR_PTR(-EINVAL);
 		if (ipv4_is_multicast(fl4->saddr) ||
@@ -1906,7 +1909,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
 		dev_out = net->loopback_dev;
 		fl4->flowi4_oif = net->loopback_dev->ifindex;
-		res.type = RTN_LOCAL;
+		type = RTN_LOCAL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
@@ -1936,14 +1939,15 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 			if (fl4->saddr == 0)
 				fl4->saddr = inet_select_addr(dev_out, 0,
 							      RT_SCOPE_LINK);
-			res.type = RTN_UNICAST;
+			type = RTN_UNICAST;
 			goto make_route;
 		}
 		rth = ERR_PTR(-ENETUNREACH);
 		goto out;
 	}
+	type = res.nh->nh_parent->fib_type;
 
-	if (res.type == RTN_LOCAL) {
+	if (type == RTN_LOCAL) {
 		if (!fl4->saddr) {
 			struct fib_info *fi = res.nh->nh_parent;
 			if (fi->fib_prefsrc)
@@ -1965,7 +1969,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 #endif
 	if (!res.prefixlen &&
 	    res.table->tb_num_default > 1 &&
-	    res.type == RTN_UNICAST && !fl4->flowi4_oif)
+	    type == RTN_UNICAST && !fl4->flowi4_oif)
 		fib_select_default(&res);
 
 	if (!fl4->saddr)
@@ -1976,7 +1980,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 
 make_route:
-	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
+	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, type, flags);
 
 out:
 	rcu_read_unlock();
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/7] ipv4: Don't store scope in fib_result.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


It can be obtained from the nexthop's fib_info.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |    2 +-
 net/ipv4/fib_frontend.c  |    2 +-
 net/ipv4/fib_semantics.c |    5 +++--
 net/ipv4/fib_trie.c      |    1 -
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index eb62a2f..847a46b 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -126,7 +126,7 @@ struct fib_result {
 	unsigned char		prefixlen;
 	unsigned char		__pad;
 	unsigned char		type;
-	unsigned char		scope;
+	unsigned char		__pad2;
 	u32			tclassid;
 	struct fib_nh		*nh;
 	struct fib_table	*table;
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index d2e8dbe..e02390d 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -946,7 +946,7 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 			frn->prefixlen = res.prefixlen;
 			frn->nh_sel = nhsel;
 			frn->type = res.type;
-			frn->scope = res.scope;
+			frn->scope = fi->fib_scope;
 		}
 		rcu_read_unlock();
 		local_bh_enable();
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index b830245..6f73403 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -612,7 +612,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 		err = -EINVAL;
 		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
 			goto out;
-		nh->nh_scope = res.scope;
+		nh->nh_scope = res.nh->nh_parent->fib_scope;
 		nh->nh_oif = res.nh->nh_oif;
 		nh->nh_dev = dev = res.nh->nh_dev;
 		if (!dev)
@@ -1140,7 +1140,8 @@ void fib_select_default(struct fib_result *res)
 	list_for_each_entry_rcu(fa, fa_head, fa_list) {
 		struct fib_nh *next_nh = &fa->fa_info->fib_nh[0];
 
-		if (next_nh->nh_parent->fib_scope != res->scope ||
+		if ((next_nh->nh_parent->fib_scope !=
+		     res->nh->nh_parent->fib_scope) ||
 		    fa->fa_type != RTN_UNICAST)
 			continue;
 
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 04b0e26..83cf215 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1396,7 +1396,6 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 #endif
 				res->prefixlen = li->plen;
 				res->type = fa->fa_type;
-				res->scope = fi->fib_scope;
 				res->nh = nh;
 				res->table = tb;
 				res->fa_head = &li->falh;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 1/7] ipv4: Provide fib_nh instead of fib_info in fib_result.
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


The latter can be obtained via nh->nh_parent, and this makes
the fib_result->nh_sel member no longer necessary.

Signed-off-by: David S. Miller <davem@davemloft.net>
---
 include/net/ip_fib.h     |   43 +++++++++++-------------
 net/ipv4/devinet.c       |    2 +-
 net/ipv4/fib_frontend.c  |   28 +++++++++-------
 net/ipv4/fib_lookup.h    |   11 -------
 net/ipv4/fib_semantics.c |   54 +++++++++++++++---------------
 net/ipv4/fib_trie.c      |    7 ++--
 net/ipv4/route.c         |   82 ++++++++++++++++++++++------------------------
 7 files changed, 108 insertions(+), 119 deletions(-)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index e69c3a4..eb62a2f 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -123,14 +123,14 @@ struct fib_rule;
 
 struct fib_table;
 struct fib_result {
-	unsigned char	prefixlen;
-	unsigned char	nh_sel;
-	unsigned char	type;
-	unsigned char	scope;
-	u32		tclassid;
-	struct fib_info *fi;
-	struct fib_table *table;
-	struct list_head *fa_head;
+	unsigned char		prefixlen;
+	unsigned char		__pad;
+	unsigned char		type;
+	unsigned char		scope;
+	u32			tclassid;
+	struct fib_nh		*nh;
+	struct fib_table	*table;
+	struct list_head	*fa_head;
 };
 
 struct fib_result_nl {
@@ -150,31 +150,28 @@ struct fib_result_nl {
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
 
-#define FIB_RES_NH(res)		((res).fi->fib_nh[(res).nh_sel])
-
 #define FIB_TABLE_HASHSZ 2
 
 #else /* CONFIG_IP_ROUTE_MULTIPATH */
 
-#define FIB_RES_NH(res)		((res).fi->fib_nh[0])
-
 #define FIB_TABLE_HASHSZ 256
 
 #endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
 extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 
-#define FIB_RES_SADDR(net, res)				\
-	((FIB_RES_NH(res).nh_saddr_genid ==		\
-	  atomic_read(&(net)->ipv4.dev_addr_genid)) ?	\
-	 FIB_RES_NH(res).nh_saddr :			\
-	 fib_info_update_nh_saddr((net), &FIB_RES_NH(res)))
-#define FIB_RES_GW(res)			(FIB_RES_NH(res).nh_gw)
-#define FIB_RES_DEV(res)		(FIB_RES_NH(res).nh_dev)
-#define FIB_RES_OIF(res)		(FIB_RES_NH(res).nh_oif)
+static inline __be32 fib_res_prefsrc(struct net *net, struct fib_result *res)
+{
+	struct fib_nh *nh = res->nh;
+	struct fib_info *fi;
 
-#define FIB_RES_PREFSRC(net, res)	((res).fi->fib_prefsrc ? : \
-					 FIB_RES_SADDR(net, res))
+	fi = nh->nh_parent;
+	if (fi->fib_prefsrc)
+		return fi->fib_prefsrc;
+	if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid))
+		return nh->nh_saddr;
+	return fib_info_update_nh_saddr(net, nh);
+}
 
 struct fib_table {
 	struct hlist_node	tb_hlist;
@@ -302,7 +299,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	u32 rtag;
 #endif
-	*itag = FIB_RES_NH(*res).nh_tclassid<<16;
+	*itag = res->nh->nh_tclassid<<16;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
 	rtag = res->tclassid;
 	if (*itag == 0)
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 44bf82e..1baaa53 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -164,7 +164,7 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
 		if (local &&
 		    !fib_table_lookup(local, &fl4, &res, FIB_LOOKUP_NOREF) &&
 		    res.type == RTN_LOCAL)
-			result = FIB_RES_DEV(res);
+			result = res.nh->nh_dev;
 	}
 	if (result && devref)
 		dev_hold(result);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 8732cc7..d2e8dbe 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -174,7 +174,7 @@ static inline unsigned int __inet_dev_addr_type(struct net *net,
 		ret = RTN_UNICAST;
 		rcu_read_lock();
 		if (!fib_table_lookup(local_table, &fl4, &res, FIB_LOOKUP_NOREF)) {
-			if (!dev || dev == res.fi->fib_dev)
+			if (!dev || dev == res.nh->nh_dev)
 				ret = res.type;
 		}
 		rcu_read_unlock();
@@ -225,7 +225,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb)
 		fl4.flowi4_scope = scope;
 		fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
 		if (!fib_lookup(net, &fl4, &res))
-			return FIB_RES_PREFSRC(net, res);
+			return fib_res_prefsrc(net, &res);
 	} else {
 		scope = RT_SCOPE_LINK;
 	}
@@ -247,6 +247,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 {
 	int ret, no_addr, accept_local;
 	struct fib_result res;
+	struct fib_info *fi;
 	struct flowi4 fl4;
 	struct net *net;
 	bool dev_match;
@@ -273,21 +274,17 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 	fib_combine_itag(itag, &res);
 	dev_match = false;
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-	for (ret = 0; ret < res.fi->fib_nhs; ret++) {
-		struct fib_nh *nh = &res.fi->fib_nh[ret];
+	fi = res.nh->nh_parent;
+	for (ret = 0; ret < fi->fib_nhs; ret++) {
+		struct fib_nh *nh = &fi->fib_nh[ret];
 
 		if (nh->nh_dev == dev) {
 			dev_match = true;
 			break;
 		}
 	}
-#else
-	if (FIB_RES_DEV(res) == dev)
-		dev_match = true;
-#endif
 	if (dev_match) {
-		ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+		ret = res.nh->nh_scope >= RT_SCOPE_HOST;
 		return ret;
 	}
 	if (no_addr)
@@ -299,7 +296,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
 	ret = 0;
 	if (fib_lookup(net, &fl4, &res) == 0) {
 		if (res.type == RTN_UNICAST)
-			ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
+			ret = res.nh->nh_scope >= RT_SCOPE_HOST;
 	}
 	return ret;
 
@@ -939,8 +936,15 @@ static void nl_fib_lookup(struct fib_result_nl *frn, struct fib_table *tb)
 		frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
 
 		if (!frn->err) {
+			struct fib_nh *nh = res.nh;
+			struct fib_info *fi;
+			int nhsel;
+
+			fi = nh->nh_parent;
+			nhsel = nh - &fi->fib_nh[0];
+
 			frn->prefixlen = res.prefixlen;
-			frn->nh_sel = res.nh_sel;
+			frn->nh_sel = nhsel;
 			frn->type = res.type;
 			frn->scope = res.scope;
 		}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index af0f14a..5f110b6 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -36,17 +36,6 @@ extern void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
 		      unsigned int nlm_flags);
 extern struct fib_alias *fib_find_alias(struct list_head *fah,
 					u8 tos, u32 prio);
-extern int fib_detect_death(struct fib_info *fi, int order,
-			    struct fib_info **last_resort,
-			    int *last_idx, int dflt);
-
-static inline void fib_result_assign(struct fib_result *res,
-				     struct fib_info *fi)
-{
-	/* we used to play games with refcounts, but we now use RCU */
-	res->fi = fi;
-}
-
 struct fib_prop {
 	int	error;
 	u8	scope;
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index da0cc2e..b830245 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -393,13 +393,14 @@ struct fib_alias *fib_find_alias(struct list_head *fah, u8 tos, u32 prio)
 	return NULL;
 }
 
-int fib_detect_death(struct fib_info *fi, int order,
-		     struct fib_info **last_resort, int *last_idx, int dflt)
+int fib_detect_death(struct fib_nh *nh, int order,
+		     struct fib_nh **last_resort, int *last_idx,
+		     int dflt)
 {
 	struct neighbour *n;
 	int state = NUD_NONE;
 
-	n = neigh_lookup(&arp_tbl, &fi->fib_nh[0].nh_gw, fi->fib_dev);
+	n = neigh_lookup(&arp_tbl, &nh->nh_gw, nh->nh_dev);
 	if (n) {
 		state = n->nud_state;
 		neigh_release(n);
@@ -410,7 +411,7 @@ int fib_detect_death(struct fib_info *fi, int order,
 		return 0;
 	if ((state & NUD_VALID) ||
 	    (*last_idx < 0 && order > dflt)) {
-		*last_resort = fi;
+		*last_resort = nh;
 		*last_idx = order;
 	}
 	return 1;
@@ -612,8 +613,8 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi,
 		if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
 			goto out;
 		nh->nh_scope = res.scope;
-		nh->nh_oif = FIB_RES_OIF(res);
-		nh->nh_dev = dev = FIB_RES_DEV(res);
+		nh->nh_oif = res.nh->nh_oif;
+		nh->nh_dev = dev = res.nh->nh_dev;
 		if (!dev)
 			goto out;
 		dev_hold(dev);
@@ -1130,54 +1131,55 @@ int fib_sync_down_dev(struct net_device *dev, int force)
 /* Must be invoked inside of an RCU protected region.  */
 void fib_select_default(struct fib_result *res)
 {
-	struct fib_info *fi = NULL, *last_resort = NULL;
+	struct fib_nh *nh = NULL, *last_resort = NULL;
 	struct list_head *fa_head = res->fa_head;
 	struct fib_table *tb = res->table;
 	int order = -1, last_idx = -1;
 	struct fib_alias *fa;
 
 	list_for_each_entry_rcu(fa, fa_head, fa_list) {
-		struct fib_info *next_fi = fa->fa_info;
+		struct fib_nh *next_nh = &fa->fa_info->fib_nh[0];
 
-		if (next_fi->fib_scope != res->scope ||
+		if (next_nh->nh_parent->fib_scope != res->scope ||
 		    fa->fa_type != RTN_UNICAST)
 			continue;
 
-		if (next_fi->fib_priority > res->fi->fib_priority)
+		if (next_nh->nh_parent->fib_priority >
+		    res->nh->nh_parent->fib_priority)
 			break;
-		if (!next_fi->fib_nh[0].nh_gw ||
-		    next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
+
+		if (!next_nh->nh_gw || next_nh->nh_scope != RT_SCOPE_LINK)
 			continue;
 
 		fib_alias_accessed(fa);
 
-		if (fi == NULL) {
-			if (next_fi != res->fi)
+		if (nh == NULL) {
+			if (next_nh != res->nh)
 				break;
-		} else if (!fib_detect_death(fi, order, &last_resort,
+		} else if (!fib_detect_death(nh, order, &last_resort,
 					     &last_idx, tb->tb_default)) {
-			fib_result_assign(res, fi);
+			res->nh = nh;
 			tb->tb_default = order;
 			goto out;
 		}
-		fi = next_fi;
+		nh = next_nh;
 		order++;
 	}
 
-	if (order <= 0 || fi == NULL) {
+	if (order <= 0 || nh == NULL) {
 		tb->tb_default = -1;
 		goto out;
 	}
 
-	if (!fib_detect_death(fi, order, &last_resort, &last_idx,
-				tb->tb_default)) {
-		fib_result_assign(res, fi);
+	if (!fib_detect_death(nh, order, &last_resort, &last_idx,
+			      tb->tb_default)) {
+		res->nh = nh;
 		tb->tb_default = order;
 		goto out;
 	}
 
 	if (last_idx >= 0)
-		fib_result_assign(res, last_resort);
+		res->nh = last_resort;
 	tb->tb_default = last_idx;
 out:
 	return;
@@ -1249,7 +1251,7 @@ int fib_sync_up(struct net_device *dev)
  */
 void fib_select_multipath(struct fib_result *res)
 {
-	struct fib_info *fi = res->fi;
+	struct fib_info *fi = res->nh->nh_parent;
 	int w;
 
 	spin_lock_bh(&fib_multipath_lock);
@@ -1265,7 +1267,7 @@ void fib_select_multipath(struct fib_result *res)
 		if (power <= 0) {
 			spin_unlock_bh(&fib_multipath_lock);
 			/* Race condition: route has just become dead. */
-			res->nh_sel = 0;
+			res->nh = &fi->fib_nh[0];
 			return;
 		}
 	}
@@ -1284,7 +1286,7 @@ void fib_select_multipath(struct fib_result *res)
 			if (w <= 0) {
 				nexthop_nh->nh_power--;
 				fi->fib_power--;
-				res->nh_sel = nhsel;
+				res->nh = &fi->fib_nh[nhsel];
 				spin_unlock_bh(&fib_multipath_lock);
 				return;
 			}
@@ -1292,7 +1294,7 @@ void fib_select_multipath(struct fib_result *res)
 	} endfor_nexthops(fi);
 
 	/* Race condition: route has just become dead. */
-	res->nh_sel = 0;
+	res->nh = &fi->fib_nh[0];
 	spin_unlock_bh(&fib_multipath_lock);
 }
 #endif
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 18cbc15..04b0e26 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1384,7 +1384,7 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 			if (fi->fib_flags & RTNH_F_DEAD)
 				continue;
 			for (nhsel = 0; nhsel < fi->fib_nhs; nhsel++) {
-				const struct fib_nh *nh = &fi->fib_nh[nhsel];
+				struct fib_nh *nh = &fi->fib_nh[nhsel];
 
 				if (nh->nh_flags & RTNH_F_DEAD)
 					continue;
@@ -1395,10 +1395,9 @@ static int check_leaf(struct fib_table *tb, struct trie *t, struct leaf *l,
 				t->stats.semantic_match_passed++;
 #endif
 				res->prefixlen = li->plen;
-				res->nh_sel = nhsel;
 				res->type = fa->fa_type;
-				res->scope = fa->fa_info->fib_scope;
-				res->fi = fi;
+				res->scope = fi->fib_scope;
+				res->nh = nh;
 				res->table = tb;
 				res->fa_head = &li->falh;
 				if (!(fib_flags & FIB_LOOKUP_NOREF))
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fc1a81c..0b3277c 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -722,7 +722,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow
 			neigh_event_send(n, NULL);
 		} else {
 			if (fib_lookup(net, fl4, &res) == 0) {
-				struct fib_nh *nh = &FIB_RES_NH(res);
+				struct fib_nh *nh = res.nh;
 
 				update_or_create_fnhe(nh, fl4->daddr, new_gw,
 						      0, 0);
@@ -926,7 +926,7 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 		mtu = ip_rt_min_pmtu;
 
 	if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
-		struct fib_nh *nh = &FIB_RES_NH(res);
+		struct fib_nh *nh = res.nh;
 
 		update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
 				      jiffies + ip_rt_mtu_expires);
@@ -1085,7 +1085,7 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
 
 		rcu_read_lock();
 		if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
-			src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res);
+			src = fib_res_prefsrc(dev_net(rt->dst.dev), &res);
 		else
 			src = inet_select_addr(rt->dst.dev,
 					       rt_nexthop(rt, iph->daddr),
@@ -1237,16 +1237,14 @@ static bool rt_cache_valid(const struct rtable *rt)
 static void rt_set_nexthop(struct rtable *rt, __be32 daddr,
 			   const struct fib_result *res,
 			   struct fib_nh_exception *fnhe,
-			   struct fib_info *fi, u16 type, u32 itag)
+			   struct fib_nh *nh, u16 type, u32 itag)
 {
-	if (fi) {
-		struct fib_nh *nh = &FIB_RES_NH(*res);
-
+	if (nh) {
 		if (nh->nh_gw && nh->nh_scope == RT_SCOPE_LINK)
 			rt->rt_gateway = nh->nh_gw;
 		if (unlikely(fnhe))
 			rt_bind_exception(rt, fnhe, daddr);
-		dst_init_metrics(&rt->dst, fi->fib_metrics, true);
+		dst_init_metrics(&rt->dst, nh->nh_parent->fib_metrics, true);
 #ifdef CONFIG_IP_ROUTE_CLASSID
 		rt->dst.tclassid = nh->nh_tclassid;
 #endif
@@ -1373,6 +1371,7 @@ static int __mkroute_input(struct sk_buff *skb,
 			   struct in_device *in_dev,
 			   __be32 daddr, __be32 saddr, u32 tos)
 {
+	struct fib_nh *nh = res->nh;
 	struct rtable *rth;
 	int err;
 	struct in_device *out_dev;
@@ -1381,14 +1380,14 @@ static int __mkroute_input(struct sk_buff *skb,
 	u32 itag;
 
 	/* get a working reference to the output device */
-	out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res));
+	out_dev = __in_dev_get_rcu(nh->nh_dev);
 	if (out_dev == NULL) {
 		net_crit_ratelimited("Bug in ip_route_input_slow(). Please report.\n");
 		return -EINVAL;
 	}
 
 
-	err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res),
+	err = fib_validate_source(skb, saddr, daddr, tos, nh->nh_oif,
 				  in_dev->dev, in_dev, &itag);
 	if (err < 0) {
 		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr,
@@ -1399,7 +1398,7 @@ static int __mkroute_input(struct sk_buff *skb,
 
 	if (out_dev == in_dev && err &&
 	    (IN_DEV_SHARED_MEDIA(out_dev) ||
-	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+	     inet_addr_onlink(out_dev, saddr, nh->nh_gw)))
 		flags |= RTCF_DOREDIRECT;
 
 	if (skb->protocol != htons(ETH_P_IP)) {
@@ -1418,15 +1417,13 @@ static int __mkroute_input(struct sk_buff *skb,
 	}
 
 	do_cache = false;
-	if (res->fi) {
-		if (!itag) {
-			rth = FIB_RES_NH(*res).nh_rth_input;
-			if (rt_cache_valid(rth)) {
-				skb_dst_set_noref(skb, &rth->dst);
-				goto out;
-			}
-			do_cache = true;
+	if (!itag) {
+		rth = nh->nh_rth_input;
+		if (rt_cache_valid(rth)) {
+			skb_dst_set_noref(skb, &rth->dst);
+			goto out;
 		}
+		do_cache = true;
 	}
 
 	rth = rt_dst_alloc(out_dev->dev,
@@ -1448,7 +1445,7 @@ static int __mkroute_input(struct sk_buff *skb,
 	rth->dst.input = ip_forward;
 	rth->dst.output = ip_output;
 
-	rt_set_nexthop(rth, daddr, res, NULL, res->fi, res->type, itag);
+	rt_set_nexthop(rth, daddr, res, NULL, nh, res->type, itag);
 	skb_dst_set(skb, &rth->dst);
 out:
 	err = 0;
@@ -1463,7 +1460,7 @@ static int ip_mkroute_input(struct sk_buff *skb,
 			    __be32 daddr, __be32 saddr, u32 tos)
 {
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res->fi && res->fi->fib_nhs > 1)
+	if (res->nh->nh_parent->fib_nhs > 1)
 		fib_select_multipath(res);
 #endif
 
@@ -1507,7 +1504,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
 		goto martian_source;
 
-	res.fi = NULL;
+	res.nh = NULL;
 	if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0))
 		goto brd_input;
 
@@ -1580,9 +1577,9 @@ brd_input:
 
 local_input:
 	do_cache = false;
-	if (res.fi) {
+	if (res.nh) {
 		if (!itag) {
-			rth = FIB_RES_NH(res).nh_rth_input;
+			rth = res.nh->nh_rth_input;
 			if (rt_cache_valid(rth)) {
 				skb_dst_set_noref(skb, &rth->dst);
 				err = 0;
@@ -1616,7 +1613,7 @@ local_input:
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 	if (do_cache)
-		rt_cache_route(&FIB_RES_NH(res), rth);
+		rt_cache_route(res.nh, rth);
 	skb_dst_set(skb, &rth->dst);
 	err = 0;
 	goto out;
@@ -1706,8 +1703,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 				       struct net_device *dev_out,
 				       unsigned int flags)
 {
-	struct fib_info *fi = res->fi;
 	struct fib_nh_exception *fnhe;
+	struct fib_nh *nh = res->nh;
 	struct in_device *in_dev;
 	u16 type = res->type;
 	struct rtable *rth;
@@ -1732,7 +1729,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 
 	if (type == RTN_BROADCAST) {
 		flags |= RTCF_BROADCAST | RTCF_LOCAL;
-		fi = NULL;
+		nh = NULL;
 	} else if (type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST | RTCF_LOCAL;
 		if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
@@ -1742,15 +1739,15 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 		 * default one, but do not gateway in this case.
 		 * Yes, it is hack.
 		 */
-		if (fi && res->prefixlen < 4)
-			fi = NULL;
+		if (nh && res->prefixlen < 4)
+			nh = NULL;
 	}
 
 	fnhe = NULL;
-	if (fi) {
-		fnhe = find_exception(&FIB_RES_NH(*res), fl4->daddr);
+	if (nh) {
+		fnhe = find_exception(nh, fl4->daddr);
 		if (!fnhe) {
-			rth = FIB_RES_NH(*res).nh_rth_output;
+			rth = nh->nh_rth_output;
 			if (rt_cache_valid(rth)) {
 				dst_hold(&rth->dst);
 				return rth;
@@ -1760,7 +1757,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 	rth = rt_dst_alloc(dev_out,
 			   IN_DEV_CONF_GET(in_dev, NOPOLICY),
 			   IN_DEV_CONF_GET(in_dev, NOXFRM),
-			   fi && !fnhe);
+			   nh && !fnhe);
 	if (!rth)
 		return ERR_PTR(-ENOBUFS);
 
@@ -1795,7 +1792,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
 #endif
 	}
 
-	rt_set_nexthop(rth, fl4->daddr, res, fnhe, fi, type, 0);
+	rt_set_nexthop(rth, fl4->daddr, res, fnhe, nh, type, 0);
 
 	return rth;
 }
@@ -1814,7 +1811,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	int orig_oif;
 
 	res.tclassid	= 0;
-	res.fi		= NULL;
+	res.nh		= NULL;
 	res.table	= NULL;
 
 	orig_oif = fl4->flowi4_oif;
@@ -1915,7 +1912,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 	}
 
 	if (fib_lookup(net, fl4, &res)) {
-		res.fi = NULL;
+		res.nh = NULL;
 		res.table = NULL;
 		if (fl4->flowi4_oif) {
 			/* Apparently, routing tables are wrong. Assume,
@@ -1948,20 +1945,21 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 
 	if (res.type == RTN_LOCAL) {
 		if (!fl4->saddr) {
-			if (res.fi->fib_prefsrc)
-				fl4->saddr = res.fi->fib_prefsrc;
+			struct fib_info *fi = res.nh->nh_parent;
+			if (fi->fib_prefsrc)
+				fl4->saddr = fi->fib_prefsrc;
 			else
 				fl4->saddr = fl4->daddr;
 		}
 		dev_out = net->loopback_dev;
 		fl4->flowi4_oif = dev_out->ifindex;
-		res.fi = NULL;
+		res.nh = NULL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res.fi->fib_nhs > 1 && fl4->flowi4_oif == 0)
+	if (res.nh->nh_parent->fib_nhs > 1 && fl4->flowi4_oif == 0)
 		fib_select_multipath(&res);
 	else
 #endif
@@ -1971,9 +1969,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4)
 		fib_select_default(&res);
 
 	if (!fl4->saddr)
-		fl4->saddr = FIB_RES_PREFSRC(net, res);
+		fl4->saddr = fib_res_prefsrc(net, &res);
 
-	dev_out = FIB_RES_DEV(res);
+	dev_out = res.nh->nh_dev;
 	fl4->flowi4_oif = dev_out->ifindex;
 
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 0/7] Deconstruct struct fib_result
From: David Miller @ 2012-07-28  4:18 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev


This patch set tries to move towards reducing struct fib_result down
to it's absolute minimum.

The eventual idea is to make it so that fib_lookup() simply
returns a "struct fib_nh *" and pointer encoded errnos, instead
of writing into a complicated structure as the return value on
the stack as is done now.

Signed-off-by: David S. Miller <davem@davemloft.net>

^ permalink raw reply

* Re: [PATCH 00/16] Remove the ipv4 routing cache
From: David Miller @ 2012-07-28  4:15 UTC (permalink / raw)
  To: alexander.duyck; +Cc: eric.dumazet, netdev
In-Reply-To: <20120726.230246.219188476590178857.davem@davemloft.net>

From: David Miller <davem@davemloft.net>
Date: Thu, 26 Jul 2012 23:02:46 -0700 (PDT)

> Therefore one area of simplification would be to just return a pointer
> to the FIB nexthop, rather than the fib_info pointer and the nexthop
> index.  We can get to the fib_info, if we need to, via the nh_parent
> pointer of the nexthop.

So I'm about to post an RFC set of patches which show this kind
of simplification.  It gets fib_result down to two members:

	u32		tclassid;
	struct fib_nh	*nh;

If I could get rid of that tclassid it would be really nice.  But
that's hard because the tclassid is fetched from the fib_rule and
all of that lookup path is abstracted behind a common layer
that's shared between ipv4 and ipv6 so it's a bit of work changing
arg conventions.

These changes help, but only ever so slightly, in my testing.

^ permalink raw reply

* [PATCH v2] ppp: add 64 bit stats
From: Kevin Groeneveld @ 2012-07-28  3:38 UTC (permalink / raw)
  To: netdev; +Cc: Kevin Groeneveld

Add 64 bit stats to ppp driver.  The 64 bit stats include tx_bytes,
rx_bytes, tx_packets and rx_packets.  Other stats are still 32 bit.
The 64 bit stats can be retrieved via the ndo_get_stats operation.  The
SIOCGPPPSTATS ioctl is still 32 bit stats only.

Signed-off-by: Kevin Groeneveld <kgroeneveld@gmail.com>
---
v2: - do not use percpu variables for stats
    - use ppp_recv_lock/ppp_xmit_lock when reading 64 bit stats

 drivers/net/ppp/ppp_generic.c |   58 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 5c05572..eb3f5ce 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -94,6 +94,18 @@ struct ppp_file {
 #define PF_TO_CHANNEL(pf)	PF_TO_X(pf, struct channel)
 
 /*
+ * Data structure to hold primary network stats for which
+ * we want to use 64 bit storage.  Other network stats
+ * are stored in dev->stats of the ppp strucute.
+ */
+struct ppp_link_stats {
+	u64 rx_packets;
+	u64 tx_packets;
+	u64 rx_bytes;
+	u64 tx_bytes;
+};
+
+/*
  * Data structure describing one ppp unit.
  * A ppp unit corresponds to a ppp network interface device
  * and represents a multilink bundle.
@@ -136,6 +148,7 @@ struct ppp {
 	unsigned pass_len, active_len;
 #endif /* CONFIG_PPP_FILTER */
 	struct net	*ppp_net;	/* the net we belong to */
+	struct ppp_link_stats stats64;	/* 64 bit network stats */
 };
 
 /*
@@ -1021,9 +1034,34 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 	return err;
 }
 
+struct rtnl_link_stats64*
+ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64)
+{
+	struct ppp *ppp = netdev_priv(dev);
+
+	ppp_recv_lock(ppp);
+	stats64->rx_packets = ppp->stats64.rx_packets;
+	stats64->rx_bytes   = ppp->stats64.rx_bytes;
+	ppp_recv_unlock(ppp);
+
+	ppp_xmit_lock(ppp);
+	stats64->tx_packets = ppp->stats64.tx_packets;
+	stats64->tx_bytes   = ppp->stats64.tx_bytes;
+	ppp_xmit_unlock(ppp);
+
+	stats64->rx_errors        = dev->stats.rx_errors;
+	stats64->tx_errors        = dev->stats.tx_errors;
+	stats64->rx_dropped       = dev->stats.rx_dropped;
+	stats64->tx_dropped       = dev->stats.tx_dropped;
+	stats64->rx_length_errors = dev->stats.rx_length_errors;
+
+	return stats64;
+}
+
 static const struct net_device_ops ppp_netdev_ops = {
-	.ndo_start_xmit = ppp_start_xmit,
-	.ndo_do_ioctl   = ppp_net_ioctl,
+	.ndo_start_xmit  = ppp_start_xmit,
+	.ndo_do_ioctl    = ppp_net_ioctl,
+	.ndo_get_stats64 = ppp_get_stats64,
 };
 
 static void ppp_setup(struct net_device *dev)
@@ -1157,8 +1195,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb)
 #endif /* CONFIG_PPP_FILTER */
 	}
 
-	++ppp->dev->stats.tx_packets;
-	ppp->dev->stats.tx_bytes += skb->len - 2;
+	++ppp->stats64.tx_packets;
+	ppp->stats64.tx_bytes += skb->len - 2;
 
 	switch (proto) {
 	case PPP_IP:
@@ -1745,8 +1783,8 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
 		break;
 	}
 
-	++ppp->dev->stats.rx_packets;
-	ppp->dev->stats.rx_bytes += skb->len - 2;
+	++ppp->stats64.rx_packets;
+	ppp->stats64.rx_bytes += skb->len - 2;
 
 	npi = proto_to_npindex(proto);
 	if (npi < 0) {
@@ -2570,12 +2608,12 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st)
 	struct slcompress *vj = ppp->vj;
 
 	memset(st, 0, sizeof(*st));
-	st->p.ppp_ipackets = ppp->dev->stats.rx_packets;
+	st->p.ppp_ipackets = ppp->stats64.rx_packets;
 	st->p.ppp_ierrors = ppp->dev->stats.rx_errors;
-	st->p.ppp_ibytes = ppp->dev->stats.rx_bytes;
-	st->p.ppp_opackets = ppp->dev->stats.tx_packets;
+	st->p.ppp_ibytes = ppp->stats64.rx_bytes;
+	st->p.ppp_opackets = ppp->stats64.tx_packets;
 	st->p.ppp_oerrors = ppp->dev->stats.tx_errors;
-	st->p.ppp_obytes = ppp->dev->stats.tx_bytes;
+	st->p.ppp_obytes = ppp->stats64.tx_bytes;
 	if (!vj)
 		return;
 	st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH] ipv4: fix TCP early demux
From: David Miller @ 2012-07-27 23:00 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1343424873.2626.13112.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 27 Jul 2012 23:34:33 +0200

> I wonder why cookie is not stored in dst, and must be stored outside
> of it ?

Because in ipv6, cloned routes are never invalidated on a route
insertion or deletion.  We keep them around.

The fn_sernum tracks path reachability, rather than validation of
dsts.

So when we delete or insert a new ipv6 route, we update the serial
number of all the FIB nodes on the way down to the insert/delete
point.

If, afterwards, we can still reach a route cloned from one of those
entries successfully.  It is still valid.

If we were to store the serial number on the dst, it would invalidate
the cloned route, which the ipv6 code is largely not designed for.

To be honest, the whole route validation scheme in ipv6 was
jackhammered into place.  It was basically two years of Alexey
repairing the largely broken scheme that Pedro had put into place.

This is ~1997 legacy stuff.

It deserves a complete rewrite, but we are too busy with ipv4 at the
moment.  And frankly if nobody other than myself was concerned enough
to delete the ipv4 routing cache (code people actually use) the
likelyhood of anyone embarking on a task of similar size for ipv6 is
basically zero.

^ permalink raw reply

* Re: [PATCH] ipv4: fix TCP early demux
From: Eric Dumazet @ 2012-07-27 21:34 UTC (permalink / raw)
  To: David Miller; +Cc: netdev
In-Reply-To: <20120727.134713.1437322148321890583.davem@davemloft.net>

On Fri, 2012-07-27 at 13:47 -0700, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Fri, 27 Jul 2012 18:23:40 +0200
> 
> > From: Eric Dumazet <edumazet@google.com>
> > 
> > commit 92101b3b2e317 (ipv4: Prepare for change of rt->rt_iif encoding.)
> > invalidated TCP early demux, because rx_dst_ifindex is not properly
> > initialized and checked.
> > 
> > Also remove the use of inet_iif(skb) in favor or skb->skb_iif
> > 
> > Signed-off-by: Eric Dumazet <edumazet@google.com>
> 
> Applied.

Thanks David

IPv6 part is screwed because of the bogus dst_check(dst, 0)

(and missing code that was moved out from tcp_rcv_established() to
tcp_v4_do_rcv() : I was wondering if we could make it generic to move it
back to tcp_rcv_established()) :

                if (sk->sk_rx_dst) {
                        struct dst_entry *dst = sk->sk_rx_dst;
                        if (dst->ops->check(dst, 0) == NULL) {
                                dst_release(dst);
                                sk->sk_rx_dst = NULL;
                        }
                }
                if (unlikely(sk->sk_rx_dst == NULL)) {
                        sk->sk_rx_dst = dst_clone(skb_dst(skb));
                        inet_sk(sk)->rx_dst_ifindex = inet_iif(skb);
                }


IPv6 wants a cookie here, not 0

I wonder why cookie is not stored in dst, and must be stored outside of
it ?

We could then use :
                if (sk->sk_rx_dst) {
                        struct dst_entry *dst = sk->sk_rx_dst;
                        if (dst->ops->check(dst) == NULL) {
                                dst_release(dst);
                                sk->sk_rx_dst = NULL;
                        }
                }

^ permalink raw reply

* Re: pull request: wireless 2012-07-27
From: David Miller @ 2012-07-27 21:26 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20120727155806.GB6110@tuxdriver.com>

From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 27 Jul 2012 11:58:06 -0400

> These fixes are intended for the 3.6 stream.
> 
> Hauke Mehrtens provides a pair of bcma fixes, one to fix a build
> regression on mips and another to correct a pair of missing iounmap
> calls.
> 
> Thomas Huehn offers a mac80211_hwsim fix to avoid a possible
> use-after-free bug.
> 
> Please let me know if there are problems!

Pulled, thanks John.

^ permalink raw reply

* Re: [PATCH] sctp: Make "Invalid Stream Identifier" ERROR follows SACK when bundling
From: Vlad Yasevich @ 2012-07-27 21:22 UTC (permalink / raw)
  To: Xufeng Zhang
  Cc: Neil Horman, xufeng zhang, sri, davem, linux-sctp, netdev,
	linux-kernel
In-Reply-To: <CA+=dFzguqjjnnqHO53Mx859VB6NU=4MaPWAUzGQB2qtZGfdAUg@mail.gmail.com>

here is an untested prototype of what I was talking about.  This should 
handle multiple data chunks.

-vlad

---
  include/net/sctp/command.h |    1 +
  net/sctp/sm_sideeffect.c   |   22 ++++++++++++++++++++++
  net/sctp/sm_statefuns.c    |   18 ++++++++++--------
  3 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 712b3be..4043445 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -110,6 +110,7 @@ typedef enum {
  	SCTP_CMD_SEND_NEXT_ASCONF, /* Send the next ASCONF after ACK */
  	SCTP_CMD_PURGE_ASCONF_QUEUE, /* Purge all asconf queues.*/
  	SCTP_CMD_SET_ASOC,	 /* Restore association context */
+	SCTP_CMD_GEN_BAD_STREAM, /* Issue an Invalid Stream error */
  	SCTP_CMD_LAST
  } sctp_verb_t;

diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 1ff51c9..c5a1322 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -1036,6 +1036,22 @@ static void sctp_cmd_send_asconf(struct 
sctp_association *asoc)
  	}
  }

+static void sctp_cmd_make_inv_stream_err(sctp_cmd_seq_t *commands,
+					 struct sctp_association *asoc,
+					 struct sctp_chunk *chunk,
+					 struct sctp_datahdr *data_hdr)
+{
+	struct sctp_chunk *err;
+
+	err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
+				 &data_hdr->stream,
+				 sizeof(data_hdr->stream),
+				 sizeof(u16));
+	if (err)
+		sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
+					SCTP_CHUNK(err));
+}
+

  /* These three macros allow us to pull the debugging code out of the
   * main flow of sctp_do_sm() to keep attention focused on the real
@@ -1700,6 +1716,12 @@ static int sctp_cmd_interpreter(sctp_event_t 
event_type,
  			asoc = cmd->obj.asoc;
  			break;

+		case SCTP_CMD_GEN_BAD_STREAM:
+			sctp_cmd_make_inv_stream_err(commands,
+					 asoc, chunk,
+					 (struct sctp_datahdr *)cmd->obj.ptr);
+			break;
+
  		default:
  			pr_warn("Impossible command: %u, %p\n",
  				cmd->verb, cmd->obj.ptr);
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 891f5db..57532e3 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -2972,6 +2972,12 @@ discard_noforce:
  	if (chunk->end_of_packet)
  		sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, force);

+	/* Queue the INVALID STREAM error after the SACK if one is needed. */
+	if (SCTP_IERROR_BAD_STREAM == error) {
+		sctp_add_cmd_sf(commands, SCTP_CMD_GEN_BAD_STREAM,
+				SCTP_PTR(chunk->subh.data_hdr));
+	}
+
  	return SCTP_DISPOSITION_DISCARD;
  consume:
  	return SCTP_DISPOSITION_CONSUME;
@@ -3044,6 +3050,10 @@ sctp_disposition_t 
sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep,
  		 */
  		sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SHUTDOWN, SCTP_NULL());
  		sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE());
+		if (SCTP_IERROR_BAD_STREAM == error) {
+			sctp_add_cmd_sf(commands, SCTP_CMD_GEN_BAD_STREAM,
+					SCTP_PTR(chunk->subh.data_hdr));
+		}
  		sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_RESTART,
  				SCTP_TO(SCTP_EVENT_TIMEOUT_T2_SHUTDOWN));
  	}
@@ -6140,14 +6150,6 @@ static int sctp_eat_data(const struct 
sctp_association *asoc,
  	if (sid >= asoc->c.sinit_max_instreams) {
  		/* Mark tsn as received even though we drop it */
  		sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_TSN, SCTP_U32(tsn));
-
-		err = sctp_make_op_error(asoc, chunk, SCTP_ERROR_INV_STRM,
-					 &data_hdr->stream,
-					 sizeof(data_hdr->stream),
-					 sizeof(u16));
-		if (err)
-			sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
-					SCTP_CHUNK(err));
  		return SCTP_IERROR_BAD_STREAM;
  	}

-- 1.7.7.6

^ permalink raw reply related

* Re: [PATCH v2] tcp: perform DMA to userspace only if there is a task waiting for it
From: David Miller @ 2012-07-27 20:48 UTC (permalink / raw)
  To: jkosina; +Cc: christopher.leech, linux-kernel, netdev, jbohac
In-Reply-To: <alpine.LNX.2.00.1207272237470.30412@pobox.suse.cz>

From: Jiri Kosina <jkosina@suse.cz>
Date: Fri, 27 Jul 2012 22:38:50 +0200 (CEST)

> Back in 2006, commit 1a2449a87b ("[I/OAT]: TCP recv offload to I/OAT")
> added support for receive offloading to IOAT dma engine if available.
> 
> The code in tcp_rcv_established() tries to perform early DMA copy if
> applicable. It however does so without checking whether the userspace
> task is actually expecting the data in the buffer.
> 
> This is not a problem under normal circumstances, but there is a corner
> case where this doesn't work -- and that's when MSG_TRUNC flag to
> recvmsg() is used.
> 
> If the IOAT dma engine is not used, the code properly checks whether
> there is a valid ucopy.task and the socket is owned by userspace, but
> misses the check in the dmaengine case.
> 
> This problem can be observed in real trivially -- for example 'tbench' is a
> good reproducer, as it makes a heavy use of MSG_TRUNC. On systems utilizing
> IOAT, you will soon find tbench waiting indefinitely in sk_wait_data(), as they
> have been already early-copied in tcp_rcv_established() using dma engine.
> 
> This patch introduces the same check we are performing in the simple
> iovec copy case to the IOAT case as well. It fixes the indefinite
> recvmsg(MSG_TRUNC) hangs.
> 
> Signed-off-by: Jiri Kosina <jkosina@suse.cz>

Applied.

^ permalink raw reply

* Re: [PATCH] Revert "openvswitch: potential NULL deref in sample()"
From: David Miller @ 2012-07-27 20:47 UTC (permalink / raw)
  To: jesse; +Cc: netdev, dev, dan.carpenter
In-Reply-To: <1343420380-23119-1-git-send-email-jesse@nicira.com>

From: Jesse Gross <jesse@nicira.com>
Date: Fri, 27 Jul 2012 13:19:40 -0700

> This reverts commit 5b3e7e6cb5771bedda51cdb6f715d1da8cd9e644.
> 
> The problem that the original commit was attempting to fix can
> never happen in practice because validation is done one a per-flow
> basis rather than a per-packet basis.  Adding additional checks at
> runtime is unnecessary and inconsistent with the rest of the code.
> 
> CC: Dan Carpenter <dan.carpenter@oracle.com>
> Signed-off-by: Jesse Gross <jesse@nicira.com>

Applied.

^ permalink raw reply

* Re: [PATCH] ipv4: fix TCP early demux
From: David Miller @ 2012-07-27 20:47 UTC (permalink / raw)
  To: eric.dumazet; +Cc: netdev
In-Reply-To: <1343406220.2626.13092.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Fri, 27 Jul 2012 18:23:40 +0200

> From: Eric Dumazet <edumazet@google.com>
> 
> commit 92101b3b2e317 (ipv4: Prepare for change of rt->rt_iif encoding.)
> invalidated TCP early demux, because rx_dst_ifindex is not properly
> initialized and checked.
> 
> Also remove the use of inet_iif(skb) in favor or skb->skb_iif
> 
> Signed-off-by: Eric Dumazet <edumazet@google.com>

Applied.

^ permalink raw reply

* Re: [PATCH] net: fix rtnetlink IFF_PROMISC and IFF_ALLMULTI handling
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
  To: jbenc; +Cc: netdev, makc
In-Reply-To: <20120727145822.7efd10d4@griffin>

From: Jiri Benc <jbenc@redhat.com>
Date: Fri, 27 Jul 2012 14:58:22 +0200

> When device flags are set using rtnetlink, IFF_PROMISC and IFF_ALLMULTI
> flags are handled specially. Function dev_change_flags sets IFF_PROMISC and
> IFF_ALLMULTI bits in dev->gflags according to the passed value but
> do_setlink passes a result of rtnl_dev_combine_flags which takes those bits
> from dev->flags.
> 
> This can be easily trigerred by doing:
> 
> tcpdump -i eth0 &
> ip l s up eth0
> 
> ip sets IFF_UP flag in ifi_flags and ifi_change, which is combined with
> IFF_PROMISC by rtnl_dev_combine_flags, causing __dev_change_flags to set
> IFF_PROMISC in gflags.
> 
> Reported-by: Max Matveev <makc@redhat.com>
> Signed-off-by: Jiri Benc <jbenc@redhat.com>

Applied.

^ permalink raw reply

* Re: [patch] USB: kaweth.c: use GFP_ATOMIC under spin_lock
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
  To: dan.carpenter; +Cc: gregkh, linux-usb, netdev, kernel-janitors
In-Reply-To: <20120727114651.GA15492@elgon.mountain>

From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Fri, 27 Jul 2012 14:46:51 +0300

> The problem is that we call this with a spin lock held.  The call tree
> is:
> 	kaweth_start_xmit() holds kaweth->device_lock.
> 	-> kaweth_async_set_rx_mode()
> 	   -> kaweth_control()
> 	      -> kaweth_internal_control_msg()
> 
> The kaweth_internal_control_msg() function is only called from
> kaweth_control() which used GFP_ATOMIC for its allocations.
> 
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

Applied.

^ permalink raw reply

* Re: [PATCH] tcp: Add TCP_USER_TIMEOUT negative value check
From: David Miller @ 2012-07-27 20:46 UTC (permalink / raw)
  To: liuhangbin; +Cc: netdev, hkchu
In-Reply-To: <1343379141-5516-1-git-send-email-liuhangbin@gmail.com>

From: Hangbin Liu <liuhangbin@gmail.com>
Date: Fri, 27 Jul 2012 16:52:21 +0800

> TCP_USER_TIMEOUT is a TCP level socket option that takes an unsigned int. But
> patch "tcp: Add TCP_USER_TIMEOUT socket option"(dca43c75) didn't check the negative
> values. If a user assign -1 to it, the socket will set successfully and wait
> for 4294967295 miliseconds. This patch add a negative value check to avoid
> this issue.
> 
> Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>

Applied.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox