Messages in this thread | | | Date | Mon, 8 Mar 1999 17:47:36 +0100 (CET) | From | Matthias Moeller <> | Subject | Re: TCP window updates [Was: PROBLEM: Sending mail-attachment] |
| |
On Mon, 8 Mar 1999, Andrea Arcangeli wrote:
> >> + schedule_timeout(10*HZ); > > > >What is this timeout supposed to do exactly? > > It will unblock after 10 sec if not wakenup before by the reception of > some new packet. > > So after 10 sec the loop restart and you'll be inside cleanup_rbuf again > and you'll send a new ack. Dave said it's not needed though so probably I > missed something here too.
cleanup_rbuf() only sends a new ACK if it can advertise an increased window. It would probably be the wrong thing anyway to send an ACK all 10 seconds. Maybe the sender has no data. The sender should probe the receivers window. Linux has TIME_PROBE0 for this. As long as the sender has data to send this works fine. If the receivers window is too small (in terms of SWS avoidance?) the TIMER_PROBE0 will be started.
This works as follows:
tcp_rcv_established() calls tcp_data_send_check() for an incoming ACK:
static __inline__ void tcp_data_snd_check(struct sock *sk) { struct sk_buff *skb = sk->tp_pinfo.af_tcp.send_head;
if (skb != NULL) __tcp_data_snd_check(sk, skb); }
this calls __tcp_data_snd_check() but only if we have data to send.
__tcp_data_snd_check() now puts either data on the wire or starts the PROBE0 timer.
This all works fine until the receiver has advertised a very small window __and__ the sender does not have any data queued in this moment.
Any further write() calls with small write sizes on sender side will neither put data on the wire nor start the PROBE0 timer!
I had real deadlocks because of this and the bug in cleanup_rbuf(), the reveiver did not advertise increased windows. Okay, with Daves fix the receiver now does that but these ACKs could be dropped by the network.
I think this could be fixed in tcp_v4_sendmsg():
lock_sock(sk); retval = tcp_do_sendmsg(sk, msg->msg_iovlen, msg->msg_iov, msg->msg_flags); /* Push out partial tail frames if needed. */ tp = &(sk->tp_pinfo.af_tcp); if(tp->send_head && tcp_snd_test(sk, tp->send_head)) tcp_write_xmit(sk); + else + if (tp->packets_out == 0 && !tp->pending) + tcp_reset_xmit_timer(sk, TIME_PROBE0, tp->rto); release_sock(sk);
out: return retval;
Or it could be fixed in tcp_do_sendmsg() (The stuff with copied and queue_it, queue_it is always 1 for small write() sizes. So _no_ data will get on the wire an the PROBE0 timer will _not_ be started).
Matthias
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |