* Re: [PATCH V2 09/12] net/eipoib: Add main driver functionality
From: Ali Ayoub @ 2012-08-07 0:14 UTC (permalink / raw)
To: David Miller
Cc: ebiederm, ogerlitz, roland, netdev, sean.hefty, erezsh, dledford
In-Reply-To: <20120803.163627.1867181085116225405.davem@davemloft.net>
On 8/3/2012 4:36 PM, David Miller wrote:
> From: Ali Ayoub <ali@mellanox.com>
> Date: Fri, 03 Aug 2012 15:39:36 -0700
>
>> Users would like to use sockets API from the VM without re-writing their
>> applications on top of IB verbs, this driver meant to allow such a user
>> to do so.
>
> That's what IPoIB was for, the application writers who don't want to have
> to be knowledgable about IB verbs.
>
> You're messing with the link layer here, and that's what is upsetting me.
>
> It's a complete cop-out to changing the VM tools and emulators properly to
> handle a new link layer.
>
> The applications writers already have a way to use IB whilst using
> something familiar, like IPv4, via IPoIB. You're doing something
> completely different here, and it stinks.
Indeed, IPoIB driver meant to allow IP applications to run over
InfiniBand, but IPoIB cannot serve IPoE traffic.
The goal of eIPoIB driver to show to the user an Ethernet L2 netdev; by
translating IPoE packets to IPoIB. It keeps the same IPoIB wire
protocol, and exposes to the host an ethX interface, all IPoIB packets
are then translated to IPoIB.
Among other things, the main benefit we're targeting is to allow IPoE
traffic within the VM to go through the (Ethernet) vBridge down to the
eIPoIB PIF, and eventually to IPoIB and to the IB network.
In Para virtualized environment, the VM emulator sends/receives packets
with Ethernet header, and the vBridge also performs L2 switching based
on the Ethernet header, in addition to other tools that expect an
Ethernet link layer. We'd like to support them on top of IPoIB.
I see your point to change the the tools and VM emulations to handle
IPoIB link layer, but this involves not only changing many
components/layers such netfront/vbridge/vconfig/etc.. but also -unlike
Ethernet- having IPoIB-aware network device emulation in the VM domain
requires giving access from the VM to the IB Hardware, and this
association will break upon VM migration, as Tsirkin indicated in the
other Email.
Another issue with IPoIB-aware emulator, is that the IPoIB frame doesn't
include the destination link layer per data packet (RFC 4391), therefor
the neighbor address needs to be passed from the VM domain down to the
ipoib-aware vBridge.
I don't see in other alternatives a solution for the problem we're
trying to solve. If there are changes/suggestions to improve eIPoIB
netdev driver to avoid "messing with the link layer" and make it
acceptable, we can discuss and apply them.
^ permalink raw reply
* [RFC][PATCH v2] net-tcp: TCP/IP stack bypass for loopback connections
From: Bruce "Brutus" Curtis @ 2012-08-07 0:13 UTC (permalink / raw)
To: David S. Miller; +Cc: Eric Dumazet, netdev, Bruce "Brutus" Curtis
From: "Bruce \"Brutus\" Curtis" <brutus@google.com>
TCP/IP loopback socket pair stack bypass, based on an idea by, and
rough upstream patch from, David Miller <davem@davemloft.net> called
"friends", the data structure modifcations and connection scheme are
reused with extensive data-path changes.
A new sysctl, net.ipv4.tcp_friends, is added:
0: disable friends and use the stock data path.
1: enable friends and bypass the stack data path, the default.
Note, when friends is enabled any loopback interpose, e.g. tcpdump,
will only see the TCP/IP packets during connection establishment and
finish, all data bypasses the stack and instead is delivered to the
destination socket directly.
This is a 2nd version, the 1st was implemented as an interpose with
new orthogonal friends functions, this version is coded in-line with
the existing TCP code.
Testing done on a 4 socket 2.2GHz "Quad-Core AMD Opteron(tm) Processor
8354 CPU" based system, netperf results for a single connection show
increased TCP_STREAM throughput, increased TCP_RR and TCP_CRR transaction
rate for most message sizes vs baseline and comparable to AF_UNIX.
Significant increase (up to 5x) in aggregate throughput for multiple
netperf runs (STREAM 32KB I/O x N) is seen.
Some results:
Default netperf: netperf
netperf -t STREAM_STREAM
netperf -t STREAM_STREAM -- -s 51882 -m 16384 -M 87380
netperf
Baseline AF_UNIX AF_UNIX Friends
Mbits/S Mbits/S Mbits/S Mbits/S
6860 714 8% 9444 138% 1323% 10576 154% 1481% 112%
Note, for the AF_UNIX (STREAM_STREAM) test 2 results are listed, 1st
with no options but as the defaults for AF_UNIX sockets are much lower
performaning a 2nd set of runs with a socket buffer size and send/recv
buffer sizes equivalent to AF_INET (TCP_STREAM) are done.
Note, all subsequent AF_UNIX (STREAM_STREAM, STREAM_RR) tests are done
with "-s 51882" such that the same total effective socket buffering is
used as for the AF_INET runs defaults (16384+NNNNN/2).
STREAM 32KB I/O x N: netperf -l 100 -t TCP_STREAM -- -m 32K -M 32K
netperf -l 100 -t STREAM_STREAM -- -s 51882 -m 32K -M 32K
netperf -l 100 -t TCP_STREAM -- -m 32K -M 32K
Baseline AF_UNIX Friends
N COC Mbits/S Mbits/S Mbits/S
1 - 8616 9416 109% 11116 129% 118%
2 - 15419 17076 111% 20267 131% 119%
16 2 59497 303029 509% 347349 584% 115%
32 4 54223 273637 505% 272891 503% 100%
256 32 58244 85476 147% 273696 470% 320%
512 64 58745 87402 149% 260837 444% 298%
1600 200 83161 158915 191% 383947 462% 242%
COC = Cpu Over Commit ratio (16 core platform)
STREAM: netperf -l 100 -t TCP_STREAM
netperf -l 100 -t STREAM_STREAM -- -s 51882
netperf -l 100 -t TCP_STREAM
netperf Baseline AF_UNIX Friends
-m/-M N Mbits/S Mbits/S Mbits/S
64 1020 445 44% 515 50% 116%
1K 4881 4340 89% 5070 104% 117%
8K 5933 8387 141% 9770 165% 116%
32K 8168 9538 117% 11067 135% 116%
64K 9116 9774 107% 11515 126% 118%
128K 9053 10044 111% 13082 145% 130%
256K 9642 10351 107% 13470 140% 130%
512K 10050 10142 101% 13327 133% 131%
1M 8640 9843 114% 12201 141% 124%
16M 7179 9619 134% 11316 158% 118%
RR: netperf -l 100 -t TCP_RR
netperf -l 100 -t STREAM_RR -- -s 51882 -m 16384 -M 87380
netperf -l 100 -t TCP_RR
netperf Baseline AF_UNIX Friends
-r N,N Trans./S Trans./S Trans./S
64 47913 99681 208% 98225 205% 99%
1K 44045 92327 210% 91608 208% 99%
8K 26732 33201 124% 33025 124% 99%
32K 10903 11972 110% 13574 124% 113%
64K 7113 6718 94% 7176 101% 107%
128K 4191 3431 82% 3695 88% 108%
256K 2324 1937 83% 2147 92% 111%
512K 958 1056 110% 1202 125% 114%
1M 404 508 126% 497 123% 98%
16M 26.1 34.1 131% 32.9 126% 96%
CRR: netperf -l 100 -t TCP_CRR
netperf -l 100 -t TCP_CRR
netperf Baseline AF_UNIX Friends
-r N Trans./S Trans./S Trans./S
64 14690 - 18191 124% -
1K 14258 - 17492 123% -
8K 11535 - 14012 121% -
32K 7035 - 8974 128% -
64K 4312 - 5654 131% -
128K 2252 - 3179 141% -
256K 1237 - 2008 162% -
512K 17.5* - 1079 ? -
1M 4.93* - 458 ? -
16M 8.29* - 32.5 ? -
Note, "-" denotes test not supported for transport.
"*" denotes test results reported without statistical confidence.
"?" denotes results not comparable.
SPLICE 32KB I/O:
Source
Sink Baseline Friends
FSFS Mbits/S Mbits/S
---- 8042 10810 134%
Z--- 7071 9773 138%
--N- 8039 10820 135%
Z-N- 7902 9796 124%
-S-- 17326 37496 216%
ZS-- 9008 9573 106%
-SN- 16154 36269 225%
ZSN- 9531 9640 101%
---S 8466 9933 117%
Z--S 8000 9453 118%
--NS 12783 11379 89%
Z-NS 11055 9489 86%
-S-S 12741 24380 191%
ZS-S 8097 10242 126%
-SNS 16657 30954 186%
ZSNS 12108 12763 105%
Note, "Z" source File /dev/zero, "-" source user memory
"N" sink File /dev/null, "-" sink user memory
"S" Splice on, "-" Splice off
Signed-off-by: Bruce \"Brutus\" Curtis <brutus@google.com>
---
include/linux/skbuff.h | 2 +
include/net/request_sock.h | 1 +
include/net/sock.h | 32 +++-
include/net/tcp.h | 3 +-
net/core/skbuff.c | 1 +
net/core/stream.c | 36 +++
net/ipv4/inet_connection_sock.c | 21 ++
net/ipv4/sysctl_net_ipv4.c | 7 +
net/ipv4/tcp.c | 500 ++++++++++++++++++++++++++++++++++-----
net/ipv4/tcp_input.c | 24 ++-
net/ipv4/tcp_ipv4.c | 2 +
net/ipv4/tcp_minisocks.c | 5 +
net/ipv4/tcp_output.c | 18 ++-
net/ipv6/tcp_ipv6.c | 1 +
14 files changed, 578 insertions(+), 75 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 642cb73..2fbca93 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -332,6 +332,7 @@ typedef unsigned char *sk_buff_data_t;
* @cb: Control buffer. Free for use by every layer. Put private vars here
* @_skb_refdst: destination entry (with norefcount bit)
* @sp: the security path, used for xfrm
+ * @friend: loopback friend socket
* @len: Length of actual data
* @data_len: Data length
* @mac_len: Length of link layer header
@@ -407,6 +408,7 @@ struct sk_buff {
#ifdef CONFIG_XFRM
struct sec_path *sp;
#endif
+ struct sock *friend;
unsigned int len,
data_len;
__u16 mac_len,
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index 4c0766e..2c74420 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -63,6 +63,7 @@ struct request_sock {
unsigned long expires;
const struct request_sock_ops *rsk_ops;
struct sock *sk;
+ struct sock *friend;
u32 secid;
u32 peer_secid;
};
diff --git a/include/net/sock.h b/include/net/sock.h
index dcb54a0..3b371f5 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -197,6 +197,7 @@ struct cg_proto;
* @sk_userlocks: %SO_SNDBUF and %SO_RCVBUF settings
* @sk_lock: synchronizer
* @sk_rcvbuf: size of receive buffer in bytes
+ * @sk_friend: loopback friend socket
* @sk_wq: sock wait queue and async head
* @sk_rx_dst: receive input route used by early tcp demux
* @sk_dst_cache: destination cache
@@ -286,6 +287,14 @@ struct sock {
socket_lock_t sk_lock;
struct sk_buff_head sk_receive_queue;
/*
+ * If socket has a friend (sk_friend != NULL) then a send skb is
+ * enqueued directly to the friend's sk_receive_queue such that:
+ *
+ * sk_sndbuf -> sk_sndbuf + sk_friend->sk_rcvbuf
+ * sk_wmem_queued -> sk_friend->sk_rmem_alloc
+ */
+ struct sock *sk_friend;
+ /*
* The backlog queue is special, it is always used with
* the per-socket spinlock held and requires low latency
* access. Therefore we special case it's implementation.
@@ -673,24 +682,40 @@ static inline bool sk_acceptq_is_full(const struct sock *sk)
return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}
+static inline int sk_wmem_queued_get(const struct sock *sk)
+{
+ if (sk->sk_friend)
+ return atomic_read(&sk->sk_friend->sk_rmem_alloc);
+ else
+ return sk->sk_wmem_queued;
+}
+
+static inline int sk_sndbuf_get(const struct sock *sk)
+{
+ if (sk->sk_friend)
+ return sk->sk_sndbuf + sk->sk_friend->sk_rcvbuf;
+ else
+ return sk->sk_sndbuf;
+}
+
/*
* Compute minimal free write space needed to queue new packets.
*/
static inline int sk_stream_min_wspace(const struct sock *sk)
{
- return sk->sk_wmem_queued >> 1;
+ return sk_wmem_queued_get(sk) >> 1;
}
static inline int sk_stream_wspace(const struct sock *sk)
{
- return sk->sk_sndbuf - sk->sk_wmem_queued;
+ return sk_sndbuf_get(sk) - sk_wmem_queued_get(sk);
}
extern void sk_stream_write_space(struct sock *sk);
static inline bool sk_stream_memory_free(const struct sock *sk)
{
- return sk->sk_wmem_queued < sk->sk_sndbuf;
+ return sk_wmem_queued_get(sk) < sk_sndbuf_get(sk);
}
/* OOB backlog add */
@@ -794,6 +819,7 @@ static inline void sock_rps_reset_rxhash(struct sock *sk)
})
extern int sk_stream_wait_connect(struct sock *sk, long *timeo_p);
+extern int sk_stream_wait_friend(struct sock *sk, long *timeo_p);
extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p);
extern void sk_stream_wait_close(struct sock *sk, long timeo_p);
extern int sk_stream_error(struct sock *sk, int flags, int err);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 53fb7d8..011ba42 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -253,6 +253,7 @@ extern int sysctl_tcp_cookie_size;
extern int sysctl_tcp_thin_linear_timeouts;
extern int sysctl_tcp_thin_dupack;
extern int sysctl_tcp_early_retrans;
+extern int sysctl_tcp_friends;
extern atomic_long_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
@@ -978,7 +979,7 @@ static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
{
struct tcp_sock *tp = tcp_sk(sk);
- if (sysctl_tcp_low_latency || !tp->ucopy.task)
+ if (sysctl_tcp_low_latency || !tp->ucopy.task || sk->sk_friend)
return false;
__skb_queue_tail(&tp->ucopy.prequeue, skb);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 5a789a8..5702145 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -634,6 +634,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
#ifdef CONFIG_XFRM
new->sp = secpath_get(old->sp);
#endif
+ new->friend = old->friend;
memcpy(new->cb, old->cb, sizeof(old->cb));
new->csum = old->csum;
new->local_df = old->local_df;
diff --git a/net/core/stream.c b/net/core/stream.c
index f5df85d..85e5b03 100644
--- a/net/core/stream.c
+++ b/net/core/stream.c
@@ -83,6 +83,42 @@ int sk_stream_wait_connect(struct sock *sk, long *timeo_p)
EXPORT_SYMBOL(sk_stream_wait_connect);
/**
+ * sk_stream_wait_friend - Wait for a socket to make friends
+ * @sk: sock to wait on
+ * @timeo_p: for how long to wait
+ *
+ * Must be called with the socket locked.
+ */
+int sk_stream_wait_friend(struct sock *sk, long *timeo_p)
+{
+ struct task_struct *tsk = current;
+ DEFINE_WAIT(wait);
+ int done;
+
+ do {
+ int err = sock_error(sk);
+ if (err)
+ return err;
+ if (!sk->sk_friend)
+ return -EBADFD;
+ if (!*timeo_p)
+ return -EAGAIN;
+ if (signal_pending(tsk))
+ return sock_intr_errno(*timeo_p);
+
+ prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
+ sk->sk_write_pending++;
+ done = sk_wait_event(sk, timeo_p,
+ !sk->sk_err &&
+ sk->sk_friend->sk_friend);
+ finish_wait(sk_sleep(sk), &wait);
+ sk->sk_write_pending--;
+ } while (!done);
+ return 0;
+}
+EXPORT_SYMBOL(sk_stream_wait_friend);
+
+/**
* sk_stream_closing - Return 1 if we still have things to send in our buffers.
* @sk: socket to verify
*/
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 034ddbe..d5589e3 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -626,6 +626,27 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
if (newsk != NULL) {
struct inet_connection_sock *newicsk = inet_csk(newsk);
+ if (req->friend) {
+ /*
+ * Make friends with the requestor but the ACK of
+ * the request is already in-flight so the race is
+ * on to make friends before the ACK is processed.
+ * If the requestor's sk_friend value is != NULL
+ * then the requestor has already processed the
+ * ACK so indicate state change to wake'm up.
+ */
+ u64 was;
+
+ sock_hold(req->friend);
+ newsk->sk_friend = req->friend;
+ sock_hold(newsk);
+ was = atomic_long_xchg(&req->friend->sk_friend,
+ (u64)newsk);
+ /* If requester already connect()ed, maybe sleeping */
+ if (was && !sock_flag(req->friend, SOCK_DEAD))
+ sk->sk_state_change(req->friend);
+ }
+
newsk->sk_state = TCP_SYN_RECV;
newicsk->icsk_bind_hash = NULL;
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 12aa0c5..3fc3d50 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -716,6 +716,13 @@ static struct ctl_table ipv4_table[] = {
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero
},
+ {
+ .procname = "tcp_friends",
+ .data = &sysctl_tcp_friends,
+ .maxlen = sizeof(int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec
+ },
{ }
};
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 3ba605f..a87f0f5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -309,6 +309,38 @@ struct tcp_splice_state {
};
/*
+ * Friends? If not a friend return 0, else if friend is also a friend
+ * return 1, else wait for friend to be ready and return 1 if friends
+ * else -errno. In all cases if *friendp != NULL return friend pointer
+ * else NULL.
+ */
+static inline int tcp_friends(struct sock *sk, struct sock **friendp,
+ long *timeo)
+{
+ struct sock *friend = sk->sk_friend;
+ int ret = 0;
+
+ if (!friend)
+ goto out;
+ if (unlikely(!friend->sk_friend)) {
+ /* Friendship not complete, wait? */
+ if (!timeo) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ ret = sk_stream_wait_friend(sk, timeo);
+ if (ret != 0)
+ goto out;
+ friend = sk->sk_friend;
+ }
+ ret = 1;
+out:
+ if (friendp)
+ *friendp = friend;
+ return ret;
+}
+
+/*
* Pressure flag: try to collapse.
* Technical note: it is used by multiple contexts non atomically.
* All the __sk_mem_schedule() is of this nature: accounting
@@ -587,6 +619,73 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
}
EXPORT_SYMBOL(tcp_ioctl);
+static inline struct sk_buff *tcp_friend_tail(struct sock *sk, int *copy)
+{
+ struct sock *friend = sk->sk_friend;
+ struct sk_buff *skb = NULL;
+ int sz = 0;
+
+ if (skb_peek_tail(&friend->sk_receive_queue)) {
+ spin_lock_bh(&friend->sk_lock.slock);
+ skb = skb_peek_tail(&friend->sk_receive_queue);
+ if (skb && skb->friend) {
+ if (!*copy)
+ sz = skb_tailroom(skb);
+ else
+ sz = *copy - skb->len;
+ }
+ if (!skb || sz <= 0)
+ spin_unlock_bh(&friend->sk_lock.slock);
+ }
+
+ *copy = sz;
+ return skb;
+}
+
+static inline void tcp_friend_seq(struct sock *sk, int copy, int charge)
+{
+ struct sock *friend = sk->sk_friend;
+ struct tcp_sock *tp = tcp_sk(friend);
+
+ if (charge) {
+ sk_mem_charge(friend, charge);
+ atomic_add(charge, &friend->sk_rmem_alloc);
+ }
+ tp->rcv_nxt += copy;
+ tp->rcv_wup += copy;
+ spin_unlock_bh(&friend->sk_lock.slock);
+
+ friend->sk_data_ready(friend, copy);
+
+ tp = tcp_sk(sk);
+ tp->snd_nxt += copy;
+ tp->pushed_seq += copy;
+ tp->snd_una += copy;
+ tp->snd_up += copy;
+}
+
+static inline int tcp_friend_push(struct sock *sk, struct sk_buff *skb)
+{
+ struct sock *friend = sk->sk_friend;
+ int ret = 0;
+
+ if (friend->sk_shutdown & RCV_SHUTDOWN) {
+ __kfree_skb(skb);
+ return -ECONNRESET;
+ }
+
+ spin_lock_bh(&friend->sk_lock.slock);
+ skb->friend = sk;
+ skb_set_owner_r(skb, friend);
+ __skb_queue_tail(&friend->sk_receive_queue, skb);
+ if (!sk_rmem_schedule(friend, skb->truesize))
+ ret = 1;
+
+ tcp_friend_seq(sk, skb->len, 0);
+
+ return ret;
+}
+
static inline void tcp_mark_push(struct tcp_sock *tp, struct sk_buff *skb)
{
TCP_SKB_CB(skb)->tcp_flags |= TCPHDR_PSH;
@@ -603,8 +702,12 @@ static inline void skb_entail(struct sock *sk, struct sk_buff *skb)
struct tcp_sock *tp = tcp_sk(sk);
struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
- skb->csum = 0;
tcb->seq = tcb->end_seq = tp->write_seq;
+ if (sk->sk_friend) {
+ skb->friend = sk->sk_friend;
+ return;
+ }
+ skb->csum = 0;
tcb->tcp_flags = TCPHDR_ACK;
tcb->sacked = 0;
skb_header_release(skb);
@@ -756,6 +859,21 @@ ssize_t tcp_splice_read(struct socket *sock, loff_t *ppos,
}
EXPORT_SYMBOL(tcp_splice_read);
+static inline struct sk_buff *tcp_friend_alloc_skb(struct sock *sk, int size)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(size, sk->sk_allocation);
+ if (skb)
+ skb->avail_size = skb_tailroom(skb);
+ else {
+ sk->sk_prot->enter_memory_pressure(sk);
+ sk_stream_moderate_sndbuf(sk);
+ }
+
+ return skb;
+}
+
struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
{
struct sk_buff *skb;
@@ -813,13 +931,47 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now,
return max(xmit_size_goal, mss_now);
}
+static unsigned int tcp_friend_xmit_size_goal(struct sock *sk, int size_goal)
+{
+ u32 tmp = SKB_TRUESIZE(size_goal);
+
+ /*
+ * If goal is zero (for non linear) or truesize of goal >= largest
+ * skb return largest, else for tail fill find smallest order that
+ * fits 8 or more truesized, else use requested truesize.
+ */
+ if (size_goal == 0 || tmp >= SKB_MAX_ORDER(0, 3))
+ tmp = SKB_MAX_ORDER(0, 3);
+ else if (tmp <= (SKB_MAX_ORDER(0, 0) >> 3))
+ tmp = SKB_MAX_ORDER(0, 0);
+ else if (tmp <= (SKB_MAX_ORDER(0, 1) >> 3))
+ tmp = SKB_MAX_ORDER(0, 1);
+ else if (tmp <= (SKB_MAX_ORDER(0, 2) >> 3))
+ tmp = SKB_MAX_ORDER(0, 2);
+ else if (tmp <= (SKB_MAX_ORDER(0, 3) >> 3))
+ tmp = SKB_MAX_ORDER(0, 3);
+
+ /* At least 2 truesized in sk_buf */
+ if (tmp > (sk_sndbuf_get(sk) >> 1))
+ tmp = (sk_sndbuf_get(sk) >> 1) - SKB_TRUESIZE(0);
+
+ return tmp;
+}
+
static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
{
int mss_now;
+ int tmp;
- mss_now = tcp_current_mss(sk);
- *size_goal = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB));
+ if (sk->sk_friend) {
+ mss_now = tcp_friend_xmit_size_goal(sk, *size_goal);
+ tmp = mss_now;
+ } else {
+ mss_now = tcp_current_mss(sk);
+ tmp = tcp_xmit_size_goal(sk, mss_now, !(flags & MSG_OOB));
+ }
+ *size_goal = tmp;
return mss_now;
}
@@ -830,6 +982,8 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
int mss_now, size_goal;
int err;
ssize_t copied;
+ struct sock *friend;
+ bool friend_tail = false;
long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
/* Wait for a connection to finish. */
@@ -837,6 +991,10 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
goto out_err;
+ err = tcp_friends(sk, &friend, &timeo);
+ if (err < 0)
+ goto out_err;
+
clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags);
mss_now = tcp_send_mss(sk, &size_goal, flags);
@@ -847,19 +1005,40 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse
goto out_err;
while (psize > 0) {
- struct sk_buff *skb = tcp_write_queue_tail(sk);
+ struct sk_buff *skb;
struct page *page = pages[poffset / PAGE_SIZE];
int copy, i;
int offset = poffset % PAGE_SIZE;
int size = min_t(size_t, psize, PAGE_SIZE - offset);
bool can_coalesce;
- if (!tcp_send_head(sk) || (copy = size_goal - skb->len) <= 0) {
+ if (sk->sk_friend) {
+ if (sk->sk_friend->sk_shutdown & RCV_SHUTDOWN) {
+ sk->sk_err = ECONNRESET;
+ err = -EPIPE;
+ goto out_err;
+ }
+ copy = size_goal;
+ skb = tcp_friend_tail(sk, ©);
+ if (copy > 0)
+ friend_tail = true;
+ } else if (!tcp_send_head(sk)) {
+ copy = 0;
+ } else {
+ skb = tcp_write_queue_tail(sk);
+ copy = size_goal - skb->len;
+ }
+
+ if (copy <= 0) {
new_segment:
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
- skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation);
+ if (sk->sk_friend)
+ skb = tcp_friend_alloc_skb(sk, 0);
+ else
+ skb = sk_stream_alloc_skb(sk, 0,
+ sk->sk_allocation);
if (!skb)
goto wait_for_memory;
@@ -873,10 +1052,16 @@ new_segment:
i = skb_shinfo(skb)->nr_frags;
can_coalesce = skb_can_coalesce(skb, i, page, offset);
if (!can_coalesce && i >= MAX_SKB_FRAGS) {
- tcp_mark_push(tp, skb);
+ if (friend) {
+ if (friend_tail) {
+ tcp_friend_seq(sk, 0, 0);
+ friend_tail = false;
+ }
+ } else
+ tcp_mark_push(tp, skb);
goto new_segment;
}
- if (!sk_wmem_schedule(sk, copy))
+ if (!friend && !sk_wmem_schedule(sk, copy))
goto wait_for_memory;
if (can_coalesce) {
@@ -889,19 +1074,40 @@ new_segment:
skb->len += copy;
skb->data_len += copy;
skb->truesize += copy;
- sk->sk_wmem_queued += copy;
- sk_mem_charge(sk, copy);
- skb->ip_summed = CHECKSUM_PARTIAL;
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
skb_shinfo(skb)->gso_segs = 0;
- if (!copied)
- TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
-
copied += copy;
poffset += copy;
- if (!(psize -= copy))
+ psize -= copy;
+
+ if (friend) {
+ if (friend_tail) {
+ tcp_friend_seq(sk, copy, copy);
+ friend_tail = false;
+ } else {
+ err = tcp_friend_push(sk, skb);
+ if (err < 0) {
+ sk->sk_err = -err;
+ goto out_err;
+ }
+ if (err > 0)
+ goto wait_for_sndbuf;
+ }
+ if (!psize)
+ goto out;
+ continue;
+ }
+
+ sk->sk_wmem_queued += copy;
+ sk_mem_charge(sk, copy);
+ skb->ip_summed = CHECKSUM_PARTIAL;
+
+ if (copied == copy)
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
+
+ if (!psize)
goto out;
if (skb->len < size_goal || (flags & MSG_OOB))
@@ -922,6 +1128,7 @@ wait_for_memory:
if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
goto do_error;
+ size_goal = -mss_now;
mss_now = tcp_send_mss(sk, &size_goal, flags);
}
@@ -984,8 +1191,9 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
int iovlen, flags, err, copied;
- int mss_now = 0, size_goal;
- bool sg;
+ int mss_now = 0, size_goal = size;
+ struct sock *friend;
+ bool sg, friend_tail = false;
long timeo;
lock_sock(sk);
@@ -998,6 +1206,10 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if ((err = sk_stream_wait_connect(sk, &timeo)) != 0)
goto out_err;
+ err = tcp_friends(sk, &friend, &timeo);
+ if (err < 0)
+ goto out_err;
+
if (unlikely(tp->repair)) {
if (tp->repair_queue == TCP_RECV_QUEUE) {
copied = tcp_send_rcvq(sk, msg, size);
@@ -1037,24 +1249,40 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
int copy = 0;
int max = size_goal;
- skb = tcp_write_queue_tail(sk);
- if (tcp_send_head(sk)) {
- if (skb->ip_summed == CHECKSUM_NONE)
- max = mss_now;
- copy = max - skb->len;
+ if (friend) {
+ if (friend->sk_shutdown & RCV_SHUTDOWN) {
+ sk->sk_err = ECONNRESET;
+ err = -EPIPE;
+ goto out_err;
+ }
+ skb = tcp_friend_tail(sk, ©);
+ if (copy)
+ friend_tail = true;
+ } else {
+ skb = tcp_write_queue_tail(sk);
+ if (tcp_send_head(sk)) {
+ if (skb->ip_summed == CHECKSUM_NONE)
+ max = mss_now;
+ copy = max - skb->len;
+ }
}
if (copy <= 0) {
new_segment:
- /* Allocate new segment. If the interface is SG,
- * allocate skb fitting to single page.
- */
if (!sk_stream_memory_free(sk))
goto wait_for_sndbuf;
- skb = sk_stream_alloc_skb(sk,
- select_size(sk, sg),
- sk->sk_allocation);
+ if (friend)
+ skb = tcp_friend_alloc_skb(sk, max);
+ else {
+ /* Allocate new segment. If the
+ * interface is SG, allocate skb
+ * fitting to single page.
+ */
+ skb = sk_stream_alloc_skb(sk,
+ select_size(sk, sg),
+ sk->sk_allocation);
+ }
if (!skb)
goto wait_for_memory;
@@ -1086,6 +1314,8 @@ new_segment:
struct page *page = sk->sk_sndmsg_page;
int off;
+ BUG_ON(friend);
+
if (page && page_count(page) == 1)
sk->sk_sndmsg_off = 0;
@@ -1155,16 +1385,34 @@ new_segment:
sk->sk_sndmsg_off = off + copy;
}
- if (!copied)
- TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
-
tp->write_seq += copy;
TCP_SKB_CB(skb)->end_seq += copy;
skb_shinfo(skb)->gso_segs = 0;
from += copy;
copied += copy;
- if ((seglen -= copy) == 0 && iovlen == 0)
+ seglen -= copy;
+
+ if (friend) {
+ if (friend_tail) {
+ tcp_friend_seq(sk, copy, 0);
+ friend_tail = false;
+ } else {
+ err = tcp_friend_push(sk, skb);
+ if (err < 0) {
+ sk->sk_err = -err;
+ goto out_err;
+ }
+ if (err > 0)
+ goto wait_for_sndbuf;
+ }
+ continue;
+ }
+
+ if (copied == copy)
+ TCP_SKB_CB(skb)->tcp_flags &= ~TCPHDR_PSH;
+
+ if (seglen == 0 && iovlen == 0)
goto out;
if (skb->len < max || (flags & MSG_OOB) || unlikely(tp->repair))
@@ -1186,6 +1434,7 @@ wait_for_memory:
if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
goto do_error;
+ size_goal = -mss_now;
mss_now = tcp_send_mss(sk, &size_goal, flags);
}
}
@@ -1197,13 +1446,19 @@ out:
return copied;
do_fault:
- if (!skb->len) {
- tcp_unlink_write_queue(skb, sk);
- /* It is the one place in all of TCP, except connection
- * reset, where we can be unlinking the send_head.
- */
- tcp_check_send_head(sk, skb);
- sk_wmem_free_skb(sk, skb);
+ if (friend_tail)
+ spin_unlock_bh(&friend->sk_lock.slock);
+ else if (!skb->len) {
+ if (friend) {
+ __kfree_skb(skb);
+ } else {
+ tcp_unlink_write_queue(skb, sk);
+ /* It is the one place in all of TCP, except connection
+ * reset, where we can be unlinking the send_head.
+ */
+ tcp_check_send_head(sk, skb);
+ sk_wmem_free_skb(sk, skb);
+ }
}
do_error:
@@ -1216,6 +1471,13 @@ out_err:
}
EXPORT_SYMBOL(tcp_sendmsg);
+static inline void tcp_friend_write_space(struct sock *sk)
+{
+ /* Queued data below 1/4th of sndbuf? */
+ if ((sk_sndbuf_get(sk) >> 2) > sk_wmem_queued_get(sk))
+ sk->sk_friend->sk_write_space(sk->sk_friend);
+}
+
/*
* Handle reading urgent data. BSD has very simple semantics for
* this, no blocking and very strange errors 8)
@@ -1294,7 +1556,12 @@ void tcp_cleanup_rbuf(struct sock *sk, int copied)
struct tcp_sock *tp = tcp_sk(sk);
bool time_to_ack = false;
- struct sk_buff *skb = skb_peek(&sk->sk_receive_queue);
+ struct sk_buff *skb;
+
+ if (sk->sk_friend)
+ return;
+
+ skb = skb_peek(&sk->sk_receive_queue);
WARN(skb && !before(tp->copied_seq, TCP_SKB_CB(skb)->end_seq),
"cleanup rbuf bug: copied %X seq %X rcvnxt %X\n",
@@ -1405,9 +1672,9 @@ static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
skb_queue_walk(&sk->sk_receive_queue, skb) {
offset = seq - TCP_SKB_CB(skb)->seq;
- if (tcp_hdr(skb)->syn)
+ if (!skb->friend && tcp_hdr(skb)->syn)
offset--;
- if (offset < skb->len || tcp_hdr(skb)->fin) {
+ if (offset < skb->len || (!skb->friend && tcp_hdr(skb)->fin)) {
*off = offset;
return skb;
}
@@ -1434,14 +1701,27 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
u32 seq = tp->copied_seq;
u32 offset;
int copied = 0;
+ struct sock *friend = sk->sk_friend;
if (sk->sk_state == TCP_LISTEN)
return -ENOTCONN;
+
+ if (friend) {
+ int err;
+ long timeo = sock_rcvtimeo(sk, false);
+
+ err = tcp_friends(sk, &friend, &timeo);
+ if (err < 0)
+ return err;
+ spin_lock_bh(&sk->sk_lock.slock);
+ }
+
while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) {
if (offset < skb->len) {
int used;
size_t len;
+ again:
len = skb->len - offset;
/* Stop reading if we hit a patch of urgent data */
if (tp->urg_data) {
@@ -1451,7 +1731,13 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
if (!len)
break;
}
+ if (sk->sk_friend)
+ spin_unlock_bh(&sk->sk_lock.slock);
+
used = recv_actor(desc, skb, offset, len);
+
+ if (sk->sk_friend)
+ spin_lock_bh(&sk->sk_lock.slock);
if (used < 0) {
if (!copied)
copied = used;
@@ -1461,17 +1747,31 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
copied += used;
offset += used;
}
- /*
- * If recv_actor drops the lock (e.g. TCP splice
- * receive) the skb pointer might be invalid when
- * getting here: tcp_collapse might have deleted it
- * while aggregating skbs from the socket queue.
- */
- skb = tcp_recv_skb(sk, seq-1, &offset);
- if (!skb || (offset+1 != skb->len))
- break;
+ if (skb->friend) {
+ if (offset < skb->len) {
+ /*
+ * Friend did an skb_put() while we
+ * were away so process the same skb.
+ */
+ tp->copied_seq = seq;
+ if (!desc->count)
+ break;
+ goto again;
+ }
+ } else {
+ /*
+ * If recv_actor drops the lock (e.g. TCP
+ * splice receive) the skb pointer might be
+ * invalid when getting here: tcp_collapse
+ * might have deleted it while aggregating
+ * skbs from the socket queue.
+ */
+ skb = tcp_recv_skb(sk, seq-1, &offset);
+ if (!skb || (offset+1 != skb->len))
+ break;
+ }
}
- if (tcp_hdr(skb)->fin) {
+ if (!skb->friend && tcp_hdr(skb)->fin) {
sk_eat_skb(sk, skb, false);
++seq;
break;
@@ -1483,11 +1783,16 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
}
tp->copied_seq = seq;
- tcp_rcv_space_adjust(sk);
+ if (sk->sk_friend) {
+ spin_unlock_bh(&sk->sk_lock.slock);
+ tcp_friend_write_space(sk);
+ } else {
+ tcp_rcv_space_adjust(sk);
- /* Clean up data we have read: This will do ACK frames. */
- if (copied > 0)
- tcp_cleanup_rbuf(sk, copied);
+ /* Clean up data we have read: This will do ACK frames. */
+ if (copied > 0)
+ tcp_cleanup_rbuf(sk, copied);
+ }
return copied;
}
EXPORT_SYMBOL(tcp_read_sock);
@@ -1515,6 +1820,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
bool copied_early = false;
struct sk_buff *skb;
u32 urg_hole = 0;
+ int skb_len;
+ struct sock *friend;
+ bool locked = false;
lock_sock(sk);
@@ -1524,6 +1832,10 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
timeo = sock_rcvtimeo(sk, nonblock);
+ err = tcp_friends(sk, &friend, &timeo);
+ if (err < 0)
+ goto out;
+
/* Urgent data needs to be handled specially. */
if (flags & MSG_OOB)
goto recv_urg;
@@ -1562,7 +1874,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
available = TCP_SKB_CB(skb)->seq + skb->len - (*seq);
if ((available < target) &&
(len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
- !sysctl_tcp_low_latency &&
+ !sysctl_tcp_low_latency && !friends &&
net_dma_find_channel()) {
preempt_enable_no_resched();
tp->ucopy.pinned_list =
@@ -1586,9 +1898,30 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
}
- /* Next get a buffer. */
+ /*
+ * Next get a buffer. Note, for socket friends a sk_friend
+ * sendmsg() can either skb_queue_tail() a new skb directly
+ * or skb_put() to the tail skb while holding sk_lock.slock.
+ */
+ if (friend && !locked) {
+ spin_lock_bh(&sk->sk_lock.slock);
+ locked = true;
+ }
skb_queue_walk(&sk->sk_receive_queue, skb) {
+ offset = *seq - TCP_SKB_CB(skb)->seq;
+ skb_len = skb->len;
+ if (friend) {
+ spin_unlock_bh(&sk->sk_lock.slock);
+ locked = false;
+ if (skb->friend) {
+ if (offset < skb_len)
+ goto found_ok_skb;
+ BUG_ON(!(flags & MSG_PEEK));
+ break;
+ }
+ }
+
/* Now that we have two receive queues this
* shouldn't happen.
*/
@@ -1598,10 +1931,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
flags))
break;
- offset = *seq - TCP_SKB_CB(skb)->seq;
if (tcp_hdr(skb)->syn)
offset--;
- if (offset < skb->len)
+ if (offset < skb_len)
goto found_ok_skb;
if (tcp_hdr(skb)->fin)
goto found_fin_ok;
@@ -1612,6 +1944,11 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
/* Well, if we have backlog, try to process it now yet. */
+ if (friend && locked) {
+ spin_unlock_bh(&sk->sk_lock.slock);
+ locked = false;
+ }
+
if (copied >= target && !sk->sk_backlog.tail)
break;
@@ -1658,7 +1995,8 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
tcp_cleanup_rbuf(sk, copied);
- if (!sysctl_tcp_low_latency && tp->ucopy.task == user_recv) {
+ if (!sysctl_tcp_low_latency && !friend &&
+ tp->ucopy.task == user_recv) {
/* Install new reader */
if (!user_recv && !(flags & (MSG_TRUNC | MSG_PEEK))) {
user_recv = current;
@@ -1753,7 +2091,7 @@ do_prequeue:
found_ok_skb:
/* Ok so how much can we use? */
- used = skb->len - offset;
+ used = skb_len - offset;
if (len < used)
used = len;
@@ -1799,7 +2137,7 @@ do_prequeue:
dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
- if ((offset + used) == skb->len)
+ if ((offset + used) == skb_len)
copied_early = true;
} else
@@ -1819,6 +2157,7 @@ do_prequeue:
*seq += used;
copied += used;
len -= used;
+ offset += used;
tcp_rcv_space_adjust(sk);
@@ -1827,11 +2166,36 @@ skip_copy:
tp->urg_data = 0;
tcp_fast_path_check(sk);
}
- if (used + offset < skb->len)
+
+ if (friend) {
+ spin_lock_bh(&sk->sk_lock.slock);
+ locked = true;
+ skb_len = skb->len;
+ if (offset < skb_len) {
+ if (skb->friend && len > 0) {
+ /*
+ * Friend did an skb_put() while we
+ * were away so process the same skb.
+ */
+ spin_unlock_bh(&sk->sk_lock.slock);
+ locked = false;
+ goto found_ok_skb;
+ }
+ continue;
+ }
+ if (!(flags & MSG_PEEK)) {
+ __skb_unlink(skb, &sk->sk_receive_queue);
+ __kfree_skb(skb);
+ tcp_friend_write_space(sk);
+ }
continue;
+ }
- if (tcp_hdr(skb)->fin)
+ if (offset < skb_len)
+ continue;
+ else if (tcp_hdr(skb)->fin)
goto found_fin_ok;
+
if (!(flags & MSG_PEEK)) {
sk_eat_skb(sk, skb, copied_early);
copied_early = false;
@@ -1848,6 +2212,9 @@ skip_copy:
break;
} while (len > 0);
+ if (friend && locked)
+ spin_unlock_bh(&sk->sk_lock.slock);
+
if (user_recv) {
if (!skb_queue_empty(&tp->ucopy.prequeue)) {
int chunk;
@@ -2026,6 +2393,9 @@ void tcp_close(struct sock *sk, long timeout)
goto adjudge_to_death;
}
+ if (sk->sk_friend)
+ sock_put(sk->sk_friend);
+
/* We need to flush the recv. buffs. We do this only on the
* descriptor close, not protocol-sourced closes, because the
* reader process may not have drained the data yet!
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index ca0d0e7..52ac297 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -524,6 +524,9 @@ void tcp_rcv_space_adjust(struct sock *sk)
int time;
int space;
+ if (sk->sk_friend)
+ return;
+
if (tp->rcvq_space.time == 0)
goto new_measure;
@@ -4516,8 +4519,9 @@ static int tcp_prune_queue(struct sock *sk);
static int tcp_try_rmem_schedule(struct sock *sk, unsigned int size)
{
- if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
- !sk_rmem_schedule(sk, size)) {
+ if (!sk->sk_friend &&
+ (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf ||
+ !sk_rmem_schedule(sk, size))) {
if (tcp_prune_queue(sk) < 0)
return -1;
@@ -5839,6 +5843,18 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
* state to ESTABLISHED..."
*/
+ if (skb->friend) {
+ /*
+ * If friends haven't been made yet, our sk_friend
+ * still == NULL, then update with the ACK's friend
+ * value (the listen()er's sock addr) which is used
+ * as a place holder.
+ */
+ atomic_long_cmpxchg(&sk->sk_friend, 0,
+ (u64)skb->friend);
+ } else
+ sk->sk_friend = NULL;
+
TCP_ECN_rcv_synack(tp, th);
tp->snd_wl1 = TCP_SKB_CB(skb)->seq;
@@ -5911,9 +5927,9 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb,
tcp_finish_connect(sk, skb);
- if (sk->sk_write_pending ||
+ if (!skb->friend && (sk->sk_write_pending ||
icsk->icsk_accept_queue.rskq_defer_accept ||
- icsk->icsk_ack.pingpong) {
+ icsk->icsk_ack.pingpong)) {
/* Save one ACK. Data will be ready after
* several ticks, if write_pending is set.
*
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 64568fa..45ccafd 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1314,6 +1314,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops;
#endif
+ req->friend = skb->friend;
+
tcp_clear_options(&tmp_opt);
tmp_opt.mss_clamp = TCP_MSS_DEFAULT;
tmp_opt.user_mss = tp->rx_opt.user_mss;
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 72b7c63..4ff285b 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -315,6 +315,11 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
bool recycle_ok = false;
bool recycle_on = false;
+ if (sk->sk_friend) {
+ tcp_done(sk);
+ return;
+ }
+
if (tcp_death_row.sysctl_tw_recycle && tp->rx_opt.ts_recent_stamp) {
recycle_ok = tcp_remember_stamp(sk);
recycle_on = true;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index c465d3e..542b34a 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -65,6 +65,9 @@ int sysctl_tcp_slow_start_after_idle __read_mostly = 1;
int sysctl_tcp_cookie_size __read_mostly = 0; /* TCP_COOKIE_MAX */
EXPORT_SYMBOL_GPL(sysctl_tcp_cookie_size);
+/* TCP loopback bypass */
+int sysctl_tcp_friends __read_mostly = 1;
+
/* Account for new data that has been sent to the network. */
static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb)
@@ -829,9 +832,14 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
tcb = TCP_SKB_CB(skb);
memset(&opts, 0, sizeof(opts));
- if (unlikely(tcb->tcp_flags & TCPHDR_SYN))
+ if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) {
+ if (sysctl_tcp_friends) {
+ /* Only try to make friends if enabled */
+ skb->friend = sk;
+ }
+
tcp_options_size = tcp_syn_options(sk, skb, &opts, &md5);
- else
+ } else
tcp_options_size = tcp_established_options(sk, skb, &opts,
&md5);
tcp_header_size = tcp_options_size + sizeof(struct tcphdr);
@@ -2506,6 +2514,12 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
}
memset(&opts, 0, sizeof(opts));
+
+ if (sysctl_tcp_friends) {
+ /* Only try to make friends if enabled */
+ skb->friend = sk;
+ }
+
#ifdef CONFIG_SYN_COOKIES
if (unlikely(req->cookie_ts))
TCP_SKB_CB(skb)->when = cookie_init_timestamp(req);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6cc67ed..33f9d47 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1066,6 +1066,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops;
#endif
+ req->friend = skb->friend;
tcp_clear_options(&tmp_opt);
tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
tmp_opt.user_mss = tp->rx_opt.user_mss;
--
1.7.7.3
^ permalink raw reply related
* RE: Atheros Communications Inc. AR8121/AR8113/AR8114 Gigabit or Fast Ethernet (rev b0) 1.0.0.7 md5 corrupted using NFS
From: Huang, Xiong @ 2012-08-07 0:05 UTC (permalink / raw)
To: Marco Castiglione, netdev@vger.kernel.org
In-Reply-To: <201208061302.32582.marco.castiglione@yahoo.ca>
Marco
Could you run lspci, and list the kernel oops ?
we could duplicate it using the same NIC.
PS. The driver of 1.0.1.14 is not for your NIC.
Thanks
Xiong
> -----Original Message-----
> From: netdev-owner@vger.kernel.org [mailto:netdev-owner@vger.kernel.org]
> On Behalf Of Marco Castiglione
> Sent: Tuesday, August 07, 2012 1:03
> To: netdev@vger.kernel.org
> Subject: Atheros Communications Inc. AR8121/AR8113/AR8114 Gigabit or
> Fast Ethernet (rev b0) 1.0.0.7 md5 corrupted using NFS
>
> Hi,
>
> I have a problem with :
>
> Ethernet controller: Atheros Communications Inc. AR8121/AR8113/AR8114
> Gigabit or Fast Ethernet (rev b0)
> Subsystem: ASUSTeK Computer Inc. Device 831c
> Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop-
> ParErr-
> Stepping- SERR+ FastB2B- DisINTx+
> Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
> <TAbort- <MAbort- >SERR- <PERR- INTx-
> Latency: 0, Cache Line Size: 64 bytes
> Interrupt: pin A routed to IRQ 46
> Region 0: Memory at fbec0000 (64-bit, non-prefetchable) [size=256K]
> Region 2: I/O ports at dc00 [size=128]
> Capabilities: <access denied>
> Kernel driver in use: ATL1E
>
> The driver working fine except for nfs3 and nfs4
>
> If I try to copy a file bigger of 400 mb the file get corrupted, If I try with
> multiple files I have a kernel oops
>
> I tried different system and service (Ftp,samba) and they working fine.
>
> I also tried to set nfs to use udp, it kinda fix the problem but only in part (I get
> 1 on 3 big file with md5 mismatch).
>
> I notice in almost every kernel from 2.6 to now 3.2.15 the driver is the same
> version
>
> Filename: /lib/modules/3.2.0-2-amd64/
> kernel/drivers/net/ethernet/atheros/atl1e/atl1e.ko
> version: 1.0.0.7-NAPI
> license: GPL
> description: Atheros 1000M Ethernet Network Driver
> author: Atheros Corporation, <xiong.huang@atheros.com>, Jie Yang <
> jie.yang@atheros.com>
> srcversion: 6E5949327D7FDF32D5F4A5B
> alias: pci:v00001969d00001066sv*sd*bc*sc*i*
> alias: pci:v00001969d00001026sv*sd*bc*sc*i*
> depends:
> intree: Y
> vermagic: 3.2.0-2-amd64 SMP mod_unload modversions
> parm: tx_desc_cnt:Transmit description count (array of int)
> parm: rx_mem_size:memory size of rx buffer(KB) (array of int)
> parm: media_type:MediaType Select (array of int)
> parm: int_mod_timer:Interrupt Moderator Timer (array of int)
>
> I found on ubuntu website the last version of the driver is 1.0.1.14 with this
> change log :
>
> 1.0.1.14
> 1. don't define napi_struct in kcompat.h when GRO isn't supported.
>
> 1.0.1.13
> 1. fix AR8151-A hang when plug in LAN cable by cleaning bit1 of
> REG(0x1114).
>
> 1.0.1.12
> 1. fix tpd, rfd, rrs, configure error for powerpc
>
> 1.0.1.11
> 1. only save power when WOL enable.
>
> 1.0.1.10
> 1. add l1d 2.0 support.
> 2. fix atl1c_phy_power_saving bug.
>
> 1.0.1.9
> 1. fix AR8131 reset error TX pending.
> 2. add AR8152 description.
>
> 1.0.1.8
> 1. add L2CB V2.0 support.
>
> 1.0.1.7
> 1. fix L0s/L1 bug.
> 2. update suspend procedure.
>
> 1.0.1.6
> 1. fix valn error.
> 2. use common task instead of reset task and link change task.
> 3. reset phy when link down.
>
> 1.0.1.5
> 1. change rx mod.
>
> 1.0.1.4
> 1. add l1d support.
>
> 1.0.1.3
> 1. fix TSO error.
>
> 1.0.1.2
> 1. fix compile error for kernel >= 2.6.30.
>
> 1.0.1.1
> 1. add L2cB support.
>
> 1.0.0.10
> 1. fix memory leak when power suspend.
>
> 1.0.0.9
> 1. do power saving when bootup with link lost.
> 2. remove ATL1C_INTR_CLEAR_ON_READ for power saving
>
> 1.0.0.8
> 1. remove dump_stack(), which was used for debugging.
>
>
> So I found out the TSO is corrupt in the current version and that explain with
> the udp setting do the trick.
>
> Now I tried to compile the new version from AR81Family-linux-
> v1.0.1.14.tar.gz but was made for the 2.6 so I can't
> compile.( <http://goog_56610235>
> http://media.cdn.ubuntu-de.org/forum/attachments/2666793/AR81Family-
> linux-
> v1.0.1.14_10.10.tar.gz
> )
>
> The Atheros support and web page is gone after Qualcomm acquisition and
> the patch I found on Ubuntu forum don't work either (
> http://ubuntuforums.org/attachment.php?attachmentid=182141&d=1296221
> 015)
>
> I found out lots of people have the same issue and they using samba at the
> moment.
>
> My temp solution is use a usb/eth adapter with ax8112 chipset but it run at
> 100mbps.
>
> SO my request is this : Is possible for somebody of the kernel team look the
> code inside AR81Family-linux-v1.0.1.14.tar.gz and update the one in the
> kernel 3.x?
>
> Thank you for you time and consideration
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in the body
> of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: [PATCH 7/8] bridge: add some comments for NETDEV_RELEASE
From: Joe Perches @ 2012-08-06 23:39 UTC (permalink / raw)
To: David Miller; +Cc: amwang, netdev, shemminger
In-Reply-To: <20120806.135003.442648448779232464.davem@davemloft.net>
On Mon, 2012-08-06 at 13:50 -0700, David Miller wrote:
> From: Cong Wang <amwang@redhat.com>
> Date: Mon, 6 Aug 2012 22:23:31 +0800
>
> > + /*
> > + * We don't notify NETDEV_RELEASE event, as this will
> > + * stop netconsole on the bridge.
> > + */
>
> Please format comments in the networking:
>
> /* Like
> * this.
> */
Maybe add a networking specific block comment style
to checkpatch. This doesn't trigger on files outside
of drivers/net and net.
---
scripts/checkpatch.pl | 7 +++++++
1 files changed, 7 insertions(+), 0 deletions(-)
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 913d6bd..560f012 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1873,6 +1873,13 @@ sub process {
"No space is necessary after a cast\n" . $hereprev);
}
+ if ($realfile =~ m@^(drivers/net/|net/)@ &&
+ $rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
+ $prevrawline =~ /^\+[ \t]*$/) {
+ WARN("NETWORKING_BLOCK_COMMENT_STYLE",
+ "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
+ }
+
# check for spaces at the beginning of a line.
# Exceptions:
# 1) within comments
^ permalink raw reply related
* Re: [PATCH 00/13] SCTP: Enable netns
From: Eric W. Biederman @ 2012-08-06 23:06 UTC (permalink / raw)
To: Vlad Yasevich
Cc: David Miller, jan.ariyasu, linux-sctp, netdev, linux-kernel,
jan.ariyasu
In-Reply-To: <502039A8.7080807@gmail.com>
Vlad Yasevich <vyasevich@gmail.com> writes:
> On 08/06/2012 04:47 PM, David Miller wrote:
>> From: ebiederm@xmission.com (Eric W. Biederman)
>> Date: Mon, 06 Aug 2012 12:50:46 -0700
>>
>>> Vlad Yasevich <vyasevich@gmail.com> writes:
>>>
>>>
>>>> Hi Eric
>>>>
>>>> Associations are looked up by ports, but then verifyed by addresses.
>>>> Also, associations belong to sockets and simply validating the socket
>>>> namespace should be sufficient.
>>>
>>> True. Your set of patches isn't quite as likely to malfunction as it
>>> looked at first glance. It requires address reuse which happens accross
>>> namespaces but not too frequently.
>>>
>>> As for validating the socket namespace I agree that is the fix and my
>>> patchset winds up doing it.
>>
>> FWIW I much prefer Eric's patch set, it was so significantly easier to
>> read and validate than Jan's.
>>
>
> Yes, but Eric's patch set is missing a very significant piece which is per-net
> sctp tunables/globals. I think adding that piece in will introduce some of the
> complexities of Jan's patch.
And Jan's patchset is missing the per net snmp counters, as well
as the per net checks when looking in the hash tables. Things that look
like fairly fundamental correctness issues.
No offense but I think Jan's patchset has minor but significant
structural flaws and correctness issues that would require the patchset
to be respun, after review even if my patches did not exist.
The poor movement of variables from their global context into the per
net context is one of those problems.
The fact that after Jan's patchset all of the tunables despite being
made per net remain in struct sctp_globals and sit their unused is a
recipe for confusion.
So I think the simplest path forward would be to merge my patches, and
then merge Jan's tunable work after she has had a chance to rebase it.
> Also, I noticed that Eric went the route of placing sctp netns into struct net,
> but Jan used a generic pointer. Which one should be used? Is there some
> guidance?
Placing things directly in struct net is more efficient. Using net
generic is more convenient for development as using net generic does not
require a kernel recompile.
For minor things and especially where it does not have an impact on
performance net generic is the way to go.
It looked to me that sctp was fundamental enough and had enough
important data structures on the hot path that placing the variables
in struct net directly seemed sensible.
Eric
^ permalink raw reply
* Re: [PATCH 00/13] SCTP: Enable netns
From: Vlad Yasevich @ 2012-08-06 21:39 UTC (permalink / raw)
To: David Miller
Cc: ebiederm, jan.ariyasu, linux-sctp, netdev, linux-kernel,
jan.ariyasu
In-Reply-To: <20120806.134737.1358773847818872075.davem@davemloft.net>
On 08/06/2012 04:47 PM, David Miller wrote:
> From: ebiederm@xmission.com (Eric W. Biederman)
> Date: Mon, 06 Aug 2012 12:50:46 -0700
>
>> Vlad Yasevich <vyasevich@gmail.com> writes:
>>
>>
>>> Hi Eric
>>>
>>> Associations are looked up by ports, but then verifyed by addresses.
>>> Also, associations belong to sockets and simply validating the socket
>>> namespace should be sufficient.
>>
>> True. Your set of patches isn't quite as likely to malfunction as it
>> looked at first glance. It requires address reuse which happens accross
>> namespaces but not too frequently.
>>
>> As for validating the socket namespace I agree that is the fix and my
>> patchset winds up doing it.
>
> FWIW I much prefer Eric's patch set, it was so significantly easier to
> read and validate than Jan's.
>
Yes, but Eric's patch set is missing a very significant piece which is
per-net sctp tunables/globals. I think adding that piece in will
introduce some of the complexities of Jan's patch.
Also, I noticed that Eric went the route of placing sctp netns into
struct net, but Jan used a generic pointer. Which one should be used?
Is there some guidance?
-vlad
^ permalink raw reply
* Re: [PATCH net-next] igb: use build_skb()
From: Alexander Duyck @ 2012-08-06 21:28 UTC (permalink / raw)
To: Eric Dumazet; +Cc: Jeff Kirsher, netdev
In-Reply-To: <1344277315.26674.54.camel@edumazet-glaptop>
On 08/06/2012 11:21 AM, Eric Dumazet wrote:
> On Mon, 2012-08-06 at 10:35 -0700, Alexander Duyck wrote:
>
>> I was planning to move igb over to an ixgbe style receive path at some
>> point anyway. Since it seems like this is now a higher priority I
>> figured I would try to get the patches for it implemented in the next
>> week or so. Would there be any issue with us rejecting this patch and
>> instead switching igb over to the ixgbe style path?
> It seems I missed this part.
>
> I use igb on my dev machine, not on prod machines, so if you are moving
> igb to ixgbe, I can certainly can maintain my patch in my tree, while
> you make your changes.
>
I'll try to get the coding for this finished up this week and I can
probably send you a copy of the patches as an RFC. We will do testing
and hopefully we can have the patches pushed to net-next for 3.7.
Thanks,
Alex
^ permalink raw reply
* [GIT] Networking
From: David Miller @ 2012-08-06 21:23 UTC (permalink / raw)
To: torvalds; +Cc: akpm, netdev, linux-kernel
1) Missed rcu_assign_pointer() in mac80211 scanning, from Johannes Berg.
2) Allow devices to limit the number of segments that an individual
TCP TSO packet can use at a time, to deal with device and/or driver
specific limitations. From Ben Hutchings.
3) Fix unexpected hard IPSEC expiration after setting the date. From
Fan Du.
4) Memory leak fix in bxn2x driver, from Jesper Juhl.
5) Fix two memory leaks in libertas driver, from Daniel Drake.
6) Fix deref of out-of-range array index in packet scheduler generic
actions layer. From Hiroaki SHIMODA.
7) Fix TX flow control errors in mlx4 driver, from Yevgeny Petrilin.
8) Fix CRIS eth_v10.c driver build, from Randy Dunlap.
9) Fix wrong SKB freeing in LLC protocol layer, from Sorin Dumitru.
10) The IP output path checks neigh lookup errors incorrectly, it
needs to use IS_ERR(). From Vasiliy Kulikov.
11) An estimator leak leads to deref of freed memory in timer handler,
fix from Hiroaki SHIMODA.
12) TCP early demux in ipv6 needs to use DST cookies in order to
validate the RX route properly. Fix from Eric Dumazet.
Please pull, thanks a lot!
The following changes since commit 1a9b4993b70fb1884716902774dc9025b457760d:
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus (2012-08-01 16:47:15 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git master
for you to fetch changes up to 5d299f3d3c8a2fbc732b1bf03af36333ccec3130:
net: ipv6: fix TCP early demux (2012-08-06 13:33:21 -0700)
----------------------------------------------------------------
Amir Vadai (1):
net/mlx4_en: loopbacked packets are dropped when SMAC=DMAC
Arnaud Patard (1):
ixp4xx_eth: fix ptp_ixp46x build failure
Ben Hutchings (3):
net: Allow driver to limit number of GSO segments per skb
sfc: Fix maximum number of TSO segments and minimum TX queue size
tcp: Apply device TSO segment limit earlier
Carolyn Wyborny (1):
igb: Fix for failure to init on some 82576 devices.
Daniel Drake (2):
libertas: don't reset card on error when it is being removed
libertas: fix two memory leaks
Eliad Peller (1):
mac80211: don't clear sched_scan_sdata on sched scan stop request
Eric Dumazet (2):
ipv4: route.c cleanup
net: ipv6: fix TCP early demux
Fan Du (1):
Fix unexpected SA hard expiration after changing date
Haiyang Zhang (1):
hyperv: Move wait completion msg code into rndis_filter_halt_device()
Hiroaki SHIMODA (2):
net_sched: gact: Fix potential panic in tcf_gact().
net_sched: act: Delete estimator in error path.
Jesper Juhl (3):
bnx2x: fix mem leak when command is unknown
igb: correct hardware type (i210/i211) check in igb_loopback_test()
igb: don't break user visible strings over multiple lines in igb_ethtool.c
Johannes Berg (4):
mac80211: fix scan_sdata assignment
Merge remote-tracking branch 'wireless/master' into mac80211
mac80211: clear timer bits when disconnecting
mac80211: cancel mesh path timer
John W. Linville (1):
Merge branch 'for-john' of git://git.kernel.org/.../jberg/mac80211
Julia Lawall (2):
drivers/net/phy/mdio-mux-gpio.c: drop devm_kfree of devm_kzalloc'd data
drivers/atm/iphase.c: fix error return code
Karsten Keil (1):
mISDN: Bugfix for layer2 fixed TEI mode
Marek Lindner (1):
batman-adv: select an internet gateway if none was chosen
Masanari Iida (1):
emulex: benet: Add a missing CR in the end of message
Mohammed Shafi Shajakhan (1):
ath9k: Add PID/VID support for AR1111
Paul Stewart (1):
cfg80211: Clear "beacon_found" on regulatory restore
Peter Meiser (1):
cdc-ncm: tag Ericsson WWAN devices (eg F5521gw) with FLAG_WWAN
Rafał Miłecki (2):
bcma: BCM43228 support
b43: fix logic in GPIO init
Randy Dunlap (1):
cris: fix eth_v10.c build error
Seth Forshee (2):
cfg80211: add channel flag to prohibit OFDM operation
brcmsmac: use channel flags to restrict OFDM
Silviu-Mihai Popescu (1):
tcp_output: fix sparse warning for tcp_wfree
Sorin Dumitru (1):
llc: free the right skb
Stanislaw Gruszka (1):
wireless: reg: restore previous behaviour of chan->max_power calculations
Thomas Meyer (1):
net: Use PTR_RET rather than if(IS_ERR(.. [1]
Vasiliy Kulikov (1):
ip: fix error handling in ip_finish_output2()
Woody Hung (1):
rt2x00 : fix rt3290 resuming failed.
Wu Fengguang (1):
isdnloop: fix and simplify isdnloop_init()
Yevgeny Petrilin (2):
net/mlx4_en: Fixing TX queue stop/wake flow
net/mlx4_core: Remove port type restrictions
drivers/atm/iphase.c | 2 +-
drivers/bcma/host_pci.c | 1 +
drivers/bcma/sprom.c | 4 ++-
drivers/isdn/isdnloop/isdnloop.c | 12 -------
drivers/isdn/mISDN/layer2.c | 2 +-
drivers/net/appletalk/cops.c | 4 +--
drivers/net/appletalk/ltpc.c | 4 +--
drivers/net/cris/eth_v10.c | 2 +-
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c | 1 +
drivers/net/ethernet/emulex/benet/be_main.c | 2 +-
drivers/net/ethernet/intel/igb/e1000_82575.c | 16 ++++-----
drivers/net/ethernet/intel/igb/igb_ethtool.c | 25 +++++++-------
drivers/net/ethernet/mellanox/mlx4/en_rx.c | 4 +--
drivers/net/ethernet/mellanox/mlx4/en_tx.c | 17 ++++------
drivers/net/ethernet/mellanox/mlx4/main.c | 3 --
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 -
drivers/net/ethernet/mellanox/mlx4/sense.c | 14 --------
drivers/net/ethernet/sfc/efx.c | 6 ++++
drivers/net/ethernet/sfc/efx.h | 14 +++++---
drivers/net/ethernet/sfc/ethtool.c | 16 ++++++---
drivers/net/ethernet/sfc/tx.c | 19 +++++++++++
drivers/net/ethernet/xscale/ixp4xx_eth.c | 1 +
drivers/net/hyperv/netvsc.c | 7 ----
drivers/net/hyperv/rndis_filter.c | 11 ++++++
drivers/net/phy/mdio-mux-gpio.c | 1 -
drivers/net/usb/cdc_ncm.c | 20 +++++++++++
drivers/net/wireless/ath/ath9k/hw.c | 1 +
drivers/net/wireless/ath/ath9k/hw.h | 1 +
drivers/net/wireless/ath/ath9k/pci.c | 1 +
drivers/net/wireless/b43/main.c | 21 +++++++-----
drivers/net/wireless/brcm80211/brcmsmac/channel.c | 5 +--
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 3 +-
drivers/net/wireless/libertas/cfg.c | 1 +
drivers/net/wireless/libertas/if_sdio.c | 1 +
drivers/net/wireless/libertas/main.c | 5 ++-
drivers/net/wireless/rt2x00/rt2800lib.c | 68 +++++++++++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2800pci.c | 71 ---------------------------------------
include/linux/bcma/bcma_driver_chipcommon.h | 6 ++++
include/linux/ipv6.h | 1 +
include/linux/netdevice.h | 2 ++
include/net/cfg80211.h | 2 ++
include/net/inet_connection_sock.h | 1 +
include/net/inet_sock.h | 9 -----
include/net/sock.h | 2 ++
include/net/xfrm.h | 4 +++
net/batman-adv/gateway_client.c | 6 ++--
net/core/dev.c | 4 +++
net/core/sock.c | 1 +
net/ipv4/ip_output.c | 2 +-
net/ipv4/route.c | 4 ---
net/ipv4/tcp.c | 4 ++-
net/ipv4/tcp_cong.c | 3 +-
net/ipv4/tcp_input.c | 4 ++-
net/ipv4/tcp_ipv4.c | 13 +++++--
net/ipv4/tcp_minisocks.c | 2 +-
net/ipv4/tcp_output.c | 23 +++++++------
net/ipv6/tcp_ipv6.c | 27 +++++++++++++--
net/llc/llc_station.c | 6 ++--
net/mac80211/mesh.c | 3 ++
net/mac80211/mlme.c | 2 ++
net/mac80211/scan.c | 3 +-
net/sched/act_gact.c | 14 ++++++--
net/sched/act_ipt.c | 7 +++-
net/sched/act_pedit.c | 5 ++-
net/sched/act_simple.c | 5 ++-
net/wireless/reg.c | 19 ++++++++++-
net/xfrm/xfrm_state.c | 21 +++++++++---
67 files changed, 364 insertions(+), 228 deletions(-)
^ permalink raw reply
* Re: [PATCH net-next] tcp: ecn: dont delay ACKS after CE
From: David Miller @ 2012-08-06 21:14 UTC (permalink / raw)
To: ncardwell; +Cc: eric.dumazet, netdev
In-Reply-To: <CADVnQyk25R4qpXq7Mho=uHwCswALPdOR=nP=AjQy7qJyT+HFuA@mail.gmail.com>
From: Neal Cardwell <ncardwell@google.com>
Date: Mon, 6 Aug 2012 17:07:08 -0400
> On Mon, Aug 6, 2012 at 5:04 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> From: Eric Dumazet <edumazet@google.com>
>>
>> While playing with CoDel and ECN marking, I discovered a
>> non optimal behavior of receiver of CE (Congestion Encountered)
>> segments.
>>
>> In pathological cases, sender has reduced its cwnd to low values,
>> and receiver delays its ACK (by 40 ms).
>>
>> While RFC 3168 6.1.3 (The TCP Receiver) doesn't explicitly recommend
>> to send immediate ACKS, we believe its better to not delay ACKS, because
>> a CE segment should give same signal than a dropped segment, and its
>> quite important to reduce RTT to give ECE/CWR signals as fast as
>> possible.
>>
>> Note we already call tcp_enter_quickack_mode() from TCP_ECN_check_ce()
>> if we receive a retransmit, for the same reason.
>>
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
>> Cc: Neal Cardwell <ncardwell@google.com>
>
> Acked-by: Neal Cardwell <ncardwell@google.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next] tcp: ecn: dont delay ACKS after CE
From: Neal Cardwell @ 2012-08-06 21:07 UTC (permalink / raw)
To: Eric Dumazet; +Cc: David Miller, netdev
In-Reply-To: <1344287083.26674.83.camel@edumazet-glaptop>
On Mon, Aug 6, 2012 at 5:04 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> From: Eric Dumazet <edumazet@google.com>
>
> While playing with CoDel and ECN marking, I discovered a
> non optimal behavior of receiver of CE (Congestion Encountered)
> segments.
>
> In pathological cases, sender has reduced its cwnd to low values,
> and receiver delays its ACK (by 40 ms).
>
> While RFC 3168 6.1.3 (The TCP Receiver) doesn't explicitly recommend
> to send immediate ACKS, we believe its better to not delay ACKS, because
> a CE segment should give same signal than a dropped segment, and its
> quite important to reduce RTT to give ECE/CWR signals as fast as
> possible.
>
> Note we already call tcp_enter_quickack_mode() from TCP_ECN_check_ce()
> if we receive a retransmit, for the same reason.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
> Cc: Neal Cardwell <ncardwell@google.com>
Acked-by: Neal Cardwell <ncardwell@google.com>
neal
^ permalink raw reply
* [PATCH net-next] tcp: ecn: dont delay ACKS after CE
From: Eric Dumazet @ 2012-08-06 21:04 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Neal Cardwell
From: Eric Dumazet <edumazet@google.com>
While playing with CoDel and ECN marking, I discovered a
non optimal behavior of receiver of CE (Congestion Encountered)
segments.
In pathological cases, sender has reduced its cwnd to low values,
and receiver delays its ACK (by 40 ms).
While RFC 3168 6.1.3 (The TCP Receiver) doesn't explicitly recommend
to send immediate ACKS, we believe its better to not delay ACKS, because
a CE segment should give same signal than a dropped segment, and its
quite important to reduce RTT to give ECE/CWR signals as fast as
possible.
Note we already call tcp_enter_quickack_mode() from TCP_ECN_check_ce()
if we receive a retransmit, for the same reason.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
---
net/ipv4/tcp_input.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 2fd2bc9..fa2c2c2 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -237,7 +237,11 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, const struct sk_buff *s
tcp_enter_quickack_mode((struct sock *)tp);
break;
case INET_ECN_CE:
- tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
+ if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) {
+ /* Better not delay acks, sender can have a very low cwnd */
+ tcp_enter_quickack_mode((struct sock *)tp);
+ tp->ecn_flags |= TCP_ECN_DEMAND_CWR;
+ }
/* fallinto */
default:
tp->ecn_flags |= TCP_ECN_SEEN;
^ permalink raw reply related
* Re: [PATCH 7/8] bridge: add some comments for NETDEV_RELEASE
From: David Miller @ 2012-08-06 20:50 UTC (permalink / raw)
To: amwang; +Cc: netdev, shemminger
In-Reply-To: <1344263012-4031-8-git-send-email-amwang@redhat.com>
From: Cong Wang <amwang@redhat.com>
Date: Mon, 6 Aug 2012 22:23:31 +0800
> + /*
> + * We don't notify NETDEV_RELEASE event, as this will
> + * stop netconsole on the bridge.
> + */
Please format comments in the networking:
/* Like
* this.
*/
Thanks.
^ permalink raw reply
* Re: [PATCH 00/13] SCTP: Enable netns
From: David Miller @ 2012-08-06 20:47 UTC (permalink / raw)
To: ebiederm
Cc: vyasevich, jan.ariyasu, linux-sctp, netdev, linux-kernel,
jan.ariyasu
In-Reply-To: <874noflrzd.fsf@xmission.com>
From: ebiederm@xmission.com (Eric W. Biederman)
Date: Mon, 06 Aug 2012 12:50:46 -0700
> Vlad Yasevich <vyasevich@gmail.com> writes:
>
>
>> Hi Eric
>>
>> Associations are looked up by ports, but then verifyed by addresses.
>> Also, associations belong to sockets and simply validating the socket
>> namespace should be sufficient.
>
> True. Your set of patches isn't quite as likely to malfunction as it
> looked at first glance. It requires address reuse which happens accross
> namespaces but not too frequently.
>
> As for validating the socket namespace I agree that is the fix and my
> patchset winds up doing it.
FWIW I much prefer Eric's patch set, it was so significantly easier to
read and validate than Jan's.
^ permalink raw reply
* Re: [PATCH 1/6] hash: Introduce ptr_hash_mix routine
From: David Miller @ 2012-08-06 20:44 UTC (permalink / raw)
To: xemul; +Cc: eric.dumazet, ebiederm, netdev
In-Reply-To: <501FD11B.6000006@parallels.com>
From: Pavel Emelyanov <xemul@parallels.com>
Date: Mon, 06 Aug 2012 18:13:47 +0400
> @@ -67,4 +68,13 @@ static inline unsigned long hash_ptr(const void *ptr, unsigned int bits)
> {
> return hash_long((unsigned long)ptr, bits);
> }
> +
> +static inline u32 ptr_hash_mix(const void *ptr)
> +{
> +#if BITS_PER_LONG == 32
> + return (u32)(unsigned long)ptr;
> +#else
> + return (u32)((unsigned long)ptr >> L1_CACHE_SHIFT);
> +#endif
> +}
> #endif /* _LINUX_HASH_H */
This doesn't make much sense to me.
If the whole 32-bits of the pointer is useful for entropy on 32-bit
why isn't the whole 64-bits useful on 64-bit?
I would, instead, expect something like:
ptr ^ (ptr >> 32)
for the 64-bit case.
Also, that L1_CACHE_SHIFT is something callers can decide to do.
Only they know the size of their structure, the alignment used to
allocate such objects, and thus what bits are "less relevant" and
therefore profitable to elide from the bottom of the value.
^ permalink raw reply
* Re: [PATCH RFC] net: tcp: GRO should be ECN friendly
From: David Miller @ 2012-08-06 20:41 UTC (permalink / raw)
To: herbert; +Cc: eric.dumazet, netdev
In-Reply-To: <20120806090150.GB18425@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Mon, 6 Aug 2012 17:01:50 +0800
> On Mon, Aug 06, 2012 at 10:34:50AM +0200, Eric Dumazet wrote:
>> From: Eric Dumazet <edumazet@google.com>
>>
>> While doing TCP ECN tests, I discovered GRO was reordering packets if it
>> receives one packet with CE set, while previous packets in same NAPI run
>> have ECT(0) for the same flow :
>>
>> 09:25:25.857620 IP (tos 0x2,ECT(0), ttl 64, id 27893, offset 0, flags
>> [DF], proto TCP (6), length 4396)
>> 172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
>> 233801:238145, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
>> 1990627], length 4344
>>
>> 09:25:25.857626 IP (tos 0x3,CE, ttl 64, id 27892, offset 0, flags [DF],
>> proto TCP (6), length 1500)
>> 172.30.42.19.54550 > 172.30.42.13.44139: Flags [.], seq
>> 232353:233801, ack 1, win 115, options [nop,nop,TS val 3397779 ecr
>> 1990627], length 1448
>>
>> 09:25:25.857638 IP (tos 0x0, ttl 64, id 34581, offset 0, flags [DF],
>> proto TCP (6), length 64)
>> 172.30.42.13.44139 > 172.30.42.19.54550: Flags [.], cksum 0xac8f
>> (incorrect -> 0xca69), ack 232353, win 1271, options [nop,nop,TS val
>> 1990627 ecr 3397779,nop,nop,sack 1 {233801:238145}], length 0
>>
>> We have two problems here :
>>
>> 1) GRO reorders packets
>>
>> If NIC gave packet1, then packet2, which happen to be from "different
>> flows" GRO feeds stack with packet2, then packet1. I have yet to
>> understand how to solve this problem.
>>
>> 2) GRO is not ECN friendly
>>
>> Delivering packets out of order makes TCP stack not as fast as it could
>> be.
>>
>> In this patch I suggest we make the tos test not part of the 'same_flow'
>> determination, but part of the 'should flush' logic
>>
>> Signed-off-by: Eric Dumazet <edumazet@google.com>
>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
>
> Good catch, thanks Eric!
Applied to net-next, thanks Eric.
^ permalink raw reply
* Re: [PATCH net-next] net: reorganize IP MIB values
From: David Miller @ 2012-08-06 20:41 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344148439.9299.1570.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 05 Aug 2012 08:33:59 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> Reduce IP latencies by placing hot MIB IP fields in a single cache line.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied.
^ permalink raw reply
* Re: [PATCH] net: avoid reloads in SNMP_UPD_PO_STATS
From: David Miller @ 2012-08-06 20:40 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344147973.9299.1563.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Sun, 05 Aug 2012 08:26:13 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> Avoid two instructions to reload dev->nd_net->mib.ip_statistics pointer,
> unsing a temp variable, in ip_rcv(), ip_output() paths for example.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied to net-next
^ permalink raw reply
* Re: [PATCH] net: ipv6: fix TCP early demux
From: David Miller @ 2012-08-06 20:33 UTC (permalink / raw)
To: eric.dumazet; +Cc: netdev
In-Reply-To: <1344265773.26674.27.camel@edumazet-glaptop>
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Mon, 06 Aug 2012 17:09:33 +0200
> From: Eric Dumazet <edumazet@google.com>
>
> IPv6 needs a cookie in dst_check() call.
>
> We need to add rx_dst_cookie and provide a family independent
> sk_rx_dst_set(sk, skb) method to properly support IPv6 TCP early demux.
>
> Signed-off-by: Eric Dumazet <edumazet@google.com>
Applied, thanks.
> ---
> Note: we could group sk_rx_dst/rx_dst_ifindex/rx_dst_cookie
> in same cache line (in sk)
I don't think this is necessary, for now.
^ permalink raw reply
* Re: [PATCH net] net_sched: act: Delete estimator in error path.
From: David Miller @ 2012-08-06 20:32 UTC (permalink / raw)
To: shimoda.hiroaki; +Cc: netdev
In-Reply-To: <20120807004548.6f9e7b6d1e566d7eead73497@gmail.com>
From: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Date: Tue, 7 Aug 2012 00:45:48 +0900
> Some action modules free struct tcf_common in their error path
> while estimator is still active. This results in est_timer()
> dereference freed memory.
> Add gen_kill_estimator() in ipt, pedit and simple action.
>
> Signed-off-by: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Applied.
^ permalink raw reply
* Re: [PATCH] ip: fix error handling in ip_finish_output2()
From: David Miller @ 2012-08-06 20:32 UTC (permalink / raw)
To: segoon; +Cc: kuznet, jmorris, yoshfuji, kaber, netdev, linux-kernel
In-Reply-To: <20120806135529.GA30699@albatros>
From: Vasily Kulikov <segoon@openwall.com>
Date: Mon, 6 Aug 2012 17:55:29 +0400
> __neigh_create() returns either a pointer to struct neighbour or PTR_ERR().
> But the caller expects it to return either a pointer or NULL. Replace
> the NULL check with IS_ERR() check.
>
> The bug was introduced in a263b3093641fb1ec377582c90986a7fd0625184.
>
> Signed-off-by: Vasily Kulikov <segoon@openwall.com>
Applied.
Please provide the proper commit log header line text when referencing
another commit, otherwise in trees where the SHA1 IDs are different,
nobody will be able to figure out what you are trying to refer to.
Thanks.
^ permalink raw reply
* Re: [PATCH] llc: free the right skb
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
To: sdumitru; +Cc: netdev, acme
In-Reply-To: <1344256558-22649-1-git-send-email-sdumitru@ixiacom.com>
From: Sorin Dumitru <sdumitru@ixiacom.com>
Date: Mon, 6 Aug 2012 15:35:58 +0300
> We are freeing skb instead of nskb, resulting in a double
> free on skb and a leak from nskb.
>
> Signed-off-by: Sorin Dumitru <sdumitru@ixiacom.com>
Applied.
^ permalink raw reply
* Re: [patch 1/1] ixp4xx_eth: fix ptp_ixp46x build failure
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
To: arnaud.patard; +Cc: netdev, khc
In-Reply-To: <20120805203042.509148064@rtp-net.org>
From: Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
Date: Sun, 05 Aug 2012 22:30:11 +0200
> When building with ixp4xx_eth and ptp_ixp46x as module, one is getting the
> following error:
>
> ERROR: "ixp46x_phc_index" [drivers/ptp/ptp_ixp46x.ko] undefined!
>
> This has been introduced by commit 509a7c25729feab353502e1b544c614772a1d49a.
>
> Signed-off-by: Arnaud Patard <arnaud.patard@rtp-net.org>
Applied.
^ permalink raw reply
* Re: Subject: [PATCH] sched: add missing group change to qfq_change_class
From: David Miller @ 2012-08-06 20:31 UTC (permalink / raw)
To: paolo.valente; +Cc: shemminger, jhs, fchecconi, rizzo, netdev, linux-kernel
In-Reply-To: <501ECD61.5090209@unimore.it>
From: Paolo Valente <paolo.valente@unimore.it>
Date: Sun, 05 Aug 2012 21:45:37 +0200
> To speed up operations, QFQ internally divides classes into
> groups. Which group a class belongs to depends on the ratio between
> the maximum packet length and the weight of the class. Unfortunately
> the function qfq_change_class lacks the steps for changing the group
> of a class when the ratio max_pkt_len/weight of the class changes.
>
> For example, when the last of the following three commands is
> executed, the group of class 1:1 is not correctly changed:
>
> tc disc add dev XXX root handle 1: qfq
> tc class add dev XXX parent 1: qfq classid 1:1 weight 1
> tc class change dev XXX parent 1: classid 1:1 qfq weight 4
>
> Not changing the group of a class does not affect the long-term
> bandwidth guaranteed to the class, as the latter is independent of the
> maximum packet length, and correctly changes (only) if the weight of
> the class changes. In contrast, if the group of the class is not
> updated, the class is still guaranteed the short-term bandwidth and
> packet delay related to its old group, and not the guarantees that it
> should receive according to its new weight and/or maximum packet
> length. This may also break service guarantees for other classes.
> This patch adds the missing operations.
>
> Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
Please provide clean Subject lines with patch submissions.
Also, this patch doesn't apply cleanly at all. Email the patch
to yourself, and verify that you can in fact apply it to the
current networking GIT tree just as I will have to.
^ permalink raw reply
* Re: [PATCH 6/6] drivers/atm/iphase.c: fix error return code
From: David Miller @ 2012-08-06 20:30 UTC (permalink / raw)
To: Julia.Lawall
Cc: chas, kernel-janitors, linux-atm-general, netdev, linux-kernel,
julia
In-Reply-To: <1344160356-387-7-git-send-email-Julia.Lawall@lip6.fr>
From: Julia Lawall <Julia.Lawall@lip6.fr>
Date: Sun, 5 Aug 2012 11:52:36 +0200
> From: Julia Lawall <julia@diku.dk>
>
> Convert a 0 error return code to a negative one, as returned elsewhere in the
> function.
>
> A simplified version of the semantic match that finds this problem is as
> follows: (http://coccinelle.lip6.fr/)
...
> Signed-off-by: Julia Lawall <julia@diku.dk>
Applied.
^ permalink raw reply
* Re: [PATCH] tcp_output: fix sparse warning for tcp_wfree
From: David Miller @ 2012-08-06 20:30 UTC (permalink / raw)
To: silviupopescu1990; +Cc: netdev, kuznet, jmorris, yoshfuji, kaber, linux-kernel
In-Reply-To: <1344108689-17896-1-git-send-email-silviupopescu1990@gmail.com>
From: Silviu-Mihai Popescu <silviupopescu1990@gmail.com>
Date: Sat, 4 Aug 2012 22:31:29 +0300
> Fix sparse warning:
> * symbol 'tcp_wfree' was not declared. Should it be static?
>
> Signed-off-by: Silviu-Mihai Popescu <silviupopescu1990@gmail.com>
Applied.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox