|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)tcp_output.c 8.3 (Berkeley) 12/30/93 ! 59: */ ! 60: ! 61: #include <sys/param.h> ! 62: #include <sys/systm.h> ! 63: #include <sys/malloc.h> ! 64: #include <sys/mbuf.h> ! 65: #include <sys/protosw.h> ! 66: #include <sys/socket.h> ! 67: #include <sys/socketvar.h> ! 68: #include <sys/errno.h> ! 69: ! 70: #include <net/route.h> ! 71: ! 72: #include <netinet/in.h> ! 73: #include <netinet/in_systm.h> ! 74: #include <netinet/ip.h> ! 75: #include <netinet/in_pcb.h> ! 76: #include <netinet/ip_var.h> ! 77: #include <netinet/tcp.h> ! 78: #define TCPOUTFLAGS ! 79: #include <netinet/tcp_fsm.h> ! 80: #include <netinet/tcp_seq.h> ! 81: #include <netinet/tcp_timer.h> ! 82: #include <netinet/tcp_var.h> ! 83: #include <netinet/tcpip.h> ! 84: #include <netinet/tcp_debug.h> ! 85: ! 86: #if NEXT ! 87: #import <kern/kdebug.h> ! 88: ! 89: #if KDEBUG ! 90: ! 91: #define DBG_LAYER_BEG NETDBG_CODE(DBG_NETTCP, 1) ! 92: #define DBG_LAYER_END NETDBG_CODE(DBG_NETTCP, 3) ! 93: #define DBG_FNC_TCP_OUTPUT NETDBG_CODE(DBG_NETTCP, (4 << 8) | 1) ! 94: ! 95: #endif ! 96: ! 97: #endif ! 98: ! 99: #ifdef notyet ! 100: extern struct mbuf *m_copypack(); ! 101: #endif ! 102: ! 103: ! 104: #define MAX_TCPOPTLEN 32 /* max # bytes that go in options */ ! 105: ! 106: /* ! 107: * Tcp output routine: figure out what should be sent and send it. ! 108: */ ! 109: int ! 110: tcp_output(tp) ! 111: register struct tcpcb *tp; ! 112: { ! 113: register struct socket *so = tp->t_inpcb->inp_socket; ! 114: register long len, win; ! 115: int off, flags, error; ! 116: register struct mbuf *m; ! 117: register struct tcpiphdr *ti; ! 118: u_char opt[MAX_TCPOPTLEN]; ! 119: unsigned optlen, hdrlen; ! 120: int idle, sendalot; ! 121: ! 122: ! 123: ! 124: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_START, 0,0,0,0,0); ! 125: KERNEL_DEBUG(DBG_LAYER_BEG, ! 126: ((tp->t_template->ti_dport << 16) | tp->t_template->ti_sport), ! 127: (((tp->t_template->ti_src.s_addr & 0xffff) << 16) | ! 128: (tp->t_template->ti_dst.s_addr & 0xffff)), ! 129: 0,0,0); ! 130: ! 131: /* ! 132: * Determine length of data that should be transmitted, ! 133: * and flags that will be used. ! 134: * If there is some data or critical controls (SYN, RST) ! 135: * to send, then transmit; otherwise, investigate further. ! 136: */ ! 137: idle = (tp->snd_max == tp->snd_una); ! 138: if (idle && tp->t_idle >= tp->t_rxtcur) ! 139: /* ! 140: * We have been idle for "a while" and no acks are ! 141: * expected to clock out any data we send -- ! 142: * slow start to get ack "clock" running again. ! 143: */ ! 144: tp->snd_cwnd = tp->t_maxseg; ! 145: again: ! 146: sendalot = 0; ! 147: off = tp->snd_nxt - tp->snd_una; ! 148: win = min(tp->snd_wnd, tp->snd_cwnd); ! 149: ! 150: flags = tcp_outflags[tp->t_state]; ! 151: /* ! 152: * If in persist timeout with window of 0, send 1 byte. ! 153: * Otherwise, if window is small but nonzero ! 154: * and timer expired, we will send what we can ! 155: * and go to transmit state. ! 156: */ ! 157: if (tp->t_force) { ! 158: if (win == 0) { ! 159: /* ! 160: * If we still have some data to send, then ! 161: * clear the FIN bit. Usually this would ! 162: * happen below when it realizes that we ! 163: * aren't sending all the data. However, ! 164: * if we have exactly 1 byte of unset data, ! 165: * then it won't clear the FIN bit below, ! 166: * and if we are in persist state, we wind ! 167: * up sending the packet without recording ! 168: * that we sent the FIN bit. ! 169: * ! 170: * We can't just blindly clear the FIN bit, ! 171: * because if we don't have any more data ! 172: * to send then the probe will be the FIN ! 173: * itself. ! 174: */ ! 175: if (off < so->so_snd.sb_cc) ! 176: flags &= ~TH_FIN; ! 177: win = 1; ! 178: } else { ! 179: tp->t_timer[TCPT_PERSIST] = 0; ! 180: tp->t_rxtshift = 0; ! 181: } ! 182: } ! 183: ! 184: len = min(so->so_snd.sb_cc, win) - off; ! 185: ! 186: if (len < 0) { ! 187: /* ! 188: * If FIN has been sent but not acked, ! 189: * but we haven't been called to retransmit, ! 190: * len will be -1. Otherwise, window shrank ! 191: * after we sent into it. If window shrank to 0, ! 192: * cancel pending retransmit and pull snd_nxt ! 193: * back to (closed) window. We will enter persist ! 194: * state below. If the window didn't close completely, ! 195: * just wait for an ACK. ! 196: */ ! 197: len = 0; ! 198: if (win == 0) { ! 199: tp->t_timer[TCPT_REXMT] = 0; ! 200: tp->snd_nxt = tp->snd_una; ! 201: } ! 202: } ! 203: if (len > tp->t_maxseg) { ! 204: len = tp->t_maxseg; ! 205: sendalot = 1; ! 206: } ! 207: if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) ! 208: flags &= ~TH_FIN; ! 209: ! 210: win = sbspace(&so->so_rcv); ! 211: ! 212: /* ! 213: * Sender silly window avoidance. If connection is idle ! 214: * and can send all data, a maximum segment, ! 215: * at least a maximum default-size segment do it, ! 216: * or are forced, do it; otherwise don't bother. ! 217: * If peer's buffer is tiny, then send ! 218: * when window is at least half open. ! 219: * If retransmitting (possibly after persist timer forced us ! 220: * to send into a small window), then must resend. ! 221: */ ! 222: if (len) { ! 223: if (len == tp->t_maxseg) ! 224: goto send; ! 225: if (!(so->so_state & SS_MORETOCOME)) { ! 226: if ((idle || tp->t_flags & TF_NODELAY) && ! 227: len + off >= so->so_snd.sb_cc) ! 228: goto send; ! 229: } ! 230: if (tp->t_force) ! 231: goto send; ! 232: if (len >= tp->max_sndwnd / 2) ! 233: goto send; ! 234: if (SEQ_LT(tp->snd_nxt, tp->snd_max)) ! 235: goto send; ! 236: } ! 237: ! 238: /* ! 239: * Compare available window to amount of window ! 240: * known to peer (as advertised window less ! 241: * next expected input). If the difference is at least two ! 242: * max size segments, or at least 50% of the maximum possible ! 243: * window, then want to send a window update to peer. ! 244: */ ! 245: if (win > 0) { ! 246: /* ! 247: * "adv" is the amount we can increase the window, ! 248: * taking into account that we are limited by ! 249: * TCP_MAXWIN << tp->rcv_scale. ! 250: */ ! 251: long adv = min(win, (long)TCP_MAXWIN << tp->rcv_scale) - ! 252: (tp->rcv_adv - tp->rcv_nxt); ! 253: ! 254: if (adv >= (long) (2 * (tp->t_maxseg - MAX_TCPOPTLEN))) ! 255: goto send; ! 256: if (2 * adv >= (long) so->so_rcv.sb_hiwat) ! 257: goto send; ! 258: } ! 259: ! 260: /* ! 261: * Send if we owe peer an ACK. ! 262: */ ! 263: if (tp->t_flags & TF_ACKNOW) ! 264: goto send; ! 265: if (flags & (TH_SYN|TH_RST)) ! 266: goto send; ! 267: if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 268: goto send; ! 269: /* ! 270: * If our state indicates that FIN should be sent ! 271: * and we have not yet done so, or we're retransmitting the FIN, ! 272: * then we need to send. ! 273: */ ! 274: if (flags & TH_FIN && ! 275: ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) ! 276: goto send; ! 277: ! 278: /* ! 279: * TCP window updates are not reliable, rather a polling protocol ! 280: * using ``persist'' packets is used to insure receipt of window ! 281: * updates. The three ``states'' for the output side are: ! 282: * idle not doing retransmits or persists ! 283: * persisting to move a small or zero window ! 284: * (re)transmitting and thereby not persisting ! 285: * ! 286: * tp->t_timer[TCPT_PERSIST] ! 287: * is set when we are in persist state. ! 288: * tp->t_force ! 289: * is set when we are called to send a persist packet. ! 290: * tp->t_timer[TCPT_REXMT] ! 291: * is set when we are retransmitting ! 292: * The output side is idle when both timers are zero. ! 293: * ! 294: * If send window is too small, there is data to transmit, and no ! 295: * retransmit or persist is pending, then go to persist state. ! 296: * If nothing happens soon, send when timer expires: ! 297: * if window is nonzero, transmit what we can, ! 298: * otherwise force out a byte. ! 299: */ ! 300: if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && ! 301: tp->t_timer[TCPT_PERSIST] == 0) { ! 302: tp->t_rxtshift = 0; ! 303: tcp_setpersist(tp); ! 304: } ! 305: ! 306: /* ! 307: * No reason to send a segment, just return. ! 308: */ ! 309: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, 0,0,0,0,0); ! 310: return (0); ! 311: ! 312: send: ! 313: /* ! 314: * Before ESTABLISHED, force sending of initial options ! 315: * unless TCP set not to do any options. ! 316: * NOTE: we assume that the IP/TCP header plus TCP options ! 317: * always fit in a single mbuf, leaving room for a maximum ! 318: * link header, i.e. ! 319: * max_linkhdr + sizeof (struct tcpiphdr) + optlen <= MHLEN ! 320: */ ! 321: optlen = 0; ! 322: hdrlen = sizeof (struct tcpiphdr); ! 323: if (flags & TH_SYN) { ! 324: tp->snd_nxt = tp->iss; ! 325: if ((tp->t_flags & TF_NOOPT) == 0) { ! 326: u_short mss; ! 327: ! 328: opt[0] = TCPOPT_MAXSEG; ! 329: opt[1] = 4; ! 330: mss = htons((u_short) tcp_mss(tp, 0)); ! 331: bcopy((caddr_t)&mss, (caddr_t)(opt + 2), sizeof(mss)); ! 332: optlen = 4; ! 333: ! 334: if ((tp->t_flags & TF_REQ_SCALE) && ! 335: ((flags & TH_ACK) == 0 || ! 336: (tp->t_flags & TF_RCVD_SCALE))) { ! 337: *((u_long *) (opt + optlen)) = htonl( ! 338: TCPOPT_NOP << 24 | ! 339: TCPOPT_WINDOW << 16 | ! 340: TCPOLEN_WINDOW << 8 | ! 341: tp->request_r_scale); ! 342: optlen += 4; ! 343: } ! 344: } ! 345: } ! 346: ! 347: /* ! 348: * Send a timestamp and echo-reply if this is a SYN and our side ! 349: * wants to use timestamps (TF_REQ_TSTMP is set) or both our side ! 350: * and our peer have sent timestamps in our SYN's. ! 351: */ ! 352: if ((tp->t_flags & (TF_REQ_TSTMP|TF_NOOPT)) == TF_REQ_TSTMP && ! 353: (flags & TH_RST) == 0 && ! 354: ((flags & (TH_SYN|TH_ACK)) == TH_SYN || ! 355: (tp->t_flags & TF_RCVD_TSTMP))) { ! 356: u_long *lp = (u_long *)(opt + optlen); ! 357: ! 358: /* Form timestamp option as shown in appendix A of RFC 1323. */ ! 359: *lp++ = htonl(TCPOPT_TSTAMP_HDR); ! 360: *lp++ = htonl(tcp_now); ! 361: *lp = htonl(tp->ts_recent); ! 362: optlen += TCPOLEN_TSTAMP_APPA; ! 363: } ! 364: ! 365: hdrlen += optlen; ! 366: ! 367: /* ! 368: * Adjust data length if insertion of options will ! 369: * bump the packet length beyond the t_maxseg length. ! 370: */ ! 371: if (len > tp->t_maxseg - optlen) { ! 372: len = tp->t_maxseg - optlen; ! 373: sendalot = 1; ! 374: flags &= ~TH_FIN; ! 375: } ! 376: ! 377: #if DIAGNOSTIC ! 378: if (max_linkhdr + hdrlen > MHLEN) ! 379: panic("tcphdr too big"); ! 380: #endif ! 381: ! 382: /* ! 383: * Grab a header mbuf, attaching a copy of data to ! 384: * be transmitted, and initialize the header from ! 385: * the template for sends on this connection. ! 386: */ ! 387: if (len) { ! 388: if (tp->t_force && len == 1) ! 389: tcpstat.tcps_sndprobe++; ! 390: else if (SEQ_LT(tp->snd_nxt, tp->snd_max)) { ! 391: tcpstat.tcps_sndrexmitpack++; ! 392: tcpstat.tcps_sndrexmitbyte += len; ! 393: } else { ! 394: tcpstat.tcps_sndpack++; ! 395: tcpstat.tcps_sndbyte += len; ! 396: } ! 397: #ifdef notyet ! 398: if ((m = m_copypack(so->so_snd.sb_mb, off, ! 399: (int)len, max_linkhdr + hdrlen)) == 0) { ! 400: error = ENOBUFS; ! 401: goto out; ! 402: } ! 403: /* ! 404: * m_copypack left space for our hdr; use it. ! 405: */ ! 406: m->m_len += hdrlen; ! 407: m->m_data -= hdrlen; ! 408: #else ! 409: MGETHDR(m, M_DONTWAIT, MT_HEADER); ! 410: if (m == NULL) { ! 411: error = ENOBUFS; ! 412: goto out; ! 413: } ! 414: m->m_data += max_linkhdr; ! 415: m->m_len = hdrlen; ! 416: if (len <= (MHLEN - hdrlen - max_linkhdr)) { ! 417: register struct mbuf *m1, *m2; ! 418: register char *p; ! 419: register int cur_len, len1; ! 420: register int off1; ! 421: ! 422: p = mtod(m, caddr_t) + hdrlen; ! 423: m1 = so->so_snd.sb_mb; ! 424: off1 = off; ! 425: len1 = len; ! 426: ! 427: for (;;) { ! 428: for (cur_len = 0, m2 = m1; m2; m2 = m2->m_next) ! 429: cur_len += m2->m_len; ! 430: if (off1 < cur_len) { ! 431: cur_len = min(cur_len - off1, len1); ! 432: ! 433: m_copydata(m1, off1, (int) cur_len, p); ! 434: ! 435: if ((len1 -= cur_len) == 0) ! 436: break; ! 437: p += cur_len; ! 438: off1 = 0; ! 439: } else ! 440: off1 -= cur_len; ! 441: ! 442: kprintf("m_copydata: nextpkt path\n"); ! 443: ! 444: if ((m1 = m1->m_nextpkt) == NULL) ! 445: panic("tcp_output: m_copydata"); ! 446: } ! 447: m->m_len += len; ! 448: ! 449: } else { ! 450: register struct mbuf *m1, *m2, *m3; ! 451: register int cur_len, len1; ! 452: register int off1; ! 453: ! 454: m1 = so->so_snd.sb_mb; ! 455: m3 = m; ! 456: off1 = off; ! 457: len1 = len; ! 458: ! 459: for (;;) { ! 460: for (cur_len = 0, m2 = m1; m2; m2 = m2->m_next) ! 461: cur_len += m2->m_len; ! 462: if (off1 < cur_len) { ! 463: cur_len = min(cur_len - off1, len1); ! 464: ! 465: m3->m_next = m_copy(m1, off1, (int) cur_len); ! 466: if (m3->m_next == 0) { ! 467: (void) m_free(m); ! 468: error = ENOBUFS; ! 469: goto out; ! 470: } ! 471: if ((len1 -= cur_len) == 0) ! 472: break; ! 473: for (m3 = m3->m_next; m3->m_next; m3 = m3->m_next); ! 474: ! 475: off1 = 0; ! 476: } else ! 477: off1 -= cur_len; ! 478: ! 479: kprintf("m_copy: nextpkt path\n"); ! 480: ! 481: if ((m1 = m1->m_nextpkt) == NULL) ! 482: panic("tcp_output: m_copy"); ! 483: } ! 484: } ! 485: #endif ! 486: /* ! 487: * If we're sending everything we've got, set PUSH. ! 488: * (This will keep happy those implementations which only ! 489: * give data to the user when a buffer fills or ! 490: * a PUSH comes in.) ! 491: */ ! 492: if (off + len == so->so_snd.sb_cc) ! 493: flags |= TH_PUSH; ! 494: } else { ! 495: if (tp->t_flags & TF_ACKNOW) ! 496: tcpstat.tcps_sndacks++; ! 497: else if (flags & (TH_SYN|TH_FIN|TH_RST)) ! 498: tcpstat.tcps_sndctrl++; ! 499: else if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 500: tcpstat.tcps_sndurg++; ! 501: else ! 502: tcpstat.tcps_sndwinup++; ! 503: ! 504: MGETHDR(m, M_DONTWAIT, MT_HEADER); ! 505: if (m == NULL) { ! 506: error = ENOBUFS; ! 507: goto out; ! 508: } ! 509: m->m_data += max_linkhdr; ! 510: m->m_len = hdrlen; ! 511: } ! 512: m->m_pkthdr.rcvif = (struct ifnet *)0; ! 513: ti = mtod(m, struct tcpiphdr *); ! 514: if (tp->t_template == 0) ! 515: panic("tcp_output"); ! 516: bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); ! 517: ! 518: /* ! 519: * Fill in fields, remembering maximum advertised ! 520: * window for use in delaying messages about window sizes. ! 521: * If resending a FIN, be sure not to use a new sequence number. ! 522: */ ! 523: if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && ! 524: tp->snd_nxt == tp->snd_max) ! 525: tp->snd_nxt--; ! 526: /* ! 527: * If we are doing retransmissions, then snd_nxt will ! 528: * not reflect the first unsent octet. For ACK only ! 529: * packets, we do not want the sequence number of the ! 530: * retransmitted packet, we want the sequence number ! 531: * of the next unsent octet. So, if there is no data ! 532: * (and no SYN or FIN), use snd_max instead of snd_nxt ! 533: * when filling in ti_seq. But if we are in persist ! 534: * state, snd_max might reflect one byte beyond the ! 535: * right edge of the window, so use snd_nxt in that ! 536: * case, since we know we aren't doing a retransmission. ! 537: * (retransmit and persist are mutually exclusive...) ! 538: */ ! 539: if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) ! 540: ti->ti_seq = htonl(tp->snd_nxt); ! 541: else ! 542: ti->ti_seq = htonl(tp->snd_max); ! 543: ti->ti_ack = htonl(tp->rcv_nxt); ! 544: if (optlen) { ! 545: bcopy((caddr_t)opt, (caddr_t)(ti + 1), optlen); ! 546: ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; ! 547: } ! 548: ti->ti_flags = flags; ! 549: /* ! 550: * Calculate receive window. Don't shrink window, ! 551: * but avoid silly window syndrome. ! 552: */ ! 553: if (win < (long)(so->so_rcv.sb_hiwat / 4) && win < (long)tp->t_maxseg) ! 554: win = 0; ! 555: if (win > (long)TCP_MAXWIN << tp->rcv_scale) ! 556: win = (long)TCP_MAXWIN << tp->rcv_scale; ! 557: if (win < (long)(tp->rcv_adv - tp->rcv_nxt)) ! 558: win = (long)(tp->rcv_adv - tp->rcv_nxt); ! 559: ti->ti_win = htons((u_short) (win>>tp->rcv_scale)); ! 560: if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ! 561: ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); ! 562: ti->ti_flags |= TH_URG; ! 563: } else ! 564: /* ! 565: * If no urgent pointer to send, then we pull ! 566: * the urgent pointer to the left edge of the send window ! 567: * so that it doesn't drift into the send window on sequence ! 568: * number wraparound. ! 569: */ ! 570: tp->snd_up = tp->snd_una; /* drag it along */ ! 571: ! 572: /* ! 573: * Put TCP length in extended header, and then ! 574: * checksum extended header and data. ! 575: */ ! 576: if (len + optlen) ! 577: ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + ! 578: optlen + len)); ! 579: ti->ti_sum = in_cksum(m, (int)(hdrlen + len)); ! 580: ! 581: /* ! 582: * In transmit state, time the transmission and arrange for ! 583: * the retransmit. In persist state, just set snd_max. ! 584: */ ! 585: if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { ! 586: tcp_seq startseq = tp->snd_nxt; ! 587: ! 588: /* ! 589: * Advance snd_nxt over sequence space of this segment. ! 590: */ ! 591: if (flags & (TH_SYN|TH_FIN)) { ! 592: if (flags & TH_SYN) ! 593: tp->snd_nxt++; ! 594: if (flags & TH_FIN) { ! 595: tp->snd_nxt++; ! 596: tp->t_flags |= TF_SENTFIN; ! 597: } ! 598: } ! 599: tp->snd_nxt += len; ! 600: if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { ! 601: tp->snd_max = tp->snd_nxt; ! 602: /* ! 603: * Time this transmission if not a retransmission and ! 604: * not currently timing anything. ! 605: */ ! 606: if (tp->t_rtt == 0) { ! 607: tp->t_rtt = 1; ! 608: tp->t_rtseq = startseq; ! 609: tcpstat.tcps_segstimed++; ! 610: } ! 611: } ! 612: ! 613: /* ! 614: * Set retransmit timer if not currently set, ! 615: * and not doing an ack or a keep-alive probe. ! 616: * Initial value for retransmit timer is smoothed ! 617: * round-trip time + 2 * round-trip time variance. ! 618: * Initialize shift counter which is used for backoff ! 619: * of retransmit time. ! 620: */ ! 621: if (tp->t_timer[TCPT_REXMT] == 0 && ! 622: tp->snd_nxt != tp->snd_una) { ! 623: tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; ! 624: if (tp->t_timer[TCPT_PERSIST]) { ! 625: tp->t_timer[TCPT_PERSIST] = 0; ! 626: tp->t_rxtshift = 0; ! 627: } ! 628: } ! 629: } else ! 630: if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) ! 631: tp->snd_max = tp->snd_nxt + len; ! 632: ! 633: /* ! 634: * Trace. ! 635: */ ! 636: if (so->so_options & SO_DEBUG) ! 637: tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); ! 638: ! 639: /* ! 640: * Fill in IP length and desired time to live and ! 641: * send to IP level. There should be a better way ! 642: * to handle ttl and tos; we could keep them in ! 643: * the template, but need a way to checksum without them. ! 644: */ ! 645: m->m_pkthdr.len = hdrlen + len; ! 646: #if TUBA ! 647: if (tp->t_tuba_pcb) ! 648: error = tuba_output(m, tp); ! 649: else ! 650: #endif ! 651: { ! 652: ((struct ip *)ti)->ip_len = m->m_pkthdr.len; ! 653: ((struct ip *)ti)->ip_ttl = tp->t_inpcb->inp_ip.ip_ttl; /* XXX */ ! 654: ((struct ip *)ti)->ip_tos = tp->t_inpcb->inp_ip.ip_tos; /* XXX */ ! 655: ! 656: KERNEL_DEBUG(DBG_LAYER_END, ((ti->ti_dport << 16) | ti->ti_sport), ! 657: (((ti->ti_src.s_addr & 0xffff) << 16) | (ti->ti_dst.s_addr & 0xffff)), ! 658: ti->ti_seq, ti->ti_ack, ti->ti_win); ! 659: ! 660: #if BSD >= 43 ! 661: error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, ! 662: so->so_options & SO_DONTROUTE, 0); ! 663: #else ! 664: error = ip_output(m, (struct mbuf *)0, &tp->t_inpcb->inp_route, ! 665: so->so_options & SO_DONTROUTE); ! 666: #endif ! 667: } ! 668: if (error) { ! 669: out: ! 670: if (error == ENOBUFS) { ! 671: tcp_quench(tp->t_inpcb, 0); ! 672: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, 0,0,0,0,0); ! 673: return (0); ! 674: } ! 675: if ((error == EHOSTUNREACH || error == ENETDOWN) ! 676: && TCPS_HAVERCVDSYN(tp->t_state)) { ! 677: tp->t_softerror = error; ! 678: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, 0,0,0,0,0); ! 679: return (0); ! 680: } ! 681: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, error,0,0,0,0); ! 682: return (error); ! 683: } ! 684: tcpstat.tcps_sndtotal++; ! 685: ! 686: /* ! 687: * Data sent (as far as we can tell). ! 688: * If this advertises a larger window than any other segment, ! 689: * then remember the size of the advertised window. ! 690: * Any pending ACK has now been sent. ! 691: */ ! 692: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) ! 693: tp->rcv_adv = tp->rcv_nxt + win; ! 694: tp->last_ack_sent = tp->rcv_nxt; ! 695: tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); ! 696: if (sendalot) ! 697: goto again; ! 698: ! 699: KERNEL_DEBUG(DBG_FNC_TCP_OUTPUT | DBG_FUNC_END, 0,0,0,0,0); ! 700: return (0); ! 701: } ! 702: ! 703: void ! 704: tcp_setpersist(tp) ! 705: register struct tcpcb *tp; ! 706: { ! 707: register t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1; ! 708: ! 709: if (tp->t_timer[TCPT_REXMT]) ! 710: panic("tcp_output REXMT"); ! 711: /* ! 712: * Start/restart persistance timer. ! 713: */ ! 714: TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], ! 715: t * tcp_backoff[tp->t_rxtshift], ! 716: TCPTV_PERSMIN, TCPTV_PERSMAX); ! 717: if (tp->t_rxtshift < TCP_MAXRXTSHIFT) ! 718: tp->t_rxtshift++; ! 719: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.