|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: * ! 6: * @(#)tcp_output.c 7.2 (Berkeley) 8/20/86 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "mbuf.h" ! 12: #include "protosw.h" ! 13: #include "socket.h" ! 14: #include "socketvar.h" ! 15: #include "errno.h" ! 16: ! 17: #include "../net/route.h" ! 18: ! 19: #include "in.h" ! 20: #include "in_pcb.h" ! 21: #include "in_systm.h" ! 22: #include "ip.h" ! 23: #include "ip_var.h" ! 24: #include "tcp.h" ! 25: #define TCPOUTFLAGS ! 26: #include "tcp_fsm.h" ! 27: #include "tcp_seq.h" ! 28: #include "tcp_timer.h" ! 29: #include "tcp_var.h" ! 30: #include "tcpip.h" ! 31: #include "tcp_debug.h" ! 32: ! 33: /* ! 34: * Initial options. ! 35: */ ! 36: u_char tcp_initopt[4] = { TCPOPT_MAXSEG, 4, 0x0, 0x0, }; ! 37: ! 38: /* ! 39: * Tcp output routine: figure out what should be sent and send it. ! 40: */ ! 41: tcp_output(tp) ! 42: register struct tcpcb *tp; ! 43: { ! 44: register struct socket *so = tp->t_inpcb->inp_socket; ! 45: register int len, win; ! 46: struct mbuf *m0; ! 47: int off, flags, error; ! 48: register struct mbuf *m; ! 49: register struct tcpiphdr *ti; ! 50: u_char *opt; ! 51: unsigned optlen = 0; ! 52: int idle, sendalot; ! 53: ! 54: /* ! 55: * Determine length of data that should be transmitted, ! 56: * and flags that will be used. ! 57: * If there is some data or critical controls (SYN, RST) ! 58: * to send, then transmit; otherwise, investigate further. ! 59: */ ! 60: idle = (tp->snd_max == tp->snd_una); ! 61: again: ! 62: sendalot = 0; ! 63: off = tp->snd_nxt - tp->snd_una; ! 64: win = MIN(tp->snd_wnd, tp->snd_cwnd); ! 65: ! 66: /* ! 67: * If in persist timeout with window of 0, send 1 byte. ! 68: * Otherwise, if window is small but nonzero ! 69: * and timer expired, we will send what we can ! 70: * and go to transmit state. ! 71: */ ! 72: if (tp->t_force) { ! 73: if (win == 0) ! 74: win = 1; ! 75: else { ! 76: tp->t_timer[TCPT_PERSIST] = 0; ! 77: tp->t_rxtshift = 0; ! 78: } ! 79: } ! 80: ! 81: len = MIN(so->so_snd.sb_cc, win) - off; ! 82: flags = tcp_outflags[tp->t_state]; ! 83: ! 84: if (len < 0) { ! 85: /* ! 86: * If FIN has been sent but not acked, ! 87: * but we haven't been called to retransmit, ! 88: * len will be -1; transmit if acking, otherwise no need. ! 89: * Otherwise, window shrank after we sent into it. ! 90: * If window shrank to 0, cancel pending retransmit ! 91: * and pull snd_nxt back to (closed) window. ! 92: * We will enter persist state below. ! 93: * If the window didn't close completely, ! 94: * just wait for an ACK. ! 95: */ ! 96: if (flags & TH_FIN) { ! 97: if (tp->t_flags & TF_ACKNOW) ! 98: len = 0; ! 99: else ! 100: return (0); ! 101: } else if (win == 0) { ! 102: tp->t_timer[TCPT_REXMT] = 0; ! 103: tp->snd_nxt = tp->snd_una; ! 104: len = 0; ! 105: } else ! 106: return (0); ! 107: } ! 108: if (len > tp->t_maxseg) { ! 109: len = tp->t_maxseg; ! 110: /* ! 111: * Don't send more than one segment if retransmitting ! 112: * (or persisting, but then we shouldn't be here). ! 113: */ ! 114: if (tp->t_rxtshift == 0) ! 115: sendalot = 1; ! 116: } ! 117: if (SEQ_LT(tp->snd_nxt + len, tp->snd_una + so->so_snd.sb_cc)) ! 118: flags &= ~TH_FIN; ! 119: win = sbspace(&so->so_rcv); ! 120: ! 121: ! 122: /* ! 123: * If our state indicates that FIN should be sent ! 124: * and we have not yet done so, or we're retransmitting the FIN, ! 125: * then we need to send. ! 126: */ ! 127: if (flags & TH_FIN && ! 128: ((tp->t_flags & TF_SENTFIN) == 0 || tp->snd_nxt == tp->snd_una)) ! 129: goto send; ! 130: /* ! 131: * Send if we owe peer an ACK. ! 132: */ ! 133: if (tp->t_flags & TF_ACKNOW) ! 134: goto send; ! 135: if (flags & (TH_SYN|TH_RST)) ! 136: goto send; ! 137: if (SEQ_GT(tp->snd_up, tp->snd_una)) ! 138: goto send; ! 139: ! 140: /* ! 141: * Sender silly window avoidance. If connection is idle ! 142: * and can send all data, a maximum segment, ! 143: * at least a maximum default-size segment do it, ! 144: * or are forced, do it; otherwise don't bother. ! 145: * If peer's buffer is tiny, then send ! 146: * when window is at least half open. ! 147: * If retransmitting (possibly after persist timer forced us ! 148: * to send into a small window), then must resend. ! 149: */ ! 150: if (len) { ! 151: if (len == tp->t_maxseg || len >= TCP_MSS) /* a lot */ ! 152: goto send; ! 153: if ((idle || tp->t_flags & TF_NODELAY) && ! 154: len + off >= so->so_snd.sb_cc) ! 155: goto send; ! 156: if (tp->t_force) ! 157: goto send; ! 158: if (len >= tp->max_sndwnd / 2) ! 159: goto send; ! 160: if (SEQ_LT(tp->snd_nxt, tp->snd_max)) ! 161: goto send; ! 162: } ! 163: ! 164: /* ! 165: * Compare available window to amount of window ! 166: * known to peer (as advertised window less ! 167: * next expected input.) If the difference is 35% or more of the ! 168: * maximum possible window, then want to send a window update to peer. ! 169: */ ! 170: if (win > 0 && ! 171: ((100*(win-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35)) ! 172: goto send; ! 173: ! 174: /* ! 175: * TCP window updates are not reliable, rather a polling protocol ! 176: * using ``persist'' packets is used to insure receipt of window ! 177: * updates. The three ``states'' for the output side are: ! 178: * idle not doing retransmits or persists ! 179: * persisting to move a small or zero window ! 180: * (re)transmitting and thereby not persisting ! 181: * ! 182: * tp->t_timer[TCPT_PERSIST] ! 183: * is set when we are in persist state. ! 184: * tp->t_force ! 185: * is set when we are called to send a persist packet. ! 186: * tp->t_timer[TCPT_REXMT] ! 187: * is set when we are retransmitting ! 188: * The output side is idle when both timers are zero. ! 189: * ! 190: * If send window is too small, there is data to transmit, and no ! 191: * retransmit or persist is pending, then go to persist state. ! 192: * If nothing happens soon, send when timer expires: ! 193: * if window is nonzero, transmit what we can, ! 194: * otherwise force out a byte. ! 195: */ ! 196: if (so->so_snd.sb_cc && tp->t_timer[TCPT_REXMT] == 0 && ! 197: tp->t_timer[TCPT_PERSIST] == 0) { ! 198: tp->t_rxtshift = 0; ! 199: tcp_setpersist(tp); ! 200: } ! 201: ! 202: /* ! 203: * No reason to send a segment, just return. ! 204: */ ! 205: return (0); ! 206: ! 207: send: ! 208: /* ! 209: * Grab a header mbuf, attaching a copy of data to ! 210: * be transmitted, and initialize the header from ! 211: * the template for sends on this connection. ! 212: */ ! 213: MGET(m, M_DONTWAIT, MT_HEADER); ! 214: if (m == NULL) ! 215: return (ENOBUFS); ! 216: m->m_off = MMAXOFF - sizeof (struct tcpiphdr); ! 217: m->m_len = sizeof (struct tcpiphdr); ! 218: if (len) { ! 219: m->m_next = m_copy(so->so_snd.sb_mb, off, len); ! 220: if (m->m_next == 0) ! 221: len = 0; ! 222: } ! 223: ti = mtod(m, struct tcpiphdr *); ! 224: if (tp->t_template == 0) ! 225: panic("tcp_output"); ! 226: bcopy((caddr_t)tp->t_template, (caddr_t)ti, sizeof (struct tcpiphdr)); ! 227: ! 228: /* ! 229: * Fill in fields, remembering maximum advertised ! 230: * window for use in delaying messages about window sizes. ! 231: * If resending a FIN, be sure not to use a new sequence number. ! 232: */ ! 233: if (flags & TH_FIN && tp->t_flags & TF_SENTFIN && ! 234: tp->snd_nxt != tp->snd_una) ! 235: tp->snd_nxt--; ! 236: ti->ti_seq = htonl(tp->snd_nxt); ! 237: ti->ti_ack = htonl(tp->rcv_nxt); ! 238: /* ! 239: * Before ESTABLISHED, force sending of initial options ! 240: * unless TCP set to not do any options. ! 241: */ ! 242: opt = NULL; ! 243: if (tp->t_state < TCPS_ESTABLISHED && (tp->t_flags & TF_NOOPT) == 0) { ! 244: u_short mss; ! 245: ! 246: mss = MIN(so->so_rcv.sb_hiwat / 2, tcp_mss(tp)); ! 247: if (mss > IP_MSS - sizeof(struct tcpiphdr)) { ! 248: opt = tcp_initopt; ! 249: optlen = sizeof (tcp_initopt); ! 250: *(u_short *)(opt + 2) = htons(mss); ! 251: } ! 252: } else if (tp->t_tcpopt) { ! 253: opt = mtod(tp->t_tcpopt, u_char *); ! 254: optlen = tp->t_tcpopt->m_len; ! 255: } ! 256: if (opt) { ! 257: m0 = m->m_next; ! 258: m->m_next = m_get(M_DONTWAIT, MT_DATA); ! 259: if (m->m_next == 0) { ! 260: (void) m_free(m); ! 261: m_freem(m0); ! 262: return (ENOBUFS); ! 263: } ! 264: m->m_next->m_next = m0; ! 265: m0 = m->m_next; ! 266: m0->m_len = optlen; ! 267: bcopy((caddr_t)opt, mtod(m0, caddr_t), optlen); ! 268: opt = (u_char *)(mtod(m0, caddr_t) + optlen); ! 269: while (m0->m_len & 0x3) { ! 270: *opt++ = TCPOPT_EOL; ! 271: m0->m_len++; ! 272: } ! 273: optlen = m0->m_len; ! 274: ti->ti_off = (sizeof (struct tcphdr) + optlen) >> 2; ! 275: } ! 276: ti->ti_flags = flags; ! 277: /* ! 278: * Calculate receive window. Don't shrink window, ! 279: * but avoid silly window syndrome. ! 280: */ ! 281: if (win < so->so_rcv.sb_hiwat / 4 && win < tp->t_maxseg) ! 282: win = 0; ! 283: if (win < (int)(tp->rcv_adv - tp->rcv_nxt)) ! 284: win = (int)(tp->rcv_adv - tp->rcv_nxt); ! 285: ti->ti_win = htons((u_short)win); ! 286: if (SEQ_GT(tp->snd_up, tp->snd_nxt)) { ! 287: ti->ti_urp = htons((u_short)(tp->snd_up - tp->snd_nxt)); ! 288: ti->ti_flags |= TH_URG; ! 289: } else ! 290: /* ! 291: * If no urgent pointer to send, then we pull ! 292: * the urgent pointer to the left edge of the send window ! 293: * so that it doesn't drift into the send window on sequence ! 294: * number wraparound. ! 295: */ ! 296: tp->snd_up = tp->snd_una; /* drag it along */ ! 297: /* ! 298: * If anything to send and we can send it all, set PUSH. ! 299: * (This will keep happy those implementations which only ! 300: * give data to the user when a buffer fills or a PUSH comes in.) ! 301: */ ! 302: if (len && off+len == so->so_snd.sb_cc) ! 303: ti->ti_flags |= TH_PUSH; ! 304: ! 305: /* ! 306: * Put TCP length in extended header, and then ! 307: * checksum extended header and data. ! 308: */ ! 309: if (len + optlen) ! 310: ti->ti_len = htons((u_short)(sizeof(struct tcphdr) + ! 311: optlen + len)); ! 312: ti->ti_sum = in_cksum(m, sizeof (struct tcpiphdr) + (int)optlen + len); ! 313: ! 314: /* ! 315: * In transmit state, time the transmission and arrange for ! 316: * the retransmit. In persist state, just set snd_max. ! 317: */ ! 318: if (tp->t_force == 0 || tp->t_timer[TCPT_PERSIST] == 0) { ! 319: /* ! 320: * Advance snd_nxt over sequence space of this segment. ! 321: */ ! 322: if (flags & TH_SYN) ! 323: tp->snd_nxt++; ! 324: if (flags & TH_FIN) { ! 325: tp->snd_nxt++; ! 326: tp->t_flags |= TF_SENTFIN; ! 327: } ! 328: tp->snd_nxt += len; ! 329: if (SEQ_GT(tp->snd_nxt, tp->snd_max)) { ! 330: tp->snd_max = tp->snd_nxt; ! 331: /* ! 332: * Time this transmission if not a retransmission and ! 333: * not currently timing anything. ! 334: */ ! 335: if (tp->t_rtt == 0) { ! 336: tp->t_rtt = 1; ! 337: tp->t_rtseq = tp->snd_nxt - len; ! 338: } ! 339: } ! 340: ! 341: /* ! 342: * Set retransmit timer if not currently set, ! 343: * and not doing an ack or a keep-alive probe. ! 344: * Initial value for retransmit timer is tcp_beta*tp->t_srtt. ! 345: * Initialize shift counter which is used for backoff ! 346: * of retransmit time. ! 347: */ ! 348: if (tp->t_timer[TCPT_REXMT] == 0 && ! 349: tp->snd_nxt != tp->snd_una) { ! 350: TCPT_RANGESET(tp->t_timer[TCPT_REXMT], ! 351: tcp_beta * (tp->t_srtt ? tp->t_srtt : TCPTV_SRTTDFLT), ! 352: TCPTV_MIN, TCPTV_MAX); ! 353: tp->t_rxtshift = 0; ! 354: tp->t_timer[TCPT_PERSIST] = 0; ! 355: } ! 356: } else ! 357: if (SEQ_GT(tp->snd_nxt + len, tp->snd_max)) ! 358: tp->snd_max = tp->snd_nxt + len; ! 359: ! 360: /* ! 361: * Trace. ! 362: */ ! 363: if (so->so_options & SO_DEBUG) ! 364: tcp_trace(TA_OUTPUT, tp->t_state, tp, ti, 0); ! 365: ! 366: /* ! 367: * Fill in IP length and desired time to live and ! 368: * send to IP level. ! 369: */ ! 370: ((struct ip *)ti)->ip_len = sizeof (struct tcpiphdr) + optlen + len; ! 371: ((struct ip *)ti)->ip_ttl = TCP_TTL; ! 372: error = ip_output(m, tp->t_inpcb->inp_options, &tp->t_inpcb->inp_route, ! 373: so->so_options & SO_DONTROUTE); ! 374: if (error) ! 375: return (error); ! 376: ! 377: /* ! 378: * Data sent (as far as we can tell). ! 379: * If this advertises a larger window than any other segment, ! 380: * then remember the size of the advertised window. ! 381: * Any pending ACK has now been sent. ! 382: */ ! 383: if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv)) ! 384: tp->rcv_adv = tp->rcv_nxt + win; ! 385: tp->t_flags &= ~(TF_ACKNOW|TF_DELACK); ! 386: if (sendalot) ! 387: goto again; ! 388: return (0); ! 389: } ! 390: ! 391: tcp_setpersist(tp) ! 392: register struct tcpcb *tp; ! 393: { ! 394: ! 395: if (tp->t_timer[TCPT_REXMT]) ! 396: panic("tcp_output REXMT"); ! 397: /* ! 398: * Start/restart persistance timer. ! 399: */ ! 400: TCPT_RANGESET(tp->t_timer[TCPT_PERSIST], ! 401: ((int)(tcp_beta * tp->t_srtt)) << tp->t_rxtshift, ! 402: TCPTV_PERSMIN, TCPTV_MAX); ! 403: tp->t_rxtshift++; ! 404: if (tp->t_rxtshift >= TCP_MAXRXTSHIFT) ! 405: tp->t_rxtshift = 0; ! 406: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.