diff options
author | jlemon <jlemon@FreeBSD.org> | 2003-02-19 21:18:23 +0000 |
---|---|---|
committer | jlemon <jlemon@FreeBSD.org> | 2003-02-19 21:18:23 +0000 |
commit | 8b16df5c375c62f55a0bcea508d27d701a505e02 (patch) | |
tree | 5fd0290a91d0e3b84e43be4acc5477d4dc970210 | |
parent | 13bf23a61cb3844604c8df4e11030488a4557188 (diff) | |
download | FreeBSD-src-8b16df5c375c62f55a0bcea508d27d701a505e02.zip FreeBSD-src-8b16df5c375c62f55a0bcea508d27d701a505e02.tar.gz |
Clean up delayed acks and T/TCP interactions:
- delay acks for T/TCP regardless of delack setting
- fix bug where a single pass through tcp_input might not delay acks
- use callout_active() instead of callout_pending()
Sponsored by: DARPA, NAI Labs
-rw-r--r-- | sys/netinet/tcp_input.c | 55 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 7 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 55 |
3 files changed, 58 insertions, 59 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index f8de9e9..748d145 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -153,14 +153,16 @@ do { \ /* * Indicate whether this ack should be delayed. We can delay the ack if - * - delayed acks are enabled and * - there is no delayed ack timer in progress and * - our last ack wasn't a 0-sized window. We never want to delay - * the ack that opens up a 0-sized window. + * the ack that opens up a 0-sized window and + * - delayed acks are enabled or + * - this is a half-synchronized T/TCP connection. */ -#define DELAY_ACK(tp) \ - (tcp_delack_enabled && !callout_pending(tp->tt_delack) && \ - (tp->t_flags & TF_RXWIN0SENT) == 0) +#define DELAY_ACK(tp) \ + (((!callout_active(tp->tt_delack) && \ + (tp->t_flags & TF_RXWIN0SENT) == 0)) && \ + (tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN))) static int tcp_reass(tp, th, tlenp, m) @@ -505,7 +507,7 @@ tcp_input(m, off0) th->th_urp = ntohs(th->th_urp); /* - * Delay droping TCP, IP headers, IPv6 ext headers, and TCP options, + * Delay dropping TCP, IP headers, IPv6 ext headers, and TCP options, * until after ip6_savecontrol() is called and before other functions * which don't want those proto headers. * Because ip6_savecontrol() is going to parse the mbuf to @@ -862,23 +864,16 @@ findpcb: tp->t_state = TCPS_ESTABLISHED; /* - * If there is a FIN, or if there is data and the - * connection is local, then delay SYN,ACK(SYN) in - * the hope of piggy-backing it on a response - * segment. Otherwise must send ACK now in case - * the other side is slow starting. + * T/TCP logic: + * If there is a FIN or if there is data, then + * delay SYN,ACK(SYN) in the hope of piggy-backing + * it on a response segment. Otherwise must send + * ACK now in case the other side is slow starting. */ - if (DELAY_ACK(tp) && - ((thflags & TH_FIN) || - (tlen != 0 && - ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || - (!isipv6 && in_localaddr(inp->inp_faddr)))))) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); - tp->t_flags |= TF_NEEDSYN; - } else + if (thflags & TH_FIN || tlen != 0) + tp->t_flags |= (TF_DELACK | TF_NEEDSYN); + else tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); - tcpstat.tcps_connects++; soisconnected(so); goto trimthenstep6; @@ -1089,8 +1084,7 @@ after_listen: } sorwakeup(so); if (DELAY_ACK(tp)) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tp->t_flags |= TF_DELACK; } else { tp->t_flags |= TF_ACKNOW; tcp_output(tp); @@ -2099,8 +2093,7 @@ dodata: /* XXX */ LIST_EMPTY(&tp->t_segq) && TCPS_HAVEESTABLISHED(tp->t_state)) { if (DELAY_ACK(tp)) - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tp->t_flags |= TF_DELACK; else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt += tlen; @@ -2143,9 +2136,8 @@ dodata: /* XXX */ * Otherwise, since we received a FIN then no * more input can be expected, send ACK now. */ - if (DELAY_ACK(tp) && (tp->t_flags & TF_NEEDSYN)) - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + if (tp->t_flags & TF_NEEDSYN) + tp->t_flags |= TF_DELACK; else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; @@ -2214,6 +2206,13 @@ dodata: /* XXX */ */ if (needoutput || (tp->t_flags & TF_ACKNOW)) (void) tcp_output(tp); + else if (tp->t_flags & TF_DELACK) { + tp->t_flags &= ~TF_DELACK; + KASSERT(!callout_active(tp->tt_delack), + ("delayed ack already active")); + callout_reset(tp->tt_delack, tcp_delacktime, + tcp_timer_delack, tp); + } INP_UNLOCK(inp); return; diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index 34b0d84..a917ed3 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -339,8 +339,9 @@ again: * next expected input). If the difference is at least two * max size segments, or at least 50% of the maximum possible * window, then want to send a window update to peer. + * Skip this if the connection is in T/TCP half-open state. */ - if (win > 0) { + if (win > 0 && !(tp->t_flags & TF_NEEDSYN)) { /* * "adv" is the amount we can increase the window, * taking into account that we are limited by @@ -965,8 +966,8 @@ out: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) tp->rcv_adv = tp->rcv_nxt + win; tp->last_ack_sent = tp->rcv_nxt; - tp->t_flags &= ~TF_ACKNOW; - if (tcp_delack_enabled) + tp->t_flags &= ~(TF_ACKNOW | TF_DELACK); + if (callout_active(tp->tt_delack)) callout_stop(tp->tt_delack); #if 0 /* diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index f8de9e9..748d145 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -153,14 +153,16 @@ do { \ /* * Indicate whether this ack should be delayed. We can delay the ack if - * - delayed acks are enabled and * - there is no delayed ack timer in progress and * - our last ack wasn't a 0-sized window. We never want to delay - * the ack that opens up a 0-sized window. + * the ack that opens up a 0-sized window and + * - delayed acks are enabled or + * - this is a half-synchronized T/TCP connection. */ -#define DELAY_ACK(tp) \ - (tcp_delack_enabled && !callout_pending(tp->tt_delack) && \ - (tp->t_flags & TF_RXWIN0SENT) == 0) +#define DELAY_ACK(tp) \ + (((!callout_active(tp->tt_delack) && \ + (tp->t_flags & TF_RXWIN0SENT) == 0)) && \ + (tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN))) static int tcp_reass(tp, th, tlenp, m) @@ -505,7 +507,7 @@ tcp_input(m, off0) th->th_urp = ntohs(th->th_urp); /* - * Delay droping TCP, IP headers, IPv6 ext headers, and TCP options, + * Delay dropping TCP, IP headers, IPv6 ext headers, and TCP options, * until after ip6_savecontrol() is called and before other functions * which don't want those proto headers. * Because ip6_savecontrol() is going to parse the mbuf to @@ -862,23 +864,16 @@ findpcb: tp->t_state = TCPS_ESTABLISHED; /* - * If there is a FIN, or if there is data and the - * connection is local, then delay SYN,ACK(SYN) in - * the hope of piggy-backing it on a response - * segment. Otherwise must send ACK now in case - * the other side is slow starting. + * T/TCP logic: + * If there is a FIN or if there is data, then + * delay SYN,ACK(SYN) in the hope of piggy-backing + * it on a response segment. Otherwise must send + * ACK now in case the other side is slow starting. */ - if (DELAY_ACK(tp) && - ((thflags & TH_FIN) || - (tlen != 0 && - ((isipv6 && in6_localaddr(&inp->in6p_faddr)) || - (!isipv6 && in_localaddr(inp->inp_faddr)))))) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); - tp->t_flags |= TF_NEEDSYN; - } else + if (thflags & TH_FIN || tlen != 0) + tp->t_flags |= (TF_DELACK | TF_NEEDSYN); + else tp->t_flags |= (TF_ACKNOW | TF_NEEDSYN); - tcpstat.tcps_connects++; soisconnected(so); goto trimthenstep6; @@ -1089,8 +1084,7 @@ after_listen: } sorwakeup(so); if (DELAY_ACK(tp)) { - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tp->t_flags |= TF_DELACK; } else { tp->t_flags |= TF_ACKNOW; tcp_output(tp); @@ -2099,8 +2093,7 @@ dodata: /* XXX */ LIST_EMPTY(&tp->t_segq) && TCPS_HAVEESTABLISHED(tp->t_state)) { if (DELAY_ACK(tp)) - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + tp->t_flags |= TF_DELACK; else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt += tlen; @@ -2143,9 +2136,8 @@ dodata: /* XXX */ * Otherwise, since we received a FIN then no * more input can be expected, send ACK now. */ - if (DELAY_ACK(tp) && (tp->t_flags & TF_NEEDSYN)) - callout_reset(tp->tt_delack, tcp_delacktime, - tcp_timer_delack, tp); + if (tp->t_flags & TF_NEEDSYN) + tp->t_flags |= TF_DELACK; else tp->t_flags |= TF_ACKNOW; tp->rcv_nxt++; @@ -2214,6 +2206,13 @@ dodata: /* XXX */ */ if (needoutput || (tp->t_flags & TF_ACKNOW)) (void) tcp_output(tp); + else if (tp->t_flags & TF_DELACK) { + tp->t_flags &= ~TF_DELACK; + KASSERT(!callout_active(tp->tt_delack), + ("delayed ack already active")); + callout_reset(tp->tt_delack, tcp_delacktime, + tcp_timer_delack, tp); + } INP_UNLOCK(inp); return; |