On Mon, Apr 18, 2016 at 05:06:57PM -0700, Eric Dumazet wrote: > It should only be a request from user space to ask TCP to not aggregate > stuff on future sendpage()/sendmsg() on the skb carrying this new flag. > How about something like this. Please advise if tcp_sendmsg_noappend can be simpler.
diff --git a/include/net/tcp.h b/include/net/tcp.h index c0ef054..ac31798 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -762,7 +762,8 @@ struct tcp_skb_cb { __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ __u8 txstamp_ack:1, /* Record TX timestamp for ack? */ - unused:7; + eor:1, /* Is skb MSG_EOR marked */ + unused:6; __u32 ack_seq; /* Sequence number ACK'd */ union { struct inet_skb_parm h4; diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 4d73858..12772be 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -874,6 +874,13 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) return mss_now; } +static bool tcp_sendmsg_noappend(const struct sock *sk) +{ + const struct sk_buff *skb = tcp_write_queue_tail(sk); + + return (!skb || TCP_SKB_CB(skb)->eor); +} + static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, size_t size, int flags) { @@ -903,6 +910,9 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) goto out_err; + if (tcp_sendmsg_noappend(sk)) + goto new_segment; + while (size > 0) { struct sk_buff *skb = tcp_write_queue_tail(sk); int copy, i; @@ -960,6 +970,7 @@ new_segment: size -= copy; if (!size) { tcp_tx_timestamp(sk, sk->sk_tsflags, skb); + TCP_SKB_CB(skb)->eor = !!(flags & MSG_EOR); goto out; } @@ -1145,6 +1156,9 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) sg = !!(sk->sk_route_caps & NETIF_F_SG); + if (tcp_sendmsg_noappend(sk)) + goto new_segment; + while (msg_data_left(msg)) { int copy = 0; int max = size_goal; @@ -1250,6 +1264,7 @@ new_segment: copied += copy; if (!msg_data_left(msg)) { tcp_tx_timestamp(sk, sockc.tsflags, skb); + TCP_SKB_CB(skb)->eor = !!(flags & MSG_EOR); goto out; } -- 2.5.1