|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988, 1990 Regents of the University of California. ! 3: * 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 ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 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 7.22 (Berkeley) 8/31/90 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "malloc.h" ! 39: #include "mbuf.h" ! 40: #include "protosw.h" ! 41: #include "socket.h" ! 42: #include "socketvar.h" ! 43: #include "errno.h" ! 44: ! 45: #include "../net/route.h" ! 46: ! 47: #include "in.h" ! 48: #include "in_systm.h" ! 49: #include "ip.h" ! 50: #include "in_pcb.h" ! 51: #include "ip_var.h" ! 52: #include "tcp.h" ! 53: #define TCPOUTFLAGS ! 54: #include "tcp_fsm.h" ! 55: #include "tcp_seq.h" ! 56: #include "tcp_timer.h" ! 57: #include "tcp_var.h" ! 58: #include "tcpip.h" ! 59: #include "tcp_debug.h" ! 60: ! 61: #ifdef notyet ! 62: extern struct mbuf *m_copypack(); ! 63: #endif ! 64: ! 65: /* ! 66: * Initial options. ! 67: */ ! 68: u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; ! 69: ! 70: /* ! 71: * Tcp output routine: figure out what should be sent and send it. ! 72: */ ! 73: tcp_output(tp) ! 74: register struct tcpcb *tp; ! 75: { ! 76: register struct socket *so = tp->t_inpcb->inp_socket; ! 77: register long len, win; ! 78: int off, flags, error; ! 79: register struct mbuf *m; ! 80: register struct tcpiphdr *ti; ! 81: u_char *opt; ! 82: unsigned optlen, hdrlen; ! 83: int idle, sendalot; ! 84: ! 85: /* ! 86: * Determine length of data that should be transmitted, ! 87: * and flags that will be used. ! 88: * If there is some data or critical controls (SYN, RST) ! 89: * to send, then transmit; otherwise, investigate further. ! 90: */ ! 91: idle = (tp->snd_max == tp->snd_una); ! 92: if (idle && tp->t_idle >= tp->t_rxtcur) ! 93: /* ! 94: * We have been idle for "a while" and no acks are ! 95: * expected to clock out any data we send -- ! 96: * slow start to get ack "clock" running again. ! 97: */ ! 98: tp->snd_cwnd = tp->t_maxseg; ! 99: again: ! 100: sendalot = 0; ! 101: off = tp->snd_nxt - tp->snd_una; ! 102: win = min(tp->snd_wnd, tp->snd_cwnd); ! 103: ! 104: /* ! 105: * If in persist timeout with window of 0, send 1 byte. ! 106: * Otherwise, if window is small but nonzero ! 107: * and timer expired, we will send what we can ! 108: * and go to transmit state. ! 109: */ ! 110: if (tp->t_force) { ! 111: if (win == 0) ! 112: win = 1; ! 113: else { ! 114: tp->t_timer[TCPT_PERSIST] = 0; ! 115: tp->t_rxtshift = 0; ! 116: } ! 117: } ! 118: ! 119: flags = tcp_outflags[tp->t_state]; ! 120: len = min(so->so_snd.sb_cc, win) - off; ! 121: ! 122: if (len < 0) { ! 123: /* ! 124: * If FIN has been sent but not acked, ! 125: * but we haven't been called to retransmit, ! 126: * len will be -1. Otherwise, window shrank ! 127: * after we sent into it. If window shrank to 0, ! 128: * cancel pending retransmit and pull snd_nxt ! 129: * back to (closed) window. We will enter persist ! 130: * state below. If the window didn't close completely, ! 131: * just wait for an ACK. ! 132: */ ! 133: len = 0; ! 134: if (win == 0) { ! 135: tp->t_timer[TCPT_REXMT] = 0; ! 136: tp->snd_nxt = tp->snd_una; ! 137: } ! 138: } ! 139: if (len > tp->t_maxseg) { ! 140: len = tp->t_maxseg; ! 141: sendalot = 1; ! 142: } ! 143: if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) ! 144: flags &= ~TH_FIN; ! 145: ! 146: win = sbspace(&so->so_rcv); ! 147: ! 148: /* ! 149: * Sender silly window avoidance. If connection is idle ! 150: * and can send all data, a maximum segment, ! 151: * at least a maximum default-size segment do it, ! 152: * or are forced, do it; otherwise don't bother. ! 153: * If peer's buffer is tiny, then send ! 154: * when window is at least half open. ! 155: * If retransmitting (possibly after persist timer forced us ! 156: * to send into a small window), then must resend. ! 157: */ ! 158: if (len) { ! 159: if (len == tp->t_maxseg) ! 160: goto send; ! 161: if ((idle || tp->t_flags & TF_NODELAY) && ! 162: len + off >= so->so_snd.sb_cc) ! 163: goto send; ! 164: if (tp->t_force) ! 165: goto send; ! 166: if (len >= tp->max_sndwnd / 2) ! 167: goto send; ! 168: if (SEQ_LT(tp->snd_nxt, tp->snd_max)) ! 169: goto send; ! 170: } ! 171: ! 172: /* ! 173: * Compare available window to amount of window ! 174: * known to peer (as advertised window less ! 175: * next expected input). If the difference is at least two ! 176: * max size segments, or at least 50% of the maximum possible ! 177: * window, then want to send a window update to peer. ! 178: */ ! 179: if (win > 0) { ! 180: long adv = win - (tp->rcv_adv - tp->rcv_nxt); ! 181: ! 182: if (adv >= (long) (2 * tp->t_maxseg)) ! 183: goto send; ! 184: if (2 * adv >= (long) so->so_rcv.sb_hiwat) ! 185: goto send; ! 186: } ! 187: ! 188: /* ! 189: * Send if we owe peer an ACK. ! 190: */ ! 191: if (tp->t_flags & TF_ACKNOW) ! 192: goto send; ! 193: if (flags & (TH_SYN|TH_RST)) ! 194: goto send; ! 195: if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 196: goto send; ! 197: /* ! 198: * If our state indicates that FIN should be sent ! 199: * and we have not yet done so, or we're retransmitting the FIN, ! 200: * then we need to send. ! 201: */ ! 202: if (flags & TH_FIN && ! 203: ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) ! 204: goto send; ! 205: ! 206: /* ! 207: * TCP window updates are not reliable, rather a polling protocol ! 208: * using ``persist'' packets is used to insure receipt of window ! 209: * updates. The three ``states'' for the output side are: ! 210: * idle not doing retransmits or persists ! 211: * persisting to move a small or zero window ! 212: * (re)transmitting and thereby not persisting ! 213: * ! 214: * tp->t_timer[TCPT_PERSIST] ! 215: * is set when we are in persist state. ! 216: * tp->t_force ! 217: * is set when we are called to send a persist packet. ! 218: * tp->t_timer[TCPT_REXMT] ! 219: * is set when we are retransmitting ! 220: * The output side is idle when both timers are zero. ! 221: * ! 222: * If send window is too small, there is data to transmit, and no ! 223: * retransmit or persist is pending, then go to persist state. ! 224: * If nothing happens soon, send when timer expires: ! 225: * if window is nonzero, transmit what we can, ! 226: * otherwise force out a byte. ! 227: */ ! 228: if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && ! 229: tp->t_timer[TCPT_PERSIST] == 0) { ! 230: tp->t_rxtshift = 0; ! 231: tcp_setpersist(tp); ! 232: } ! 233: ! 234: /* ! 235: * No reason to send a segment, just return. ! 236: */ ! 237: return (0); ! 238: ! 239: send: ! 240: /* ! 241: * Before ESTABLISHED, force sending of initial options ! 242: * unless TCP set not to do any options. ! 243: * NOTE: we assume that the IP/TCP header plus TCP options ! 244: * always fit in a single mbuf, leaving room for a maximum ! 245: * link header, i.e. ! 246: * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN ! 247: */ ! 248: optlen = 0; ! 249: hdrlen = sizeof (struct tcpiphdr); ! 250: if (flags & TH_SYN && (tp->t_flags & TF_NOOPT) == 0) { ! 251: opt = tcp_initopt; ! 252: optlen = sizeof (tcp_initopt); ! 253: hdrlen += sizeof (tcp_initopt); ! 254: *(u_short *)(opt + 2) = htons((u_short) tcp_mss(tp, 0)); ! 255: #ifdef DIAGNOSTIC ! 256: if (max_linkhdr + hdrlen > MHLEN) ! 257: panic("tcphdr too big"); ! 258: #endif ! 259: } ! 260: ! 261: /* ! 262: * Grab a header mbuf, attaching a copy of data to ! 263: * be transmitted, and initialize the header from ! 264: * the template for sends on this connection. ! 265: */ ! 266: if (len) { ! 267: if (tp->t_force && len == 1) ! 268: tcpstat.tcps_sndprobe++; ! 269: else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { ! 270: tcpstat.tcps_sndrexmitpack++; ! 271: tcpstat.tcps_sndrexmitbyte += len; ! 272: } else { ! 273: tcpstat.tcps_sndpack++; ! 274: tcpstat.tcps_sndbyte += len; ! 275: } ! 276: #ifdef notyet ! 277: if ((m = m_copypack(so->so_snd.sb_mb, off, ! 278: (int)len, max_linkhdr + hdrlen)) == 0) { ! 279: error = ENOBUFS; ! 280: goto out; ! 281: } ! 282: /* ! 283: * m_copypack left space for our hdr; use it. ! 284: */ ! 285: m->m_len += hdrlen; ! 286: m->m_data -= hdrlen; ! 287: #else ! 288: MGETHDR(m, M_DONTWAIT, MT_HEADER); ! 289: if (m == NULL) { ! 290: error = ENOBUFS; ! 291: goto out; ! 292: } ! 293: m->m_data += max_linkhdr; ! 294: m->m_len = hdrlen; ! 295: if (len <= MHLEN - hdrlen - max_linkhdr) { ! 296: m_copydata(so->so_snd.sb_mb, off, (int) len, ! 297: mtod(m, caddr_t) + hdrlen); ! 298: m->m_len += len; ! 299: } else { ! 300: m->m_next = m_copy(so->so_snd.sb_mb, off, (int) len); ! 301: if (m->m_next == 0) ! 302: len = 0; ! 303: } ! 304: #endif ! 305: /* ! 306: * If we're sending everything we've got, set PUSH. ! 307: * (This will keep happy those implementations which only ! 308: * give data to the user when a buffer fills or ! 309: * a PUSH comes in.) ! 310: */ ! 311: if (off + len == so->so_snd.sb_cc) ! 312: flags |= TH_PUSH; ! 313: } else { ! 314: if (tp->t_flags & TF_ACKNOW) ! 315: tcpstat.tcps_sndacks++; ! 316: else if (flags & (TH_SYN|TH_FIN|TH_RST)) ! 317: tcpstat.tcps_sndctrl++; ! 318: else if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 319: tcpstat.tcps_sndurg++; ! 320: else ! 321: tcpstat.tcps_sndwinup++; ! 322: ! 323: MGETHDR(m, M_DONTWAIT, MT_HEADER); ! 324: if (m == NULL) { ! 325: error = ENOBUFS; ! 326: goto out; ! 327: } ! 328: m->m_data += max_linkhdr; ! 329: m->m_len = hdrlen; ! 330: } ! 331: m->m_pkthdr.rcvif = (struct ifnet *)0; ! 332: ti = mtod(m, struct tcpiphdr *); ! 333: if (tp->t_template == 0) ! 334: panic("tcp_output"); ! 335: bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); ! 336: ! 337: /* ! 338: * Fill in fields, remembering maximum advertised ! 339: * window for use in delaying messages about window sizes. ! 340: * If resending a FIN, be sure not to use a new sequence number. ! 341: */ ! 342: if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && ! 343: tp->snd_nxt == tp->snd_max) ! 344: tp->snd_nxt--; ! 345: ti->ti_seq = htonl(tp->snd_nxt); ! 346: ti->ti_ack = htonl(tp->rcv_nxt); ! 347: if (optlen) { ! 348: bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen); ! 349: ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; ! 350: } ! 351: ti->ti_flags = flags; ! 352: /* ! 353: * Calculate receive window. Don't shrink window, ! 354: * but avoid silly window syndrome. ! 355: */ ! 356: if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) ! 357: win = 0; ! 358: if (win > TCP_MAXWIN) ! 359: win = TCP_MAXWIN; ! 360: if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) ! 361: win = (long)(tp->rcv_adv - tp->rcv_nxt); ! 362: ti->ti_win = htons((u_short)win); ! 363: if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ! 364: ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); ! 365: ti->ti_flags |= TH_URG; ! 366: } else ! 367: /* ! 368: * If no urgent pointer to send, then we pull ! 369: * the urgent pointer to the left edge of the send window ! 370: * so that it doesn't drift into the send window on sequence ! 371: * number wraparound. ! 372: */ ! 373: tp->snd_up = tp->snd_una; /* drag it along */ ! 374: ! 375: /* ! 376: * Put TCP length in extended header, and then ! 377: * checksum extended header and data. ! 378: */ ! 379: if (len + optlen) ! 380: ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + ! 381: optlen + len)); ! 382: ti->ti_sum = in_cksum(m, (int)(hdrlen + len)); ! 383: ! 384: /* ! 385: * In transmit state, time the transmission and arrange for ! 386: * the retransmit. In persist state, just set snd_max. ! 387: */ ! 388: if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { ! 389: tcp_seq startseq = tp->snd_nxt; ! 390: ! 391: /* ! 392: * Advance snd_nxt over sequence space of this segment. ! 393: */ ! 394: if (flags & (TH_SYN|TH_FIN)) { ! 395: if (flags & TH_SYN) ! 396: tp->snd_nxt++; ! 397: if (flags & TH_FIN) { ! 398: tp->snd_nxt++; ! 399: tp->t_flags |= TF_SENTFIN; ! 400: } ! 401: } ! 402: tp->snd_nxt += len; ! 403: if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { ! 404: tp->snd_max = tp->snd_nxt; ! 405: /* ! 406: * Time this transmission if not a retransmission and ! 407: * not currently timing anything. ! 408: */ ! 409: if (tp->t_rtt == 0) { ! 410: tp->t_rtt = 1; ! 411: tp->t_rtseq = startseq; ! 412: tcpstat.tcps_segstimed++; ! 413: } ! 414: } ! 415: ! 416: /* ! 417: * Set retransmit timer if not currently set, ! 418: * and not doing an ack or a keep-alive probe. ! 419: * Initial value for retransmit timer is smoothed ! 420: * round-trip time + 2 * round-trip time variance. ! 421: * Initialize shift counter which is used for backoff ! 422: * of retransmit time. ! 423: */ ! 424: if (tp->t_timer[TCPT_REXMT] == 0 && ! 425: tp->snd_nxt != tp->snd_una) { ! 426: tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; ! 427: if (tp->t_timer[TCPT_PERSIST]) { ! 428: tp->t_timer[TCPT_PERSIST] = 0; ! 429: tp->t_rxtshift = 0; ! 430: } ! 431: } ! 432: } else ! 433: if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) ! 434: tp->snd_max = tp->snd_nxt + len; ! 435: ! 436: /* ! 437: * Trace. ! 438: */ ! 439: if (so->so_options & SO_DEBUG) ! 440: tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); ! 441: ! 442: /* ! 443: * Fill in IP length and desired time to live and ! 444: * send to IP level. There should be a better way ! 445: * to handle ttl and tos; we could keep them in ! 446: * the template, but need a way to checksum without them. ! 447: */ ! 448: m->m_pkthdr.len = hdrlen + len; ! 449: ((struct ip *)ti)->ip_len = m->m_pkthdr.len; ! 450: ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */ ! 451: ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */ ! 452: #if BSD >= 43 ! 453: error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, ! 454: so->so_options & SO_DONTROUTE); ! 455: #else ! 456: error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, ! 457: so->so_options & SO_DONTROUTE); ! 458: #endif ! 459: if (error) { ! 460: out: ! 461: if (error == ENOBUFS) { ! 462: tcp_quench(tp->t_inpcb); ! 463: return (0); ! 464: } ! 465: if ((error == EHOSTUNREACH || error == ENETDOWN) ! 466: && TCPS_HAVERCVDSYN(tp->t_state)) { ! 467: tp->t_softerror = error; ! 468: return (0); ! 469: } ! 470: return (error); ! 471: } ! 472: tcpstat.tcps_sndtotal++; ! 473: ! 474: /* ! 475: * Data sent (as far as we can tell). ! 476: * If this advertises a larger window than any other segment, ! 477: * then remember the size of the advertised window. ! 478: * Any pending ACK has now been sent. ! 479: */ ! 480: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) ! 481: tp->rcv_adv = tp->rcv_nxt + win; ! 482: tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); ! 483: if (sendalot) ! 484: goto again; ! 485: return (0); ! 486: } ! 487: ! 488: tcp_setpersist(tp) ! 489: register struct tcpcb *tp; ! 490: { ! 491: register t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; ! 492: ! 493: if (tp->t_timer[TCPT_REXMT]) ! 494: panic("tcp_output REXMT"); ! 495: /* ! 496: * Start/restart persistance timer. ! 497: */ ! 498: TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], ! 499: t * tcp_backoff[tp->t_rxtshift], ! 500: TCPTV_PERSMIN, TCPTV_PERSMAX); ! 501: if (tp->t_rxtshift < TCP_MAXRXTSHIFT) ! 502: tp->t_rxtshift++; ! 503: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.