Netdev List
 help / color / mirror / Atom feed
* [PATCH 2/5] soreuseport: TCP/IPv4 implementation
From: Tom Herbert @ 2013-01-22 19:50 UTC (permalink / raw)
  To: netdev, davem; +Cc: netdev, eric.dumazet

Allow multiple listener sockets to bind to the same port.

Motivation for soresuseport would be something like a web server
binding to port 80 running with multiple threads, where each thread
might have it's own listener socket.  This could be done as an
alternative to other models: 1) have one listener thread which
dispatches completed connections to workers. 2) accept on a single
listener socket from multiple threads.  In case #1 the listener thread
can easily become the bottleneck with high connection turn-over rate.
In case #2, the proportion of connections accepted per thread tends
to be uneven under high connection load (assuming simple event loop:
while (1) { accept(); process() }, wakeup does not promote fairness
among the sockets.  We have seen the  disproportion to be as high
as 3:1 ratio between thread accepting most connections and the one
accepting the fewest.  With so_reusport the distribution is
uniform.

Signed-off-by: Tom Herbert <therbert@google.com>
---
 include/net/inet_hashtables.h          |   13 ++++++--
 include/net/netfilter/nf_tproxy_core.h |    1 +
 net/ipv4/inet_connection_sock.c        |   48 ++++++++++++++++++++++++-------
 net/ipv4/inet_hashtables.c             |   28 ++++++++++++++----
 net/ipv4/tcp_ipv4.c                    |    4 ++-
 5 files changed, 73 insertions(+), 21 deletions(-)

diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 67a8fa0..7b2ae9d 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -81,7 +81,9 @@ struct inet_bind_bucket {
 	struct net		*ib_net;
 #endif
 	unsigned short		port;
-	signed short		fastreuse;
+	signed char		fastreuse;
+	signed char		fastreuseport;
+	kuid_t			fastuid;
 	int			num_owners;
 	struct hlist_node	node;
 	struct hlist_head	owners;
@@ -257,15 +259,19 @@ extern void inet_unhash(struct sock *sk);
 
 extern struct sock *__inet_lookup_listener(struct net *net,
 					   struct inet_hashinfo *hashinfo,
+					   const __be32 saddr,
+					   const __be16 sport,
 					   const __be32 daddr,
 					   const unsigned short hnum,
 					   const int dif);
 
 static inline struct sock *inet_lookup_listener(struct net *net,
 		struct inet_hashinfo *hashinfo,
+		__be32 saddr, __be16 sport,
 		__be32 daddr, __be16 dport, int dif)
 {
-	return __inet_lookup_listener(net, hashinfo, daddr, ntohs(dport), dif);
+	return __inet_lookup_listener(net, hashinfo, saddr, sport,
+				      daddr, ntohs(dport), dif);
 }
 
 /* Socket demux engine toys. */
@@ -358,7 +364,8 @@ static inline struct sock *__inet_lookup(struct net *net,
 	struct sock *sk = __inet_lookup_established(net, hashinfo,
 				saddr, sport, daddr, hnum, dif);
 
-	return sk ? : __inet_lookup_listener(net, hashinfo, daddr, hnum, dif);
+	return sk ? : __inet_lookup_listener(net, hashinfo, saddr, sport,
+					     daddr, hnum, dif);
 }
 
 static inline struct sock *inet_lookup(struct net *net,
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index 75ca929..1937964 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -82,6 +82,7 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
 			break;
 		case NFT_LOOKUP_LISTENER:
 			sk = inet_lookup_listener(net, &tcp_hashinfo,
+						    saddr, sport,
 						    daddr, dport,
 						    in->ifindex);
 
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d0670f0..8bb623d 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -59,6 +59,8 @@ int inet_csk_bind_conflict(const struct sock *sk,
 	struct sock *sk2;
 	struct hlist_node *node;
 	int reuse = sk->sk_reuse;
+	int reuseport = sk->sk_reuseport;
+	kuid_t uid = sock_i_uid((struct sock *)sk);
 
 	/*
 	 * Unlike other sk lookup places we do not check
@@ -73,8 +75,11 @@ int inet_csk_bind_conflict(const struct sock *sk,
 		    (!sk->sk_bound_dev_if ||
 		     !sk2->sk_bound_dev_if ||
 		     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
-			if (!reuse || !sk2->sk_reuse ||
-			    sk2->sk_state == TCP_LISTEN) {
+			if ((!reuse || !sk2->sk_reuse ||
+			    sk2->sk_state == TCP_LISTEN) &&
+			    (!reuseport || !sk2->sk_reuseport ||
+			    (sk2->sk_state != TCP_TIME_WAIT &&
+			     !uid_eq(uid, sock_i_uid(sk2))))) {
 				const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2);
 				if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) ||
 				    sk2_rcv_saddr == sk_rcv_saddr(sk))
@@ -106,6 +111,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
 	int ret, attempts = 5;
 	struct net *net = sock_net(sk);
 	int smallest_size = -1, smallest_rover;
+	kuid_t uid = sock_i_uid(sk);
 
 	local_bh_disable();
 	if (!snum) {
@@ -125,9 +131,12 @@ again:
 			spin_lock(&head->lock);
 			inet_bind_bucket_for_each(tb, node, &head->chain)
 				if (net_eq(ib_net(tb), net) && tb->port == rover) {
-					if (tb->fastreuse > 0 &&
-					    sk->sk_reuse &&
-					    sk->sk_state != TCP_LISTEN &&
+					if (((tb->fastreuse > 0 &&
+					      sk->sk_reuse &&
+					      sk->sk_state != TCP_LISTEN) ||
+					     (tb->fastreuseport > 0 &&
+					      sk->sk_reuseport &&
+					      uid_eq(tb->fastuid, uid))) &&
 					    (tb->num_owners < smallest_size || smallest_size == -1)) {
 						smallest_size = tb->num_owners;
 						smallest_rover = rover;
@@ -185,14 +194,17 @@ tb_found:
 		if (sk->sk_reuse == SK_FORCE_REUSE)
 			goto success;
 
-		if (tb->fastreuse > 0 &&
-		    sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+		if (((tb->fastreuse > 0 &&
+		      sk->sk_reuse && sk->sk_state != TCP_LISTEN) ||
+		     (tb->fastreuseport > 0 &&
+		      sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
 		    smallest_size == -1) {
 			goto success;
 		} else {
 			ret = 1;
 			if (inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb, true)) {
-				if (sk->sk_reuse && sk->sk_state != TCP_LISTEN &&
+				if (((sk->sk_reuse && sk->sk_state != TCP_LISTEN) ||
+				     (sk->sk_reuseport && uid_eq(tb->fastuid, uid))) &&
 				    smallest_size != -1 && --attempts >= 0) {
 					spin_unlock(&head->lock);
 					goto again;
@@ -212,9 +224,23 @@ tb_not_found:
 			tb->fastreuse = 1;
 		else
 			tb->fastreuse = 0;
-	} else if (tb->fastreuse &&
-		   (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
-		tb->fastreuse = 0;
+		if (sk->sk_reuseport) {
+			tb->fastreuseport = 1;
+			tb->fastuid = uid;
+		} else {
+			tb->fastreuseport = 0;
+			tb->fastuid = 0;
+		}
+	} else {
+		if (tb->fastreuse &&
+		    (!sk->sk_reuse || sk->sk_state == TCP_LISTEN))
+			tb->fastreuse = 0;
+		if (tb->fastreuseport &&
+		    (!sk->sk_reuseport || !uid_eq(tb->fastuid, uid))) {
+			tb->fastreuseport = 0;
+			tb->fastuid = 0;
+		}
+	}
 success:
 	if (!inet_csk(sk)->icsk_bind_hash)
 		inet_bind_hash(sk, tb, snum);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index fa3ae81..0ce0595 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -39,6 +39,7 @@ struct inet_bind_bucket *inet_bind_bucket_create(struct kmem_cache *cachep,
 		write_pnet(&tb->ib_net, hold_net(net));
 		tb->port      = snum;
 		tb->fastreuse = 0;
+		tb->fastreuseport = 0;
 		tb->num_owners = 0;
 		INIT_HLIST_HEAD(&tb->owners);
 		hlist_add_head(&tb->node, &head->chain);
@@ -151,16 +152,16 @@ static inline int compute_score(struct sock *sk, struct net *net,
 	if (net_eq(sock_net(sk), net) && inet->inet_num == hnum &&
 			!ipv6_only_sock(sk)) {
 		__be32 rcv_saddr = inet->inet_rcv_saddr;
-		score = sk->sk_family == PF_INET ? 1 : 0;
+		score = sk->sk_family == PF_INET ? 2 : 1;
 		if (rcv_saddr) {
 			if (rcv_saddr != daddr)
 				return -1;
-			score += 2;
+			score += 4;
 		}
 		if (sk->sk_bound_dev_if) {
 			if (sk->sk_bound_dev_if != dif)
 				return -1;
-			score += 2;
+			score += 4;
 		}
 	}
 	return score;
@@ -176,6 +177,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
 
 struct sock *__inet_lookup_listener(struct net *net,
 				    struct inet_hashinfo *hashinfo,
+				    const __be32 saddr, __be16 sport,
 				    const __be32 daddr, const unsigned short hnum,
 				    const int dif)
 {
@@ -183,17 +185,29 @@ struct sock *__inet_lookup_listener(struct net *net,
 	struct hlist_nulls_node *node;
 	unsigned int hash = inet_lhashfn(net, hnum);
 	struct inet_listen_hashbucket *ilb = &hashinfo->listening_hash[hash];
-	int score, hiscore;
+	int score, hiscore, matches = 0, reuseport = 0;
+	u32 phash = 0;
 
 	rcu_read_lock();
 begin:
 	result = NULL;
-	hiscore = -1;
+	hiscore = 0;
 	sk_nulls_for_each_rcu(sk, node, &ilb->head) {
 		score = compute_score(sk, net, hnum, daddr, dif);
 		if (score > hiscore) {
 			result = sk;
 			hiscore = score;
+			reuseport = sk->sk_reuseport;
+			if (reuseport) {
+				phash = inet_ehashfn(net, daddr, hnum,
+						     saddr, sport);
+				matches = 1;
+			}
+		} else if (score == hiscore && reuseport) {
+			matches++;
+			if (((u64)phash * matches) >> 32 == 0)
+				result = sk;
+			phash = next_pseudo_random32(phash);
 		}
 	}
 	/*
@@ -501,7 +515,8 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 			inet_bind_bucket_for_each(tb, node, &head->chain) {
 				if (net_eq(ib_net(tb), net) &&
 				    tb->port == port) {
-					if (tb->fastreuse >= 0)
+					if (tb->fastreuse >= 0 ||
+					    tb->fastreuseport >= 0)
 						goto next_port;
 					WARN_ON(hlist_empty(&tb->owners));
 					if (!check_established(death_row, sk,
@@ -518,6 +533,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 				break;
 			}
 			tb->fastreuse = -1;
+			tb->fastreuseport = -1;
 			goto ok;
 
 		next_port:
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index c6ce9ca..bbbdcc5 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -657,7 +657,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 		 * no RST generated if md5 hash doesn't match.
 		 */
 		sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
-					     &tcp_hashinfo, ip_hdr(skb)->daddr,
+					     &tcp_hashinfo, ip_hdr(skb)->saddr,
+					     th->source, ip_hdr(skb)->daddr,
 					     ntohs(th->source), inet_iif(skb));
 		/* don't send rst if it can't find key */
 		if (!sk1)
@@ -2074,6 +2075,7 @@ do_time_wait:
 	case TCP_TW_SYN: {
 		struct sock *sk2 = inet_lookup_listener(dev_net(skb->dev),
 							&tcp_hashinfo,
+							iph->saddr, th->source,
 							iph->daddr, th->dest,
 							inet_iif(skb));
 		if (sk2) {
-- 
1.7.7.3

^ permalink raw reply related

* [PATCH 1/5] soreuseport: infrastructure
From: Tom Herbert @ 2013-01-22 19:49 UTC (permalink / raw)
  To: netdev, davem; +Cc: netdev, eric.dumazet

Definitions and macros for implementing soreusport.

Signed-off-by: Tom Herbert <therbert@google.com>
---
 arch/alpha/include/uapi/asm/socket.h   |    2 +-
 arch/avr32/include/uapi/asm/socket.h   |    2 +-
 arch/cris/include/uapi/asm/socket.h    |    2 +-
 arch/frv/include/uapi/asm/socket.h     |    2 +-
 arch/h8300/include/uapi/asm/socket.h   |    2 +-
 arch/ia64/include/uapi/asm/socket.h    |    2 +-
 arch/m32r/include/uapi/asm/socket.h    |    2 +-
 arch/mips/include/uapi/asm/socket.h    |    3 +--
 arch/mn10300/include/uapi/asm/socket.h |    2 +-
 arch/parisc/include/uapi/asm/socket.h  |    2 +-
 arch/powerpc/include/uapi/asm/socket.h |    2 +-
 arch/s390/include/uapi/asm/socket.h    |    2 +-
 arch/sparc/include/uapi/asm/socket.h   |    2 +-
 arch/xtensa/include/uapi/asm/socket.h  |    2 +-
 include/linux/random.h                 |    6 ++++++
 include/net/sock.h                     |    5 ++++-
 include/uapi/asm-generic/socket.h      |    3 +--
 net/core/sock.c                        |    7 +++++++
 18 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 755702e..c519552 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -19,7 +19,7 @@
 #define SO_BROADCAST	0x0020
 #define SO_LINGER	0x0080
 #define SO_OOBINLINE	0x0100
-/* To add :#define SO_REUSEPORT 0x0200 */
+#define SO_REUSEPORT	0x0200
 
 #define SO_TYPE		0x1008
 #define SO_ERROR	0x1007
diff --git a/arch/avr32/include/uapi/asm/socket.h b/arch/avr32/include/uapi/asm/socket.h
index f3f38a0..51c6401 100644
--- a/arch/avr32/include/uapi/asm/socket.h
+++ b/arch/avr32/include/uapi/asm/socket.h
@@ -22,7 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/cris/include/uapi/asm/socket.h b/arch/cris/include/uapi/asm/socket.h
index 406b583..50692b7 100644
--- a/arch/cris/include/uapi/asm/socket.h
+++ b/arch/cris/include/uapi/asm/socket.h
@@ -24,7 +24,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/frv/include/uapi/asm/socket.h b/arch/frv/include/uapi/asm/socket.h
index d8e1132..595391f 100644
--- a/arch/frv/include/uapi/asm/socket.h
+++ b/arch/frv/include/uapi/asm/socket.h
@@ -22,7 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/h8300/include/uapi/asm/socket.h b/arch/h8300/include/uapi/asm/socket.h
index c8b87a8..43e3262 100644
--- a/arch/h8300/include/uapi/asm/socket.h
+++ b/arch/h8300/include/uapi/asm/socket.h
@@ -22,7 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/ia64/include/uapi/asm/socket.h b/arch/ia64/include/uapi/asm/socket.h
index f390896..c567adc 100644
--- a/arch/ia64/include/uapi/asm/socket.h
+++ b/arch/ia64/include/uapi/asm/socket.h
@@ -31,7 +31,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/m32r/include/uapi/asm/socket.h b/arch/m32r/include/uapi/asm/socket.h
index 6a89515..519afa2 100644
--- a/arch/m32r/include/uapi/asm/socket.h
+++ b/arch/m32r/include/uapi/asm/socket.h
@@ -22,7 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index 9d11a77..7e27236 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -28,8 +28,7 @@
 #define SO_LINGER	0x0080	/* Block on close of a reliable
 				   socket to transmit pending data.  */
 #define SO_OOBINLINE 0x0100	/* Receive out-of-band data in-band.  */
-#if 0
-To add: #define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
+#define SO_REUSEPORT 0x0200	/* Allow local address and port reuse.  */
 #endif
 
 #define SO_TYPE		0x1008	/* Compatible name for SO_STYLE.  */
diff --git a/arch/mn10300/include/uapi/asm/socket.h b/arch/mn10300/include/uapi/asm/socket.h
index ab702c4..5c7c7c9 100644
--- a/arch/mn10300/include/uapi/asm/socket.h
+++ b/arch/mn10300/include/uapi/asm/socket.h
@@ -22,7 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index da2c8d3..526e4b9 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -13,7 +13,7 @@
 #define SO_BROADCAST	0x0020
 #define SO_LINGER	0x0080
 #define SO_OOBINLINE	0x0100
-/* To add :#define SO_REUSEPORT 0x0200 */
+#define SO_REUSEPORT	0x0200
 #define SO_SNDBUF	0x1001
 #define SO_RCVBUF	0x1002
 #define SO_SNDBUFFORCE	0x100a
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h
index e6ca318..a26dcae 100644
--- a/arch/powerpc/include/uapi/asm/socket.h
+++ b/arch/powerpc/include/uapi/asm/socket.h
@@ -29,7 +29,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_RCVLOWAT	16
 #define SO_SNDLOWAT	17
 #define SO_RCVTIMEO	18
diff --git a/arch/s390/include/uapi/asm/socket.h b/arch/s390/include/uapi/asm/socket.h
index 9ce60b6..f99eea7 100644
--- a/arch/s390/include/uapi/asm/socket.h
+++ b/arch/s390/include/uapi/asm/socket.h
@@ -28,7 +28,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index fbbba57..cbbad74 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -15,7 +15,7 @@
 #define SO_PEERCRED	0x0040
 #define SO_LINGER	0x0080
 #define SO_OOBINLINE	0x0100
-/* To add :#define SO_REUSEPORT 0x0200 */
+#define SO_REUSEPORT	0x0200
 #define SO_BSDCOMPAT    0x0400
 #define SO_RCVLOWAT     0x0800
 #define SO_SNDLOWAT     0x1000
diff --git a/arch/xtensa/include/uapi/asm/socket.h b/arch/xtensa/include/uapi/asm/socket.h
index dbf3164..35905cb 100644
--- a/arch/xtensa/include/uapi/asm/socket.h
+++ b/arch/xtensa/include/uapi/asm/socket.h
@@ -32,7 +32,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
+#define SO_REUSEPORT	15
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
 #define SO_RCVLOWAT	18
diff --git a/include/linux/random.h b/include/linux/random.h
index d984608..347ce55 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -74,4 +74,10 @@ static inline int arch_get_random_int(unsigned int *v)
 }
 #endif
 
+/* Pseudo random number generator from numerical recipes. */
+static inline u32 next_pseudo_random32(u32 seed)
+{
+	return seed * 1664525 + 1013904223;
+}
+
 #endif /* _LINUX_RANDOM_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index 5a34e2f..581dc6b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -140,6 +140,7 @@ typedef __u64 __bitwise __addrpair;
  *	@skc_family: network address family
  *	@skc_state: Connection state
  *	@skc_reuse: %SO_REUSEADDR setting
+ *	@skc_reuseport: %SO_REUSEPORT setting
  *	@skc_bound_dev_if: bound device index if != 0
  *	@skc_bind_node: bind hash linkage for various protocol lookup tables
  *	@skc_portaddr_node: second hash linkage for UDP/UDP-Lite protocol
@@ -179,7 +180,8 @@ struct sock_common {
 
 	unsigned short		skc_family;
 	volatile unsigned char	skc_state;
-	unsigned char		skc_reuse;
+	unsigned char		skc_reuse:4;
+	unsigned char		skc_reuseport:4;
 	int			skc_bound_dev_if;
 	union {
 		struct hlist_node	skc_bind_node;
@@ -297,6 +299,7 @@ struct sock {
 #define sk_family		__sk_common.skc_family
 #define sk_state		__sk_common.skc_state
 #define sk_reuse		__sk_common.skc_reuse
+#define sk_reuseport		__sk_common.skc_reuseport
 #define sk_bound_dev_if		__sk_common.skc_bound_dev_if
 #define sk_bind_node		__sk_common.skc_bind_node
 #define sk_prot			__sk_common.skc_prot
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index 3f6a992..4ef3acb 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -22,8 +22,7 @@
 #define SO_PRIORITY	12
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
-/* To add :#define SO_REUSEPORT 15 */
-
+#define SO_REUSEPORT	15
 #ifndef SO_PASSCRED /* powerpc only differs in these */
 #define SO_PASSCRED	16
 #define SO_PEERCRED	17
diff --git a/net/core/sock.c b/net/core/sock.c
index 8258fb7..235fb89 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -665,6 +665,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
 	case SO_REUSEADDR:
 		sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
 		break;
+	case SO_REUSEPORT:
+		sk->sk_reuseport = valbool;
+		break;
 	case SO_TYPE:
 	case SO_PROTOCOL:
 	case SO_DOMAIN:
@@ -972,6 +975,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
 		v.val = sk->sk_reuse;
 		break;
 
+	case SO_REUSEPORT:
+		v.val = sk->sk_reuseport;
+		break;
+
 	case SO_KEEPALIVE:
 		v.val = sock_flag(sk, SOCK_KEEPOPEN);
 		break;
-- 
1.7.7.3

^ permalink raw reply related

* [PATCH 0/5]: soreuseport: Bind multiple sockets to the same port
From: Tom Herbert @ 2013-01-22 19:49 UTC (permalink / raw)
  To: netdev, davem; +Cc: netdev, eric.dumazet

[-- Attachment #1: Type: TEXT/PLAIN, Size: 2587 bytes --]

This series implements so_reuseport (SO_REUSEPORT socket option) for
TCP and UDP.  For TCP, so_reuseport allows multiple listener sockets
to be bound to the same port.  In the case of UDP, so_reuseport allows
multiple sockets to bind to the same port.  To prevent port hijacking
all sockets bound to the same port using so_reuseport must have the
same uid.  Received packets are distributed to multiple sockets bound
to the same port using a 4-tuple hash.

The motivating case for so_resuseport in TCP would be something like
a web server binding to port 80 running with multiple threads, where
each thread might have it's own listener socket.  This could be done
as an alternative to other models: 1) have one listener thread which
dispatches completed connections to workers. 2) accept on a single
listener socket from multiple threads.  In case #1 the listener thread
can easily become the bottleneck with high connection turn-over rate.
In case #2, the proportion of connections accepted per thread tends
to be uneven under high connection load (assuming simple event loop:
while (1) { accept(); process() }, wakeup does not promote fairness
among the sockets.  We have seen the  disproportion to be as high
as 3:1 ratio between thread accepting most connections and the one
accepting the fewest.  With so_reusport the distribution is
uniform.

The TCP implementation has a problem in that the request sockets for a
listener are attached to a listener socket.  If a SYN is received, a
listener socket is chosen and request structure is created (SYN-RECV
state).  If the subsequent ack in 3WHS does not match the same port
by so_reusport, the connection state is not found (reset) and the
request structure is orphaned.  This scenario would occur when the
number of listener sockets bound to a port changes (new ones are
added, or old ones closed).  We are looking for a solution to this,
maybe allow multiple sockets to share the same request table...

The motivating case for so_reuseport in UDP would be something like a
DNS server.  An alternative would be to recv on the same socket from
multiple threads.  As in the case of TCP, the load across these threads
tends to be disproportionate and we also see a lot of contection on
the socket lock.  Note that SO_REUSEADDR already allows multiple UDP
sockets to bind to the same port, however there is no provision to
prevent hijacking and nothing to distribute packets across all the
sockets sharing the same bound port.  This patch does not change the
semantics of SO_REUSEADDR, but provides usable functionality of it
for unicast.

^ permalink raw reply

* Re: [PATCH RFC net-next 00/15] drivers/net: obsolete ISA driver round-up
From: David Miller @ 2013-01-22 19:49 UTC (permalink / raw)
  To: paul.gortmaker
  Cc: netdev, becker, jeffrey.t.kirsher, alan, andi, janpascal, miku
In-Reply-To: <1358819182-28032-1-git-send-email-paul.gortmaker@windriver.com>

From: Paul Gortmaker <paul.gortmaker@windriver.com>
Date: Mon, 21 Jan 2013 20:46:07 -0500

> git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux.git legacy-isa-delete

This seems entirely reasonable, pulled thanks Paul.

And thanks even more for the verbose justification text, which I've
added to the merge commit message.

^ permalink raw reply

* Re: [PATCH v5 01/45] percpu_rwlock: Introduce the global reader-writer lock backend
From: Srivatsa S. Bhat @ 2013-01-22 19:41 UTC (permalink / raw)
  To: Stephen Hemminger
  Cc: tglx, peterz, tj, oleg, paulmck, rusty, mingo, akpm, namhyung,
	rostedt, wangyun, xiaoguangrong, rjw, sbw, fweisbec, linux,
	nikunj, linux-pm, linux-arch, linux-arm-kernel, linuxppc-dev,
	netdev, linux-doc, linux-kernel
In-Reply-To: <20130122104506.32b4e581@nehalam.linuxnetplumber.net>

On 01/23/2013 12:15 AM, Stephen Hemminger wrote:
> On Tue, 22 Jan 2013 13:03:22 +0530
> "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com> wrote:
> 
>> A straight-forward (and obvious) algorithm to implement Per-CPU Reader-Writer
>> locks can also lead to too many deadlock possibilities which can make it very
>> hard/impossible to use. This is explained in the example below, which helps
>> justify the need for a different algorithm to implement flexible Per-CPU
>> Reader-Writer locks.
>>
>> We can use global rwlocks as shown below safely, without fear of deadlocks:
>>
>> Readers:
>>
>>          CPU 0                                CPU 1
>>          ------                               ------
>>
>> 1.    spin_lock(&random_lock);             read_lock(&my_rwlock);
>>
>>
>> 2.    read_lock(&my_rwlock);               spin_lock(&random_lock);
>>
>>
>> Writer:
>>
>>          CPU 2:
>>          ------
>>
>>        write_lock(&my_rwlock);
>>
>>
>> We can observe that there is no possibility of deadlocks or circular locking
>> dependencies here. Its perfectly safe.
>>
>> Now consider a blind/straight-forward conversion of global rwlocks to per-CPU
>> rwlocks like this:
>>
>> The reader locks its own per-CPU rwlock for read, and proceeds.
>>
>> Something like: read_lock(per-cpu rwlock of this cpu);
>>
>> The writer acquires all per-CPU rwlocks for write and only then proceeds.
>>
>> Something like:
>>
>>   for_each_online_cpu(cpu)
>> 	write_lock(per-cpu rwlock of 'cpu');
>>
>>
>> Now let's say that for performance reasons, the above scenario (which was
>> perfectly safe when using global rwlocks) was converted to use per-CPU rwlocks.
>>
>>
>>          CPU 0                                CPU 1
>>          ------                               ------
>>
>> 1.    spin_lock(&random_lock);             read_lock(my_rwlock of CPU 1);
>>
>>
>> 2.    read_lock(my_rwlock of CPU 0);       spin_lock(&random_lock);
>>
>>
>> Writer:
>>
>>          CPU 2:
>>          ------
>>
>>       for_each_online_cpu(cpu)
>>         write_lock(my_rwlock of 'cpu');
>>
>>
>> Consider what happens if the writer begins his operation in between steps 1
>> and 2 at the reader side. It becomes evident that we end up in a (previously
>> non-existent) deadlock due to a circular locking dependency between the 3
>> entities, like this:
>>
>>
>> (holds              Waiting for
>>  random_lock) CPU 0 -------------> CPU 2  (holds my_rwlock of CPU 0
>>                                                for write)
>>                ^                   |
>>                |                   |
>>         Waiting|                   | Waiting
>>           for  |                   |  for
>>                |                   V
>>                 ------ CPU 1 <------
>>
>>                 (holds my_rwlock of
>>                  CPU 1 for read)
>>
>>
>>
>> So obviously this "straight-forward" way of implementing percpu rwlocks is
>> deadlock-prone. One simple measure for (or characteristic of) safe percpu
>> rwlock should be that if a user replaces global rwlocks with per-CPU rwlocks
>> (for performance reasons), he shouldn't suddenly end up in numerous deadlock
>> possibilities which never existed before. The replacement should continue to
>> remain safe, and perhaps improve the performance.
>>
>> Observing the robustness of global rwlocks in providing a fair amount of
>> deadlock safety, we implement per-CPU rwlocks as nothing but global rwlocks,
>> as a first step.
>>
>>
>> Cc: David Howells <dhowells@redhat.com>
>> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
> 
> We got rid of brlock years ago, do we have to reintroduce it like this?
> The problem was that brlock caused starvation.
> 

Um? I still see it in include/linux/lglock.h and its users in fs/ directory.

BTW, I'm not advocating that everybody start converting their global reader-writer
locks to per-cpu rwlocks, because such a conversion probably won't make sense
in all scenarios.

The thing is, for CPU hotplug in particular, the "preempt_disable() at the reader;
stop_machine() at the writer" scheme had some very desirable properties at the
reader side (even though people might hate stop_machine() with all their
heart ;-)), namely : 

At the reader side:

o No need to hold locks to prevent CPU offline
o Extremely fast/optimized updates (the preempt count)
o No need for heavy memory barriers
o Extremely flexible nesting rules

So this made perfect sense at the reader for CPU hotplug, because it is expected
that CPU hotplug operations are very infrequent, and it is well-known that quite
a few atomic hotplug readers are in very hot paths. The problem was that the
stop_machine() at the writer was not only a little too heavy, but also inflicted
real-time latencies on the system because it needed cooperation from _all_ CPUs
synchronously, to take one CPU down.

So the idea is to get rid of stop_machine() without hurting the reader side.
And this scheme of per-cpu rwlocks comes close to ensuring that. (You can look
at the previous versions of this patchset [links given in cover letter] to see
what other schemes we hashed out before coming to this one).

The only reason I exposed this as a generic locking scheme was because Tejun
pointed out that, complex locking schemes implemented in individual subsystems
is not such a good idea. And also this comes at a time when per-cpu rwsemaphores
have just been introduced in the kernel and Oleg had ideas about converting the
cpu hotplug (sleepable) locking to use them.

Regards,
Srivatsa S. Bhat

^ permalink raw reply

* Re: BUG in netxen_release_tx_buffers when TSO enabled on kernels >= 3.3 and <= 3.6
From: Ben Hutchings @ 2013-01-22 19:36 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: christoph.paasch, Ian Campbell, Sony Chacko, Rajesh Borundia,
	David Miller, netdev
In-Reply-To: <1358862966.3464.3797.camel@edumazet-glaptop>

On Tue, 2013-01-22 at 05:56 -0800, Eric Dumazet wrote:
> On Tue, 2013-01-22 at 05:32 -0800, Eric Dumazet wrote:
> 
> > 
> > Something doesn't properly test MAX_SKB_FRAGS, we should track it and
> > fix.
> 
> I guess netxen driver has a bug.
> 
> Please try the following patch :
> 
> diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> index bc165f4..695667d 100644
> --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
> @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter)
>  					 buffrag->length, PCI_DMA_TODEVICE);
>  			buffrag->dma = 0ULL;
>  		}
> -		for (j = 0; j < cmd_buf->frag_count; j++) {
> +		for (j = 1; j < cmd_buf->frag_count; j++) {
>  			buffrag++;
>  			if (buffrag->dma) {
>  				pci_unmap_page(adapter->pdev, buffrag->dma,
> 

There's another bug right here, which is that 0 is a valid DMA address
in some systems.  The driver should be calling pci_dma_mapping_error()
to find out whether an address is valid or not.  But it also wants to be
able to assign an invalid address to netxen_skb_frag::dma, and
unfortunately there is no way to do that in the current DMA API.

Ben.

-- 
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.

^ permalink raw reply

* Re: [PATCH v5 01/45] percpu_rwlock: Introduce the global reader-writer lock backend
From: Steven Rostedt @ 2013-01-22 19:32 UTC (permalink / raw)
  To: Srivatsa S. Bhat
  Cc: tglx, peterz, tj, oleg, paulmck, rusty, mingo, akpm, namhyung,
	wangyun, xiaoguangrong, rjw, sbw, fweisbec, linux, nikunj,
	linux-pm, linux-arch, linux-arm-kernel, linuxppc-dev, netdev,
	linux-doc, linux-kernel
In-Reply-To: <20130122073315.13822.27093.stgit@srivatsabhat.in.ibm.com>

On Tue, 2013-01-22 at 13:03 +0530, Srivatsa S. Bhat wrote:
> A straight-forward (and obvious) algorithm to implement Per-CPU Reader-Writer
> locks can also lead to too many deadlock possibilities which can make it very
> hard/impossible to use. This is explained in the example below, which helps
> justify the need for a different algorithm to implement flexible Per-CPU
> Reader-Writer locks.
> 
> We can use global rwlocks as shown below safely, without fear of deadlocks:
> 
> Readers:
> 
>          CPU 0                                CPU 1
>          ------                               ------
> 
> 1.    spin_lock(&random_lock);             read_lock(&my_rwlock);
> 
> 
> 2.    read_lock(&my_rwlock);               spin_lock(&random_lock);
> 
> 
> Writer:
> 
>          CPU 2:
>          ------
> 
>        write_lock(&my_rwlock);
> 

I thought global locks are now fair. That is, a reader will block if a
writer is waiting. Hence, the above should deadlock on the current
rwlock_t types.

We need to fix those locations (or better yet, remove all rwlocks ;-)

-- Steve

^ permalink raw reply

* Re: [PATCH net-next 0/4] Use IS_ERR_OR_NULL().
From: David Miller @ 2013-01-22 19:28 UTC (permalink / raw)
  To: yoshfuji; +Cc: netdev
In-Reply-To: <50FEBF1E.6070209@linux-ipv6.org>

From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Wed, 23 Jan 2013 01:32:30 +0900

> YOSHIFUJI Hideaki (4):
>   net: Use IS_ERR_OR_NULL().
>   ipv4: Use IS_ERR_OR_NULL().
>   ipv6: Use IS_ERR_OR_NULL().
>   netfilter: Use IS_ERR_OR_NULL().

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next (v2, reword)] neigh: Keep neighbour cache entries if number of them is small enough.
From: David Miller @ 2013-01-22 19:25 UTC (permalink / raw)
  To: yoshfuji; +Cc: netdev
In-Reply-To: <50FEAE25.4040008@linux-ipv6.org>

From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Wed, 23 Jan 2013 00:20:05 +0900

> Since we have removed NCE (Neighbour Cache Entry) reference from
> routing entries, the only refcnt holders of an NCE are its timer
> (if running) and its owner table, in usual cases.  As a result,
> neigh_periodic_work() purges NCEs over and over again even for
> gateways.
> 
> It does not make sense to purge entries, if number of them is
> very small, so keep them.  The minimum number of entries to keep
> is specified by gc_thresh1.
> 
> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next] ipmr: fix sparse warning when testing origin or group
From: David Miller @ 2013-01-22 19:24 UTC (permalink / raw)
  To: nicolas.dichtel; +Cc: fengguang.wu, netdev
In-Reply-To: <1358849883-10452-1-git-send-email-nicolas.dichtel@6wind.com>

From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Tue, 22 Jan 2013 11:18:03 +0100

> mfc_mcastgrp and mfc_origin are __be32, thus we need to convert INADDR_ANY.
> Because INADDR_ANY is 0, this patch just fix sparse warnings.
> 
> Reported-by: Fengguang Wu <fengguang.wu@intel.com>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] ipv4: Fix route refcount on pmtu discovery
From: David Miller @ 2013-01-22 19:23 UTC (permalink / raw)
  To: steffen.klassert; +Cc: ja, netdev
In-Reply-To: <20130122100128.GD9147@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Tue, 22 Jan 2013 11:01:28 +0100

> git commit 9cb3a50c (ipv4: Invalidate the socket cached route on
> pmtu events if possible) introduced a refcount problem. We don't
> get a refcount on the route if we get it from__sk_dst_get(), but
> we need one if we want to reuse this route because __sk_dst_set()
> releases the refcount of the old route. This patch adds proper
> refcount handling for that case. We introduce a 'new' flag to
> indicate that we are going to use a new route and we release the
> old route only if we replace it by a new one.
> 
> Reported-by: Julian Anastasov <ja@ssi.bg>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

Applied, thanks.

^ permalink raw reply

* Re: pull request: ipsec 2013-01-22
From: David Miller @ 2013-01-22 19:21 UTC (permalink / raw)
  To: steffen.klassert; +Cc: herbert, netdev
In-Reply-To: <1358845596-2066-1-git-send-email-steffen.klassert@secunet.com>

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: Tue, 22 Jan 2013 10:06:31 +0100

> 1) The transport header did not point to the right place after
>    esp/ah processing on tunnel mode in the receive path. As a
>    result, the ECN field of the inner header was not set correctly,
>    fixes from Li RongQing.
> 
> 2) We did a null check too late in one of the xfrm_replay advance
>    functions. This can lead to a division by zero, fix from
>    Nickolai Zeldovich.
> 
> 3) The size calculation of the hash table missed the muiltplication
>    with the actual struct size when the hash table is freed.
>    We might call the wrong free function, fix from Michal Kubecek.
> 
> 4) On IPsec pmtu events we can't access the transport headers of
>    the original packet, so force a relookup for all routes
>    to notify about the pmtu event.
> 
> Please pull or let me know if there are problems.

Pulled, thakns a lot.

Please be explicit in the future about what tree a set of changes are
targetted at.

Thanks.

^ permalink raw reply

* [PATCH] net/ceph/osdmap.c: fix undefined behavior when using snprintf()
From: Cong Ding @ 2013-01-22 19:20 UTC (permalink / raw)
  To: Sage Weil, David S. Miller, ceph-devel, netdev, linux-kernel; +Cc: Cong Ding

The variable "str" is used as both the source and destination in function
snprintf(), which is undefined behavior based on C11. The original description
in C11 is:
	"If copying takes place between objects that
	overlap, the behavior is undefined."

And, the function of ceph_osdmap_state_str() is to return the osdmap state, so
it should return "doesn't exist" when all the conditions are not satisfied. I
fix it in this patch.

Based on C11, snprintf() does nothing if n==0:
	"If n is zero, nothing is written, and s may be a
	null pointer. Otherwise, output characters beyond
	the n-1st are discarded rather than being written to
	the array, and a null character is written at the
	end of the characters actually written into the
	array."
so I remove the unnecessary check of len (because it is not a busy path and
saves a few lines of code).

Signed-off-by: Cong Ding <dinggnu@gmail.com>
---
 net/ceph/osdmap.c |   27 ++++++++-------------------
 1 file changed, 8 insertions(+), 19 deletions(-)

diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index de73214..3131a99d3 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -13,26 +13,15 @@
 
 char *ceph_osdmap_state_str(char *str, int len, int state)
 {
-	int flag = 0;
-
-	if (!len)
-		goto done;
-
-	*str = '\0';
-	if (state) {
-		if (state & CEPH_OSD_EXISTS) {
-			snprintf(str, len, "exists");
-			flag = 1;
-		}
-		if (state & CEPH_OSD_UP) {
-			snprintf(str, len, "%s%s%s", str, (flag ? ", " : ""),
-				 "up");
-			flag = 1;
-		}
-	} else {
+	if ((state & CEPH_OSD_EXISTS) && (state & CEPH_OSD_UP))
+		snprintf(str, len, "exists, up");
+	else if (state & CEPH_OSD_EXISTS)
+		snprintf(str, len, "exists");
+	else if (state & CEPH_OSD_UP)
+		snprintf(str, len, "up");
+	else
 		snprintf(str, len, "doesn't exist");
-	}
-done:
+
 	return str;
 }
 
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH net-next 1/2] be2net: Modify GPL Marking in all source files.
From: David Miller @ 2013-01-22 19:19 UTC (permalink / raw)
  To: sarveshwar.bandi; +Cc: netdev, vasundhara.volam
In-Reply-To: <d01bcb2c-5921-4324-a28a-fe0d0729bf49@CMEXHTCAS1.ad.emulex.com>

From: <sarveshwar.bandi@emulex.com>
Date: Tue, 22 Jan 2013 13:44:08 +0530

> From: Vasundhara Volam <vasundhara.volam@emulex.com>
> 
> Signed-off-by: Vasundhara Volam <vasundhara.volam@emulex.com>
> Signed-off-by: Sarveshwar Bandi <sarveshwar.bandi@emulex.com>
> ---

You're going to have to say more than that in your commit message when
you change something as delicate as copyright designations.

"What are you doing" and more importantly exactly "Why" are you doing
it.

^ permalink raw reply

* Re: BUG in netxen_release_tx_buffers when TSO enabled on kernels >= 3.3 and <= 3.6
From: David Miller @ 2013-01-22 19:15 UTC (permalink / raw)
  To: eric.dumazet
  Cc: christoph.paasch, Ian.Campbell, sony.chacko, rajesh.borundia,
	netdev
In-Reply-To: <1358872385.3464.3940.camel@edumazet-glaptop>

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 22 Jan 2013 08:33:05 -0800

> From: Eric Dumazet <edumazet@google.com>
 ...
> [PATCH] netxen: fix off by one bug in netxen_release_tx_buffer()
> 
> Christoph Paasch found netxen could trigger a BUG in its dismantle
> phase, in netxen_release_tx_buffer(), using full size TSO packets.
> 
> cmd_buf->frag_count includes the skb->data part, so the loop must
> start at index 1 instead of 0, or else we can make an out
> of bound access to cmd_buff->frag_array[MAX_SKB_FRAGS + 2]
> 
> Christoph provided the fixes in netxen_map_tx_skb() function.
> In case of a dma mapping error, its better to clear the dma fields
> so that we don't try to unmap them again in netxen_release_tx_buffer()
> 
> Reported-by: Christoph Paasch <christoph.paasch@uclouvain.be>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Tested-by: Christoph Paasch <christoph.paasch@uclouvain.be>

Applied and queued up for -stable, thanks.

^ permalink raw reply

* Re: [PATCH 16/20] drivers/net/wireless/p54: remove depends on CONFIG_EXPERIMENTAL
From: John W. Linville @ 2013-01-22 19:14 UTC (permalink / raw)
  To: David Miller; +Cc: keescook, chunkeey, linux-kernel, netdev, gregkh, kvalo
In-Reply-To: <20130122.141252.781223481145097577.davem@davemloft.net>

On Tue, Jan 22, 2013 at 02:12:52PM -0500, David Miller wrote:
> From: Kees Cook <keescook@chromium.org>
> Date: Tue, 22 Jan 2013 10:40:12 -0800
> 
> > On Tue, Jan 22, 2013 at 10:37 AM, Christian Lamparter
> > <chunkeey@googlemail.com> wrote:
> >> Aren't these patches going through wireless-next
> >> or linux-next?
> > 
> > They can go however it makes things easiest. Greg has offered to carry
> > them in driver-core if Dave doesn't want to carry them in netdev.
> 
> Greg can take these:
> 
> Acked-by: David S. Miller <davem@davemloft.net>

Acked-by: John W. Linville <linville@tuxdriver.com>

-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* Re: [PATCH 16/20] drivers/net/wireless/p54: remove depends on CONFIG_EXPERIMENTAL
From: David Miller @ 2013-01-22 19:12 UTC (permalink / raw)
  To: keescook; +Cc: chunkeey, linux-kernel, netdev, gregkh, linville, kvalo
In-Reply-To: <CAGXu5jJCQshUntUk7MeZds59B2fa54GnonOz28dM1x2spEEGDg@mail.gmail.com>

From: Kees Cook <keescook@chromium.org>
Date: Tue, 22 Jan 2013 10:40:12 -0800

> On Tue, Jan 22, 2013 at 10:37 AM, Christian Lamparter
> <chunkeey@googlemail.com> wrote:
>> Aren't these patches going through wireless-next
>> or linux-next?
> 
> They can go however it makes things easiest. Greg has offered to carry
> them in driver-core if Dave doesn't want to carry them in netdev.

Greg can take these:

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

^ permalink raw reply

* Re: [PATCH 20/33] net: Convert to devm_ioremap_resource()
From: David Miller @ 2013-01-22 19:08 UTC (permalink / raw)
  To: arnd; +Cc: thierry.reding, linux-kernel, gregkh, dmitry.torokhov, w.sang,
	netdev
In-Reply-To: <201301221303.06785.arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Tue, 22 Jan 2013 13:03:06 +0000

> On Tuesday 22 January 2013, Thierry Reding wrote:
>> I planned to do so initially, but that yielded a Cc list of 156 people
>> and mailing lists, which I thought wasn't going to go down so well
>> either. In general I like Cc'ing everyone concerned on all patches of
>> the series, specifically for reasons of context. Some people have been
>> annoyed when I did so. Still, for small series where only a few dozen
>> people are concerned that seems to me to be the best way. But 156 email
>> addresses is a different story.
>> 
>> Either you add to many people or you don't add enough. Where do we draw
>> the line?
> 
> I've had the same problem a couple of times. The best compromise seems
> to be to Cc only the top-level subsystem maintainers and mailing lists
> on the first email.

CC:'ing individuals is pointless, CC: only the subsystem lists in
question, the maintainers had better be reading those lists.

^ permalink raw reply

* Re: [PATCH v3] net, wireless: overwrite default_ethtool_ops
From: David Miller @ 2013-01-22 19:06 UTC (permalink / raw)
  To: sgruszka-H+wXaHxf7aLQT0dZR+AlfA
  Cc: mcgrof-3uybbJdB1yH774rrrx3eTA, bhutchings-s/n/eUQHGBpZroRs9YW3xA,
	netdev-u79uwXL29TY76Z2rM5mHXA, edumazet-hpIqsD4AKlfQT0dZR+AlfA,
	greearb-my8/4N5VtI7c+919tysfdA, bjorn-yOkvZcmFvRU,
	linux-wireless-u79uwXL29TY76Z2rM5mHXA,
	mirqus-Re5JQEeQqe8AvxtiuMwx3w, johannes-cdvu00un1VgdHxzADdlk8Q
In-Reply-To: <20130122105618.GB2328-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

From: Stanislaw Gruszka <sgruszka-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Date: Tue, 22 Jan 2013 11:56:19 +0100

> On Mon, Jan 21, 2013 at 04:04:04PM -0500, David Miller wrote:
>> 
>> It's queued up for -stable already as is clearly seen at:
>> 
>> http://patchwork.ozlabs.org/user/bundle/2566/?state=*
> 
> Hmm, this link does not work for me (need user/password).

You just need to make a patchwork login, it's visible to any
registered user.

> Anyway, I marked cc -stable in v2 patch, but forgot that in v3.
> Committed patch does not include the mark, so I'll post patch
> to stable just in case.

Do NOT DO THIS, I do the submissions myself, by hand.
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 20/33] net: Convert to devm_ioremap_resource()
From: David Miller @ 2013-01-22 18:58 UTC (permalink / raw)
  To: thierry.reding
  Cc: linux-kernel, gregkh, dmitry.torokhov, arnd, w.sang, netdev
In-Reply-To: <20130122065629.GA14523@avionic-0098.adnet.avionic-design.de>

From: Thierry Reding <thierry.reding@avionic-design.de>
Date: Tue, 22 Jan 2013 07:56:29 +0100

> I planned to do so initially, but that yielded a Cc list of 156 people
> and mailing lists,

Just use mailing lists, the individuals are subscribed to the subsystem
lists that cover what they maintain.

Yes, CC:'ing 156 "people" is stupid.

^ permalink raw reply

* RE: BUG in netxen_release_tx_buffers when TSO enabled on kernels >= 3.3 and <= 3.6
From: Rajesh Borundia @ 2013-01-22 18:46 UTC (permalink / raw)
  To: Eric Dumazet, christoph.paasch@uclouvain.be
  Cc: Ian Campbell, Sony Chacko, David Miller, netdev
In-Reply-To: <1358872385.3464.3940.camel@edumazet-glaptop>

>-----Original Message-----
>From: Eric Dumazet [mailto:eric.dumazet@gmail.com]
>Sent: Tuesday, January 22, 2013 10:03 PM
>To: christoph.paasch@uclouvain.be
>Cc: Ian Campbell; Sony Chacko; Rajesh Borundia; David Miller; netdev
>Subject: Re: BUG in netxen_release_tx_buffers when TSO enabled on
>kernels >= 3.3 and <= 3.6
>
>From: Eric Dumazet <edumazet@google.com>
>
>On Tue, 2013-01-22 at 16:43 +0100, Christoph Paasch wrote:
>> In netxen_map_tx_skb() I think we also have to set nf->dma to 0ULL
>(like the
>> diff below).
>>
>> Otherwise, netxen_release_tx_buffer() may try to unmap something that
>has
>> already been unmapped.
>>
>> I'm not sure - I don't feel very comfortable in driver-code...
>
>It seems fine to me, here is the official combined patch, feel
>free to add your 'Signed-off-by'
>
>Thanks !
>
>[PATCH] netxen: fix off by one bug in netxen_release_tx_buffer()
>
>Christoph Paasch found netxen could trigger a BUG in its dismantle
>phase, in netxen_release_tx_buffer(), using full size TSO packets.
>
>cmd_buf->frag_count includes the skb->data part, so the loop must
>start at index 1 instead of 0, or else we can make an out
>of bound access to cmd_buff->frag_array[MAX_SKB_FRAGS + 2]
>
>Christoph provided the fixes in netxen_map_tx_skb() function.
>In case of a dma mapping error, its better to clear the dma fields
>so that we don't try to unmap them again in netxen_release_tx_buffer()
>
>Reported-by: Christoph Paasch <christoph.paasch@uclouvain.be>
>Signed-off-by: Eric Dumazet <edumazet@google.com>
>Tested-by: Christoph Paasch <christoph.paasch@uclouvain.be>
>Cc: Sony Chacko <sony.chacko@qlogic.com>
>Cc: Rajesh Borundia <rajesh.borundia@qlogic.com>
>---
> drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c |    2 +-
> drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c |    2 ++
> 2 files changed, 3 insertions(+), 1 deletion(-)
>
>diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
>b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
>index bc165f4..695667d 100644
>--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
>+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
>@@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter
>*adapter)
> 					 buffrag->length, PCI_DMA_TODEVICE);
> 			buffrag->dma = 0ULL;
> 		}
>-		for (j = 0; j < cmd_buf->frag_count; j++) {
>+		for (j = 1; j < cmd_buf->frag_count; j++) {
> 			buffrag++;
> 			if (buffrag->dma) {
> 				pci_unmap_page(adapter->pdev, buffrag->dma,
>diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
>b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
>index 6098fd4a..69e321a 100644
>--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
>+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
>@@ -1963,10 +1963,12 @@ unwind:
> 	while (--i >= 0) {
> 		nf = &pbuf->frag_array[i+1];
> 		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
>+		nf->dma = 0ULL;
> 	}
>
> 	nf = &pbuf->frag_array[0];
> 	pci_unmap_single(pdev, nf->dma, skb_headlen(skb),
>PCI_DMA_TODEVICE);
>+	nf->dma = 0ULL;
>
> out_err:
> 	return -ENOMEM;
>
>

Acked-by: Rajesh Borundia <rajesh.borundia@qlogic.com


^ permalink raw reply

* Re: [PATCH v5 01/45] percpu_rwlock: Introduce the global reader-writer lock backend
From: Stephen Hemminger @ 2013-01-22 18:45 UTC (permalink / raw)
  To: Srivatsa S. Bhat
  Cc: tglx, peterz, tj, oleg, paulmck, rusty, mingo, akpm, namhyung,
	rostedt, wangyun, xiaoguangrong, rjw, sbw, fweisbec, linux,
	nikunj, linux-pm, linux-arch, linux-arm-kernel, linuxppc-dev,
	netdev, linux-doc, linux-kernel
In-Reply-To: <20130122073315.13822.27093.stgit@srivatsabhat.in.ibm.com>

On Tue, 22 Jan 2013 13:03:22 +0530
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com> wrote:

> A straight-forward (and obvious) algorithm to implement Per-CPU Reader-Writer
> locks can also lead to too many deadlock possibilities which can make it very
> hard/impossible to use. This is explained in the example below, which helps
> justify the need for a different algorithm to implement flexible Per-CPU
> Reader-Writer locks.
> 
> We can use global rwlocks as shown below safely, without fear of deadlocks:
> 
> Readers:
> 
>          CPU 0                                CPU 1
>          ------                               ------
> 
> 1.    spin_lock(&random_lock);             read_lock(&my_rwlock);
> 
> 
> 2.    read_lock(&my_rwlock);               spin_lock(&random_lock);
> 
> 
> Writer:
> 
>          CPU 2:
>          ------
> 
>        write_lock(&my_rwlock);
> 
> 
> We can observe that there is no possibility of deadlocks or circular locking
> dependencies here. Its perfectly safe.
> 
> Now consider a blind/straight-forward conversion of global rwlocks to per-CPU
> rwlocks like this:
> 
> The reader locks its own per-CPU rwlock for read, and proceeds.
> 
> Something like: read_lock(per-cpu rwlock of this cpu);
> 
> The writer acquires all per-CPU rwlocks for write and only then proceeds.
> 
> Something like:
> 
>   for_each_online_cpu(cpu)
> 	write_lock(per-cpu rwlock of 'cpu');
> 
> 
> Now let's say that for performance reasons, the above scenario (which was
> perfectly safe when using global rwlocks) was converted to use per-CPU rwlocks.
> 
> 
>          CPU 0                                CPU 1
>          ------                               ------
> 
> 1.    spin_lock(&random_lock);             read_lock(my_rwlock of CPU 1);
> 
> 
> 2.    read_lock(my_rwlock of CPU 0);       spin_lock(&random_lock);
> 
> 
> Writer:
> 
>          CPU 2:
>          ------
> 
>       for_each_online_cpu(cpu)
>         write_lock(my_rwlock of 'cpu');
> 
> 
> Consider what happens if the writer begins his operation in between steps 1
> and 2 at the reader side. It becomes evident that we end up in a (previously
> non-existent) deadlock due to a circular locking dependency between the 3
> entities, like this:
> 
> 
> (holds              Waiting for
>  random_lock) CPU 0 -------------> CPU 2  (holds my_rwlock of CPU 0
>                                                for write)
>                ^                   |
>                |                   |
>         Waiting|                   | Waiting
>           for  |                   |  for
>                |                   V
>                 ------ CPU 1 <------
> 
>                 (holds my_rwlock of
>                  CPU 1 for read)
> 
> 
> 
> So obviously this "straight-forward" way of implementing percpu rwlocks is
> deadlock-prone. One simple measure for (or characteristic of) safe percpu
> rwlock should be that if a user replaces global rwlocks with per-CPU rwlocks
> (for performance reasons), he shouldn't suddenly end up in numerous deadlock
> possibilities which never existed before. The replacement should continue to
> remain safe, and perhaps improve the performance.
> 
> Observing the robustness of global rwlocks in providing a fair amount of
> deadlock safety, we implement per-CPU rwlocks as nothing but global rwlocks,
> as a first step.
> 
> 
> Cc: David Howells <dhowells@redhat.com>
> Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>

We got rid of brlock years ago, do we have to reintroduce it like this?
The problem was that brlock caused starvation.

^ permalink raw reply

* Re: Doubts about listen backlog and tcp_max_syn_backlog
From: Leandro Lucarella @ 2013-01-22 18:42 UTC (permalink / raw)
  To: Rick Jones; +Cc: Eric Dumazet, netdev, linux-kernel
In-Reply-To: <50FED7CE.1030008@hp.com>

On Tue, Jan 22, 2013 at 10:17:50AM -0800, Rick Jones wrote:
> >What is important is the backlog, and I guess you didn't increase it
> >properly. The somaxconn default is quite low (128)
> 
> Leandro -
> 
> If that is being overflowed, I believe you should be seeing something like:
> 
>     14 SYNs to LISTEN sockets dropped
> 
> in the output of netstat -s on the system on which the server
> application is running.

What is that value reporting exactly? Because we are using syncookies,
and AFAIK with that enabled, all SYNs are being replied, and what the
listen backlog is really limitting is the "completely  established
sockets waiting to be accepted", according to listen(2). What I don't
really know to be honest, is what a "completely established socket" is,
does it mean that the SYN,ACK was sent, or the ACK was received back?

Also, from the client side, when is the connect(2) call done? When the
SYN,ACK is received?

Thanks!

-- 
Leandro Lucarella
sociomantic labs GmbH
http://www.sociomantic.com

^ permalink raw reply

* Re: [PATCH 16/20] drivers/net/wireless/p54: remove depends on CONFIG_EXPERIMENTAL
From: Kees Cook @ 2013-01-22 18:40 UTC (permalink / raw)
  To: Christian Lamparter
  Cc: LKML, netdev, Greg Kroah-Hartman, John W. Linville,
	David S. Miller, Kalle Valo
In-Reply-To: <201301221937.16916.chunkeey@googlemail.com>

On Tue, Jan 22, 2013 at 10:37 AM, Christian Lamparter
<chunkeey@googlemail.com> wrote:
> Aren't these patches going through wireless-next
> or linux-next?

They can go however it makes things easiest. Greg has offered to carry
them in driver-core if Dave doesn't want to carry them in netdev.

-Kees

>
> On Tuesday, January 22, 2013 07:30:40 PM Kees Cook wrote:
>> The CONFIG_EXPERIMENTAL config item has not carried much meaning for a
>> while now and is almost always enabled by default. As agreed during the
>> Linux kernel summit, remove it from any "depends on" lines in Kconfigs.
>>
>> CC: Christian Lamparter <chunkeey@googlemail.com>
>> CC: "John W. Linville" <linville@tuxdriver.com>
>> Cc: "David S. Miller" <davem@davemloft.net>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: NetDev <netdev@vger.kernel.org>
>> Signed-off-by: Kees Cook <keescook@chromium.org>
> Acked-by: Christian Lamparter <chunkeey@googlemail.com>
> [Also ACK the carl9170, if necessary]
>
> Regards,
>         Chr



--
Kees Cook
Chrome OS Security

^ permalink raw reply

* Re: [PATCH 16/20] drivers/net/wireless/p54: remove depends on CONFIG_EXPERIMENTAL
From: Christian Lamparter @ 2013-01-22 18:37 UTC (permalink / raw)
  To: Kees Cook
  Cc: linux-kernel, netdev, Greg Kroah-Hartman, John W. Linville,
	David S. Miller
In-Reply-To: <1358879444-25834-17-git-send-email-keescook@chromium.org>

Aren't these patches going through wireless-next
or linux-next?

On Tuesday, January 22, 2013 07:30:40 PM Kees Cook wrote:
> The CONFIG_EXPERIMENTAL config item has not carried much meaning for a
> while now and is almost always enabled by default. As agreed during the
> Linux kernel summit, remove it from any "depends on" lines in Kconfigs.
> 
> CC: Christian Lamparter <chunkeey@googlemail.com>
> CC: "John W. Linville" <linville@tuxdriver.com>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: NetDev <netdev@vger.kernel.org>
> Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Christian Lamparter <chunkeey@googlemail.com>
[Also ACK the carl9170, if necessary]

Regards,
	Chr

^ 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