aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 4a8ec457310f..8cdee120a50c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1950,6 +1950,50 @@ void tcp_v4_early_demux(struct sk_buff *skb)
1950 } 1950 }
1951} 1951}
1952 1952
1953/* Packet is added to VJ-style prequeue for processing in process
1954 * context, if a reader task is waiting. Apparently, this exciting
1955 * idea (VJ's mail "Re: query about TCP header on tcp-ip" of 07 Sep 93)
1956 * failed somewhere. Latency? Burstiness? Well, at least now we will
1957 * see, why it failed. 8)8) --ANK
1958 *
1959 */
1960bool tcp_prequeue(struct sock *sk, struct sk_buff *skb)
1961{
1962 struct tcp_sock *tp = tcp_sk(sk);
1963
1964 if (sysctl_tcp_low_latency || !tp->ucopy.task)
1965 return false;
1966
1967 if (skb->len <= tcp_hdrlen(skb) &&
1968 skb_queue_len(&tp->ucopy.prequeue) == 0)
1969 return false;
1970
1971 __skb_queue_tail(&tp->ucopy.prequeue, skb);
1972 tp->ucopy.memory += skb->truesize;
1973 if (tp->ucopy.memory > sk->sk_rcvbuf) {
1974 struct sk_buff *skb1;
1975
1976 BUG_ON(sock_owned_by_user(sk));
1977
1978 while ((skb1 = __skb_dequeue(&tp->ucopy.prequeue)) != NULL) {
1979 sk_backlog_rcv(sk, skb1);
1980 NET_INC_STATS_BH(sock_net(sk),
1981 LINUX_MIB_TCPPREQUEUEDROPPED);
1982 }
1983
1984 tp->ucopy.memory = 0;
1985 } else if (skb_queue_len(&tp->ucopy.prequeue) == 1) {
1986 wake_up_interruptible_sync_poll(sk_sleep(sk),
1987 POLLIN | POLLRDNORM | POLLRDBAND);
1988 if (!inet_csk_ack_scheduled(sk))
1989 inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
1990 (3 * tcp_rto_min(sk)) / 4,
1991 TCP_RTO_MAX);
1992 }
1993 return true;
1994}
1995EXPORT_SYMBOL(tcp_prequeue);
1996
1953/* 1997/*
1954 * From tcp_input.c 1998 * From tcp_input.c
1955 */ 1999 */