tcp_output.c (87145) | tcp_output.c (87193) |
---|---|
1/* 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95 | 1/* 2 * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 17 unchanged lines hidden (view full) --- 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)tcp_output.c 8.4 (Berkeley) 5/24/95 |
34 * $FreeBSD: head/sys/netinet/tcp_output.c 87145 2001-11-30 21:33:39Z dillon $ | 34 * $FreeBSD: head/sys/netinet/tcp_output.c 87193 2001-12-02 08:49:29Z dillon $ |
35 */ 36 37#include "opt_inet6.h" 38#include "opt_ipsec.h" 39#include "opt_tcpdebug.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> --- 70 unchanged lines hidden (view full) --- 113 register struct ipovly *ipov = NULL; 114#ifdef INET6 115 struct ip6_hdr *ip6 = NULL; 116#endif /* INET6 */ 117 register struct tcphdr *th; 118 u_char opt[TCP_MAXOLEN]; 119 unsigned ipoptlen, optlen, hdrlen; 120 int idle, sendalot; | 35 */ 36 37#include "opt_inet6.h" 38#include "opt_ipsec.h" 39#include "opt_tcpdebug.h" 40 41#include <sys/param.h> 42#include <sys/systm.h> --- 70 unchanged lines hidden (view full) --- 113 register struct ipovly *ipov = NULL; 114#ifdef INET6 115 struct ip6_hdr *ip6 = NULL; 116#endif /* INET6 */ 117 register struct tcphdr *th; 118 u_char opt[TCP_MAXOLEN]; 119 unsigned ipoptlen, optlen, hdrlen; 120 int idle, sendalot; |
121#if 0 |
|
121 int maxburst = TCP_MAXBURST; | 122 int maxburst = TCP_MAXBURST; |
123#endif |
|
122 struct rmxp_tao *taop; 123 struct rmxp_tao tao_noncached; 124#ifdef INET6 125 int isipv6; 126#endif 127 128#ifdef INET6 129 isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0; --- 142 unchanged lines hidden (view full) --- 272 sendalot = 1; 273 } 274 if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) 275 flags &= ~TH_FIN; 276 277 win = sbspace(&so->so_rcv); 278 279 /* | 124 struct rmxp_tao *taop; 125 struct rmxp_tao tao_noncached; 126#ifdef INET6 127 int isipv6; 128#endif 129 130#ifdef INET6 131 isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV6) != 0; --- 142 unchanged lines hidden (view full) --- 274 sendalot = 1; 275 } 276 if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) 277 flags &= ~TH_FIN; 278 279 win = sbspace(&so->so_rcv); 280 281 /* |
280 * Sender silly window avoidance. If connection is idle 281 * and can send all data, a maximum segment, 282 * at least a maximum default-size segment do it, 283 * or are forced, do it; otherwise don't bother. 284 * If peer's buffer is tiny, then send 285 * when window is at least half open. 286 * If retransmitting (possibly after persist timer forced us 287 * to send into a small window), then must resend. | 282 * Sender silly window avoidance. We transmit under the following 283 * conditions when len is non-zero: 284 * 285 * - We have a full segment 286 * - This is the last buffer in a write()/send() and we are 287 * either idle or running NODELAY 288 * - we've timed out (e.g. persist timer) 289 * - we have more then 1/2 the maximum send window's worth of 290 * data (receiver may be limited the window size) 291 * - we need to retransmit |
288 */ 289 if (len) { 290 if (len == tp->t_maxseg) 291 goto send; | 292 */ 293 if (len) { 294 if (len == tp->t_maxseg) 295 goto send; |
292 if (!(tp->t_flags & TF_MORETOCOME) && 293 (idle || tp->t_flags & TF_NODELAY) && 294 (tp->t_flags & TF_NOPUSH) == 0 && 295 len + off >= so->so_snd.sb_cc) | 296 /* 297 * NOTE! on localhost connections an 'ack' from the remote 298 * end may occur synchronously with the output and cause 299 * us to flush a buffer queued with moretocome. XXX 300 * 301 * note: the len + off check is almost certainly unnecessary. 302 */ 303 if (!(tp->t_flags & TF_MORETOCOME) && /* normal case */ 304 (idle || (tp->t_flags & TF_NODELAY)) && 305 len + off >= so->so_snd.sb_cc && 306 (tp->t_flags & TF_NOPUSH) == 0) { |
296 goto send; | 307 goto send; |
297 if (tp->t_force) | 308 } 309 if (tp->t_force) /* typ. timeout case */ |
298 goto send; 299 if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) 300 goto send; | 310 goto send; 311 if (len >= tp->max_sndwnd / 2 && tp->max_sndwnd > 0) 312 goto send; |
301 if (SEQ_LT(tp->snd_nxt, tp->snd_max)) | 313 if (SEQ_LT(tp->snd_nxt, tp->snd_max)) /* retransmit case */ |
302 goto send; 303 } 304 305 /* 306 * Compare available window to amount of window 307 * known to peer (as advertised window less 308 * next expected input). If the difference is at least two 309 * max size segments, or at least 50% of the maximum possible --- 382 unchanged lines hidden (view full) --- 692 */ 693 if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) 694 win = 0; 695 if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) 696 win = (long)(tp->rcv_adv - tp->rcv_nxt); 697 if (win > (long)TCP_MAXWIN << tp->rcv_scale) 698 win = (long)TCP_MAXWIN << tp->rcv_scale; 699 th->th_win = htons((u_short) (win>>tp->rcv_scale)); | 314 goto send; 315 } 316 317 /* 318 * Compare available window to amount of window 319 * known to peer (as advertised window less 320 * next expected input). If the difference is at least two 321 * max size segments, or at least 50% of the maximum possible --- 382 unchanged lines hidden (view full) --- 704 */ 705 if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) 706 win = 0; 707 if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) 708 win = (long)(tp->rcv_adv - tp->rcv_nxt); 709 if (win > (long)TCP_MAXWIN << tp->rcv_scale) 710 win = (long)TCP_MAXWIN << tp->rcv_scale; 711 th->th_win = htons((u_short) (win>>tp->rcv_scale)); |
712 713 714 /* 715 * Adjust the RXWIN0SENT flag - indicate that we have advertised 716 * a 0 window. This may cause the remote transmitter to stall. This 717 * flag tells soreceive() to disable delayed acknowledgements when 718 * draining the buffer. This can occur if the receiver is attempting 719 * to read more data then can be buffered prior to transmitting on 720 * the connection. 721 */ 722 if (win == 0) 723 tp->t_flags |= TF_RXWIN0SENT; 724 else 725 tp->t_flags &= ~TF_RXWIN0SENT; |
|
700 if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { 701 th->th_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); 702 th->th_flags |= TH_URG; 703 } else 704 /* 705 * If no urgent pointer to send, then we pull 706 * the urgent pointer to the left edge of the send window 707 * so that it doesn't drift into the send window on sequence --- 249 unchanged lines hidden --- | 726 if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { 727 th->th_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); 728 th->th_flags |= TH_URG; 729 } else 730 /* 731 * If no urgent pointer to send, then we pull 732 * the urgent pointer to the left edge of the send window 733 * so that it doesn't drift into the send window on sequence --- 249 unchanged lines hidden --- |