home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / netinet / tcp_output.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  14.1 KB  |  504 lines

  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. }
  504.