listing
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Thu, 26 Nov 1981 08:10:39 +0000 (00:10 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Thu, 26 Nov 1981 08:10:39 +0000 (00:10 -0800)
SCCS-vsn: sys/netinet/tcp_fsm.h 4.8
SCCS-vsn: sys/netinet/tcp_input.c 1.31
SCCS-vsn: sys/netinet/tcp_output.c 4.18
SCCS-vsn: sys/netinet/tcp_subr.c 4.2
SCCS-vsn: sys/netinet/tcp_timer.c 4.2
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.35
SCCS-vsn: sys/netinet/tcp_var.h 4.8

usr/src/sys/netinet/tcp_fsm.h
usr/src/sys/netinet/tcp_input.c
usr/src/sys/netinet/tcp_output.c
usr/src/sys/netinet/tcp_subr.c
usr/src/sys/netinet/tcp_timer.c
usr/src/sys/netinet/tcp_usrreq.c
usr/src/sys/netinet/tcp_var.h

index d87c693..dbf5f90 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_fsm.h       4.7     81/11/24        */
+/*     tcp_fsm.h       4.8     81/11/25        */
 
 /*
  * TCP FSM state definitions.
 
 /*
  * TCP FSM state definitions.
 #define        TCPS_LISTEN             1       /* listening for connection */
 #define        TCPS_SYN_SENT           2       /* active, have sent syn */
 #define        TCPS_SYN_RCVD           3       /* have send and received syn */
 #define        TCPS_LISTEN             1       /* listening for connection */
 #define        TCPS_SYN_SENT           2       /* active, have sent syn */
 #define        TCPS_SYN_RCVD           3       /* have send and received syn */
+/* states < TCPS_ESTABLISHED are those where connections not established */
 #define        TCPS_ESTABLISHED        4       /* established */
 #define        TCPS_ESTABLISHED        4       /* established */
+#define        TCPS_CLOSE_WAIT         8       /* rcvd fin, waiting for close */
+/* states > TCPS_CLOSE_WAIT are those where user has closed */
 #define        TCPS_FIN_WAIT_1         5       /* have closed, sent fin */
 #define        TCPS_FIN_WAIT_2         6       /* have closed, fin is acked */
 #define        TCPS_TIME_WAIT          7       /* in 2*msl quiet wait after close */
 #define        TCPS_FIN_WAIT_1         5       /* have closed, sent fin */
 #define        TCPS_FIN_WAIT_2         6       /* have closed, fin is acked */
 #define        TCPS_TIME_WAIT          7       /* in 2*msl quiet wait after close */
-#define        TCPS_CLOSE_WAIT         8       /* rcvd fin, waiting for close */
 #define        TCPS_CLOSING            9       /* closed xchd FIN; await FIN ACK */
 #define        TCPS_LAST_ACK           10      /* had fin and close; await FIN ACK */
 
 #define        TCPS_CLOSING            9       /* closed xchd FIN; await FIN ACK */
 #define        TCPS_LAST_ACK           10      /* had fin and close; await FIN ACK */
 
index 9fe2f20..91acf5e 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_input.c 1.30 81/11/24 */
+/*     tcp_input.c     1.31    81/11/25        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -412,8 +412,10 @@ step6:
         * therefore can't validate drop the segment.  Otherwise ACK
         * the FIN and let the user know that the connection is closing.
         */
         * therefore can't validate drop the segment.  Otherwise ACK
         * the FIN and let the user know that the connection is closing.
         */
-       if ((tiflags & TH_FIN) && TCPS_HAVERCVDSYN(tp->t_state)) {
-               tcp_usrclosing(tp);
+       if (tiflags & TH_FIN) {
+               if (TCPS_HAVERCVDSYN(tp->t_state) == 0)
+                       goto drop;
+               socantrcvmore(so);
                tp->t_flags |= TF_ACKNOW;
                tp->rcv_nxt++;
                switch (tp->t_state) {
                tp->t_flags |= TF_ACKNOW;
                tp->rcv_nxt++;
                switch (tp->t_state) {
@@ -450,7 +452,7 @@ step6:
                 */
                case TCPS_FIN_WAIT_2:
                        tp->t_state = TCPS_FIN_WAIT_2;
                 */
                case TCPS_FIN_WAIT_2:
                        tp->t_state = TCPS_FIN_WAIT_2;
-                       tcp_canceltimers(tp, 0);
+                       tcp_canceltimers(tp);
                        tp->t_timer[TCPT_FINACK] = TCPSC_2MSL;
                        break;
 
                        tp->t_timer[TCPT_FINACK] = TCPSC_2MSL;
                        break;
 
@@ -562,7 +564,7 @@ tcp_reass(tp, ti, endp)
                        if (q->ti_len)
                                break;
                        if (q == ti)
                        if (q->ti_len)
                                break;
                        if (q == ti)
-                               panic("tcp_text dropall");
+                               panic("tcp_reass dropall");
                        q = (struct tcpiphdr *)q->ti_prev;
                        remque(q->ti_next);
                }
                        q = (struct tcpiphdr *)q->ti_prev;
                        remque(q->ti_next);
                }
@@ -594,7 +596,10 @@ present:
                        panic("tcp_reass");
                ti = (struct tcpiphdr *)ti->ti_next;
        }
                        panic("tcp_reass");
                ti = (struct tcpiphdr *)ti->ti_next;
        }
-       sorwakeup(so);
+       if (so->so_state & SS_CANTRCVMORE)
+               sbflush(&so->so_rcv);
+       else
+               sorwakeup(so);
        return (flags);
 drop:
        m_freem(dtom(ti));
        return (flags);
 drop:
        m_freem(dtom(ti));
index 3199ee8..a3cc817 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_output.c    4.17    81/11/24        */
+/*     tcp_output.c    4.18    81/11/25        */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
 #include "/usr/include/errno.h"
 
 /*
 #include "/usr/include/errno.h"
 
 /*
- * Special routines to send control messages.
+ * Tcp output routine: figure out what should be sent
+ * and, if nothing, send a null segment anyways if force is nonzero
+ * (e.g. to be sure to send an ACK).
+ *
+ * This routine can be called only after SYNs have been exchanged.
  */
  */
-tcp_sndctl(tp)
-       struct tcpcb *tp;
-{
-COUNT(TCP_SNDCTL);
-
-        if (tcp_send(tp))
-               return (1);
-       tcp_sndnull(tp);
-       return (0);
-}
-
-tcp_sndwin(tp)
-       struct tcpcb *tp;
-{
-       int ihave, hehas;
-COUNT(TCP_SNDWIN);
-
-       if (tp->rcv_adv) {
-               register struct socket *so = tp->t_inpcb->inp_socket;
-
-               ihave = so->so_rcv.sb_hiwat -
-                   (so->so_rcv.sb_cc + tp->seqcnt);
-               hehas = tp->rcv_adv - tp->rcv_nxt;
-               if ((100*(ihave-hehas)/so->so_rcv.sb_hiwat) < 35)
-                       return;
-       }
-        if (tcp_send(tp))
-               return;
-       tcp_sndnull(tp);
-}
-
-tcp_sndnull(tp)
+tcp_output(tp)
        register struct tcpcb *tp;
 {
        register struct tcpcb *tp;
 {
-COUNT(TCP_SNDNULL);
-
-       (void) tcp_output(tp, 0, 0, (struct mbuf *)0);
-        tp->tc_flags &= ~TC_ACK_DUE;
-}
-
-/*
- * Tcp segment output routine.
- */
-tcp_send(tp)
-       register struct tcpcb *tp;
-{
-       register unsigned long last, wind;
        register struct socket *so = tp->t_inpcb->inp_socket;
        register struct socket *so = tp->t_inpcb->inp_socket;
-       struct mbuf *m;
-       int flags = 0, forced, sent, len;
+       register int len;
+       struct mbuf *m0;
+       int off, flags;
+       register struct mbuf *m;
+       register struct tcpiphdr *ti;
+       int win;
 
 
-COUNT(TCP_SEND);
-       tp->snd_lst = tp->snd_nxt;
-       forced = 0;
-       m = NULL;
-       if (tp->snd_nxt == tp->iss) {
-               flags |= TH_SYN;
-               tp->snd_lst++;
-       }
-       last = tp->snd_off;
-       for (m = so->so_snd.sb_mb; m != NULL; m = m->m_next)
-               last += m->m_len;
-       if (tp->snd_nxt > last) {
-               if ((tp->tc_flags&TC_SND_FIN) &&
-                   (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) {
+COUNT(TCP_OUTPUT);
 
 
-                       flags |= TH_FIN;
-                       tp->seq_fin = tp->snd_lst++;
-               }
-       } else {
-               if (tp->tc_flags&TC_SYN_ACKED) {
-                       wind = tp->snd_una + tp->snd_wnd;
-                       tp->snd_lst = MIN(last, wind);
-                       if ((len = tp->snd_lst - tp->snd_nxt) > 1024)
-                               tp->snd_lst -= len - 1024;
-                       if (tp->snd_lst >= wind)
-                               tp->t_persist = T_PERS;
-               }
-               if ((tp->tc_flags&TC_FORCE_ONE) && (tp->snd_lst == wind)) {
-                       tp->snd_lst = tp->snd_nxt + 1;
-                       forced = 1;
-               } else if (tp->snd_nxt >= tp->snd_lst && (tp->tc_flags&TC_SND_FIN) == 0)
-                       return (0);
-               m = m_copy(so->so_snd.sb_mb,
-                     (int)(MAX(tp->iss+1,tp->snd_nxt) - tp->snd_off),
-                     (int)(tp->snd_lst - tp->snd_off));
-               if (tp->snd_end > tp->iss && tp->snd_end <= tp->snd_lst)
-                       flags |= TH_EOL;
-               if ((tp->tc_flags&TC_SND_FIN) && !forced &&
-                   tp->snd_lst == last &&
-                   (tp->seq_fin == tp->iss || tp->snd_nxt <= tp->seq_fin)) {
-                       flags |= TH_FIN;
-                       tp->seq_fin = tp->snd_lst++;
-               }
-       }
-       if (tp->snd_nxt >= tp->snd_lst)
-               return (0);
-       if (tp->tc_flags & TC_SND_URG)
-               flags |= TH_URG;
-       sent = tcp_output(tp, flags, (int)(tp->snd_lst - tp->snd_nxt), m);
-       if (!forced) {
-               tp->t_rexmt = tp->t_xmtime;
-               tp->t_rexmt_val = tp->snd_lst;
-               if ((tp->tc_flags&TC_REXMT) == 0) {
-                       tp->t_rexmttl = T_REXMTTL;
-                       tp->t_rtl_val = tp->snd_lst;
-               }
+       /*
+        * Determine length of data that can be transmitted.
+        * If will transmit to end of data and no more data
+        * is coming, then send FIN also.
+        * Make a copy of the data (if any).  If no data
+        * and not forced to transmit, just return.
+        */
+       off = tp->snd_nxt - tp->snd_una;
+       len = MIN(so->so_snd.sb_cc, tp->snd_wnd) - off;
+       if (len > tp->mtu)
+               len = tp->mtu;
+       if (len == so->so_snd.sb_cc && (so->so_state & SS_CANTSNDMORE))
+               flags = TH_FIN;
+       else
+               flags = 0;
+       if (len)
+               goto send;
+
+       /*
+        * No data to send: see if something else makes us want to send.
+        * First check if we owe peer and ack or have a unacked FIN to send.
+        */
+       if (tp->t_flags & TF_OWEACK)
+               goto send;
+       if ((so->so_state & SS_CANTSNDMORE) &&
+           TCPS_OURFINISACKED(tp->t_state) == 0)
+               goto send;
+       if (tp->t_state == TCPS_SYN_SENT) {
+               flags = TH_SYN;
+               goto send;
        }
        }
-       if (sent)
-               tp->snd_nxt = tp->snd_lst;
-       if ((tp->tc_flags&TC_SYN_ACKED) &&
-           tp->snd_una > tp->t_xmt_val) {
-               tp->t_xmt = 0;
-               tp->t_xmt_val = tp->snd_lst;
+       if (tp->t_state == TCPS_CLOSED) {
+               flags = TH_RST;
+               goto send;
        }
        }
-       tp->tc_flags &= ~(TC_ACK_DUE|TC_REXMT|TC_FORCE_ONE);
-       tp->snd_hi = MAX(tp->snd_nxt, tp->snd_hi);
-       return (1);
-}
-tcp_output(tp, flags, len, dat)
-       register struct tcpcb *tp;
-       register int flags;
-       int len;
-       struct mbuf *dat;
-{
-       register struct tcpiphdr *t;                    /* known to be r9 */
-       register struct mbuf *m;
-       struct socket *so = tp->t_inpcb->inp_socket;
-       register struct ip *ip;
-COUNT(TCP_OUTPUT);
 
 
-       if ((t = tp->t_template) == 0)
-               return (0);
+       /*
+        * Calculate available window in i, and also amount
+        * of window known to peer (as advertised window less
+        * next expected input.)  If this is 35% or more of the
+        * maximum possible window, then want to send a segment to peer.
+        */
+       i = sbspace(&so->so_rcv) - tp->seqcnt;
+       if (i > 0 &&
+           ((100*(i-(tp->rcv_adv-tp->rcv_nxt))/so->so_rcv.sb_hiwat) >= 35))
+               goto send;
+
+       /*
+        * No reason to send a segment, just return.
+        */
+       return;
+
+send:
+       /*
+        * Grab a header mbuf, attaching a copy of data to
+        * be transmitted, and initialize the header from
+        * the template for sends on this connection.
+        */
        MGET(m, 0);
        if (m == 0)
                return (0);
        m->m_off = MMAXOFF - sizeof(struct tcpiphdr);
        m->m_len = sizeof (struct tcpiphdr);
        MGET(m, 0);
        if (m == 0)
                return (0);
        m->m_off = MMAXOFF - sizeof(struct tcpiphdr);
        m->m_len = sizeof (struct tcpiphdr);
-       m->m_next = dat;
+       if (len) {
+               m->m_next = m_copy(so->so_snd.sb_mb, off, len);
+               if (m->m_next == 0)
+                       len = 0;
+       }
+       ti = mtod(m, struct tcpiphdr *);
+       if (tp->t_template == 0)
+               panic("tcp_output");
+       bcopy((caddr_t)tp->t_template, ti, sizeof (struct tcpiphdr));
+
+       /*
+        * Fill in fields, remembering maximum advertised
+        * window for use in delaying messages about window sizes.
+        */
+       ti->ti_seq = htonl(tp->snd_nxt);
+       ti->ti_ackno = htonl(tp->rcv_nxt);
+       /* OPTIONS */
        if (flags & TH_SYN)
        if (flags & TH_SYN)
-               len--;
+               ti->ti_flags = flags;
+       else
+               ti->ti_flags = flags | TH_ACK;
+       win = sbspace(&so->so_rcv);
+       if (win > 0)
+               ti->ti_win = htons(win);
+       if (SEQ_GT(tp->snd_urp, tp->snd_nxt))
+               ti->ti_urp = htons((u_short)(tp->snd_urp - tp->snd_nxt));
+               ti->ti_flags |= TH_URG;
+       } else
+               /*
+                * If no urgent pointer to send, then we pull
+                * the urgent pointer to the left edge of the send window
+                * so that it doesn't drift into the send window on sequence
+                * number wraparound.
+                */
+               tp->snd_urp = tp->snd_una;              /* drag it along */
+
+       /*
+        * Put TCP length in extended header, and then
+        * checksum extended header and data.
+        */
+       if (len)
+               ti->ti_len = htons((u_short)(len + sizeof (struct tcphdr)));
+       ti->ti_sum = inet_cksum(m, sizeof (struct tcpiphdr) + len);
+
+       /*
+        * Fill in IP length and desired time to live and
+        * send to IP level.
+        */
+       ((struct ip *)ti)->ip_len = len + sizeof (struct tcpiphdr);
+       ((struct ip *)ti)->ip_ttl = TCP_TTL;
+       if (ip_output(m) == 0)
+               return;
+
+       /*
+        * Data sent (as far as we can tell).
+        * If this advertises a larger window than any other segment,
+        * then record its sequence to be used in suppressing messages.
+        * Advance snd_nxt to reflect transmitted sequence space,
+        * drop send for purpose of ACK requirements,
+        * and time transmission if not a retransmit.
+        */
+       if (win > 0 && SEQ_GT(tp->rcv_nxt+win, tp->rcv_adv))
+               tp->rcv_adv = tp->rcv_nxt + win;
+       tp->snd_nxt += len;
+       tp->t_flags &= ~(TF_OWEACK|TF_DELACK);
        if (flags & TH_FIN)
        if (flags & TH_FIN)
-               len--;
-       if (len < 0)
-               panic("tcp_output");
-       bcopy((caddr_t)t, mtod(m, caddr_t), sizeof (struct tcpiphdr));
-       t = mtod(m, struct tcpiphdr *);
-       if (tp->tc_flags&TC_SND_RST) {
-               flags &= ~TH_SYN;
-               flags |= TH_RST;
+               tp->snd_nxt++;
+       if (SEQ_GT(tp->snd_nxt, tp->snd_hi)) {
+               tp->snd_hi = tp->snd_nxt;
+               /* TIME TRANSMIT */
        }
        }
-       if (tp->tc_flags&TC_SYN_RCVD)
-               flags |= TH_ACK;
-       t->ti_flags = flags;
-       if (flags & TH_URG)
-               t->ti_urp = htons((u_short)tp->snd_urp);        /*XXX */
-       t->ti_win =
-           so->so_rcv.sb_hiwat -
-               (so->so_rcv.sb_cc + tp->seqcnt);
-       if (tp->rcv_nxt + t->ti_win > tp->rcv_adv)
-               tp->rcv_adv = tp->rcv_nxt + t->ti_win;
-       if (len)
-               t->ti_len = htons((u_short)(len + sizeof (struct tcphdr)));
-       t->ti_win = htons(t->ti_win);
-       t->ti_seq = htonl(tp->snd_nxt);
-       t->ti_ackno = htonl(tp->rcv_nxt);
-       t->ti_sum = 0;          /* gratuitous? */
-       t->ti_sum = inet_cksum(m, sizeof (struct tcpiphdr) + len);
-       ip = (struct ip *)t;
-       ip->ip_v = IPVERSION;
-       ip->ip_hl = 5;
-       ip->ip_tos = 0;
-       ip->ip_len = len + sizeof(struct tcpiphdr);
-       ip->ip_id = ip_id++;
-       ip->ip_off = 0;
-       ip->ip_ttl = MAXTTL;
-       ip_send(ip);
-       return (1);
+       return;
 }
 }
index dbe2491..3938b7e 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_subr.c 4.1 81/11/24 */
+/* tcp_subr.c 4.2 81/11/25 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -97,3 +97,97 @@ tcp_reflect(ti, ack, seq, flags)
        ((struct ip *)ti)->ip_ttl = MAXTTL;
        ip_output(m);
 }
        ((struct ip *)ti)->ip_ttl = MAXTTL;
        ip_output(m);
 }
+
+struct tcpcb *
+tcp_newtcpcb(inp)
+       struct inpcb *inp;
+{
+       struct mbuf *m = m_getclr(0);
+       register struct tcpcb *tp;
+COUNT(TCP_NEWTCPCB);
+
+       if (m == 0)
+               return (0);
+       tp = mtod(m, struct tcpcb *);
+
+       /*
+        * Make empty reassembly queue.
+        */
+       tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
+
+       /*
+        * Initialize sequence numbers and round trip retransmit timer.
+        */
+       tp->t_xmtime = T_REXMT;
+       tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
+           tp->iss = tcp_iss;
+       tp->snd_off = tp->iss + 1;
+       tcp_iss += (ISSINCR >> 1) + 1;
+
+       /*
+        * Hook to inpcb.
+        */
+       tp->t_inpcb = inp;
+       inp->inp_ppcb = (caddr_t)tp;
+       return (tp);
+}
+
+tcp_drop(tp, errno)
+       struct tcpcb *tp;
+       int errno;
+{
+       struct socket *so = tp->t_inpcb->inp_socket;
+
+COUNT(TCP_DROP);
+       if (TCPS_HAVERCVDSYN(tp->t_state) &&
+           TCPS_OURFINISACKED(tp->t_state) == 0) {
+               tp->t_state = TCPS_CLOSED;
+               tcp_output(tp);
+       }
+       so->so_error = errno;
+       socantrcvmore(so);
+       socantsndmore(so);
+       tcp_close(tp);
+}
+
+tcp_close(tp)
+       register struct tcpcb *tp;
+{
+       register struct tcpiphdr *t;
+
+COUNT(TCP_CLOSE);
+       tcp_canceltimers(tp);
+       t = tp->seg_next;
+       for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next)
+               m_freem(dtom(t));
+       if (tp->t_template) {
+               (void) m_free(dtom(tp->t_template));
+               tp->t_template = 0;
+       }
+       in_pcbfree(tp->t_inpcb);
+       (void) m_free(dtom(tp));
+}
+
+/*ARGSUSED*/
+tcp_sense(m)
+       struct mbuf *m;
+{
+
+COUNT(TCP_SENSE);
+       return (EOPNOTSUPP);
+}
+
+tcp_drain()
+{
+       register struct inpcb *ip;
+
+COUNT(TCP_DRAIN);
+}
+
+tcp_ctlinput(m)
+       struct mbuf *m;
+{
+
+COUNT(TCP_CTLINPUT);
+       m_freem(m);
+}
index 34b8e5d..85175e5 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_timer.c 4.1 81/11/24 */
+/* tcp_timer.c 4.2 81/11/25 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -46,7 +46,7 @@ COUNT(TCP_TIMEO);
        for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) {
                tp = intotcpcb(ip);
                tmp = &tp->t_init;
        for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next) {
                tp = intotcpcb(ip);
                tmp = &tp->t_init;
-               for (i = 0; i < TNTIMERS; i++) {
+               for (i = 0; i < TCPT_NTIMERS; i++) {
                        if (*tmp && --*tmp == 0)
                                (void) tcp_usrreq(tp->t_inpcb->inp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
                        if (*tmp && --*tmp == 0)
                                (void) tcp_usrreq(tp->t_inpcb->inp_socket,
                                    PRU_SLOWTIMO, (struct mbuf *)0,
@@ -55,86 +55,51 @@ COUNT(TCP_TIMEO);
                }
                tp->t_xmt++;
        }
                }
                tp->t_xmt++;
        }
-       tcp_iss += ISSINCR/2;           /* increment iss */
+       tcp_iss += TCP_ISSINCR/PR_SLOWHZ;               /* increment iss */
        splx(s);
 }
 
 /*
        splx(s);
 }
 
 /*
- * Cancel all timers for tcp tp.
+ * Cancel all timers for TCP tp.
  */
 tcp_tcancel(tp)
        struct tcpcb *tp;
 {
  */
 tcp_tcancel(tp)
        struct tcpcb *tp;
 {
-       register short *tmp = &tp->t_init;
        register int i;
 
        register int i;
 
-       for (i = 0; i < TNTIMERS; i++)
-               *tmp++ = 0;
+       for (i = 0; i < TCPT_NTIMERS; i++)
+               tp->t_timer[i] = 0;
 }
 
 /*
  * TCP timer went off processing.
  */
 }
 
 /*
  * TCP timer went off processing.
  */
-tcp_timers(tp, timertype)
+tcp_timers(tp, timer)
        register struct tcpcb *tp;
        register struct tcpcb *tp;
-       int timertype;
+       int timer;
 {
 
 COUNT(TCP_TIMERS);
        switch (timertype) {
 
 {
 
 COUNT(TCP_TIMERS);
        switch (timertype) {
 
-       case TFINACK:           /* fin-ack timer */
-               switch (tp->t_state) {
+       case TCPT_2MSL:
+               tcp_close(tp);
+               return;
 
 
-               case TIME_WAIT:
-                       /*
-                        * We can be sure our ACK of foreign FIN was rcvd,
-                        * and can close if no data left for user.
-                        */
-                       if (rcv_empty(tp)) {
-                               tcp_disconnect(tp);
-                               return (CLOSED);
-                       }
-                       return (RCV_WAIT);                      /* 17 */
-
-               case CLOSING:
-                       tp->tc_flags |= TC_WAITED_2_ML;
-                       return (SAME);
-
-               default:
-                       return (SAME);
+       case TCPT_REXMT:
+               tp->t_xmtime <<= 1;
+               if (tp->t_xmtime > TCPT_TOOLONG) {
+                       tcp_drop(tp, ETIMEDOUT);
+                       return;
                }
                }
+               tcp_output(tp);
+               return;
 
 
-       case TREXMT:            /* retransmission timer */
-               if (tp->t_rexmt_val > tp->snd_una) {            /* 34 */
-                       /*
-                        * Set so for a retransmission, increase rexmt time
-                        * in case of multiple retransmissions.
-                        */
-                       tp->snd_nxt = tp->snd_una;
-                       tp->tc_flags |= TC_REXMT;
-                       tp->t_xmtime = tp->t_xmtime << 1;
-                       if (tp->t_xmtime > T_REMAX)
-                               tp->t_xmtime = T_REMAX;
-                       (void) tcp_send(tp);
-               }
-               return (SAME);
-
-       case TREXMTTL:          /* retransmit too long */
-               if (tp->t_rtl_val > tp->snd_una) {              /* 36 */
-                       tcp_error(tp, ETIMEDOUT);
-                       return (CLOSED);
-               }
-               return (SAME);
+       case TCPT_PERSIST:
+               if (tcp_output(tp) == 0)
+                       tp->snd_wnd++, (void) tcp_output(tp), tp->snd_wnd--;
 
 
-       case TPERSIST:          /* persist timer */
-               /*
-                * Force a byte send through closed window.
-                */
-               tp->tc_flags |= TC_FORCE_ONE;
-               (void) tcp_send(tp);
-               return (SAME);
+       case TCPT_KEEP:
+               return;
        }
        }
-       panic("tcp_timers");
-       /*NOTREACHED*/
 }
 }
index d6871f7..abad774 100644 (file)
@@ -1,4 +1,4 @@
-/* tcp_usrreq.c 1.34 81/11/24 */
+/* tcp_usrreq.c 1.35 81/11/25 */
 
 #include "../h/param.h"
 #include "../h/systm.h"
 
 #include "../h/param.h"
 #include "../h/systm.h"
@@ -33,27 +33,24 @@ tcp_usrreq(so, req, m, addr)
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
        int s = splnet();
        register struct inpcb *inp = sotoinpcb(so);
        register struct tcpcb *tp;
        int s = splnet();
-       register int nstate;
        int error = 0;
        int error = 0;
+       struct tcpiphdr ti;
 COUNT(TCP_USRREQ);
 
        /*
         * Make sure attached.  If not,
         * only PRU_ATTACH is valid.
         */
 COUNT(TCP_USRREQ);
 
        /*
         * Make sure attached.  If not,
         * only PRU_ATTACH is valid.
         */
-       if (inp == 0) {
-               if (req != PRU_ATTACH) {
-                       splx(s);
-                       return (EINVAL);
-               }
-       } else {
+       if (inp == 0 && req != PRU_ATTACH)
+               splx(s);
+               return (EINVAL);
+       }
+       if (inp) {
                tp = intotcpcb(inp);
                tp = intotcpcb(inp);
-               nstate = tp->t_state;
 #ifdef KPROF
 #ifdef KPROF
-               tcp_acounts[nstate][req]++;
+               tcp_acounts[tp->t_state][req]++;
 #endif
        }
 #endif
        }
-
        switch (req) {
 
        case PRU_ATTACH:
        switch (req) {
 
        case PRU_ATTACH:
@@ -62,20 +59,19 @@ COUNT(TCP_USRREQ);
                        break;
                }
                error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
                        break;
                }
                error = in_pcballoc(so, &tcb, 2048, 2048, (struct sockaddr_in *)addr);
-               if (error) {
-                       (void) m_free(dtom(tp));
+               if (error)
                        break;
                        break;
-               }
                inp = (struct inpcb *)so->so_pcb;
                if (so->so_options & SO_ACCEPTCONN) {
                        tp = tcp_newtcpcb(inp);
                        if (tp == 0) {
                inp = (struct inpcb *)so->so_pcb;
                if (so->so_options & SO_ACCEPTCONN) {
                        tp = tcp_newtcpcb(inp);
                        if (tp == 0) {
+                               in_pcbfree(inp);
                                error = ENOBUFS;
                                break;
                        }
                                error = ENOBUFS;
                                break;
                        }
-                       nstate = LISTEN;
+                       tp->t_state = TCPS_LISTEN;
                } else
                } else
-                       nstate = CLOSED;
+                       tp->t_state = TCPS_CLOSED;
                break;
 
        case PRU_DETACH:
                break;
 
        case PRU_DETACH:
@@ -93,9 +89,9 @@ COUNT(TCP_USRREQ);
                }
                tp->t_inpcb = inp;
                inp->inp_ppcb = (caddr_t)tp;
                }
                tp->t_inpcb = inp;
                inp->inp_ppcb = (caddr_t)tp;
-               (void) tcp_sndctl(tp);
-               nstate = SYN_SENT;
                soisconnecting(so);
                soisconnecting(so);
+               tp->t_state = TCPS_SYN_SENT;
+               tcp_output(tp);
                break;
 
        case PRU_ACCEPT:
                break;
 
        case PRU_ACCEPT:
@@ -103,72 +99,64 @@ COUNT(TCP_USRREQ);
                break;
 
        case PRU_DISCONNECT:
                break;
 
        case PRU_DISCONNECT:
-               if (nstate < ESTAB)
-                       tcp_disconnect(tp);
+               if (tp->t_state < TCPS_ESTABLISHED)
+                       tcp_close(tp);
                else {
                else {
-                       tp->tc_flags |= TC_SND_FIN;
-                       (void) tcp_sndctl(tp);
                        soisdisconnecting(so);
                        soisdisconnecting(so);
+                       tcp_output(tp);
                }
                break;
 
        case PRU_SHUTDOWN:
                }
                break;
 
        case PRU_SHUTDOWN:
-               switch (nstate) {
+               socantsndmore(so);
+               switch (tp->t_state) {
 
                case TCPS_LISTEN:
                case TCPS_SYN_SENT:
 
                case TCPS_LISTEN:
                case TCPS_SYN_SENT:
-                       nstate = TCPS_CLOSED;
+                       tp->t_state = TCPS_CLOSED;
                        break;
 
                case TCPS_SYN_RCVD:
                        break;
 
                case TCPS_SYN_RCVD:
-               case TCPS_ESTABLISHED:
-               case TCPS_CLOSE_WAIT:
-                       tp->tc_flags |= TC_SND_FIN;
-                       (void) tcp_sndctl(tp);
-                       nstate = nstate != CLOSE_WAIT ? FIN_W1 : LAST_ACK;
-                       break;
-                       
-               case TCPS_FIN_W1:
-               case TCPS_FIN_W2:
-               case TCPS_TIME_WAIT:
-               case TCPS_CLOSING:
-               case TCPS_LAST_ACK:
-               case TCPS_RCV_WAIT:
+               case TCPS_ESTAB:
+                       tp->t_state = TCPS_FIN_WAIT_1;
+                       tcp_output(tp);
                        break;
 
                        break;
 
-               default:
-                       goto bad;
+               case TCPS_CLOSE_WAIT:
+                       tp->t_state = TCPS_LAST_ACK;
+                       tcp_output(tp);
+                       break;
                }
                break;
 
        case PRU_RCVD:
                }
                break;
 
        case PRU_RCVD:
-               if (nstate < TCPS_ESTAB)
-                       goto bad;
-               tcp_sndwin(tp);
-               if (nstate == TCPS_RCV_WAIT && rcv_empty(tp))
-                       nstate = TCPS_CLOSED;
+               if (tp->t_state < TCPS_ESTABLISHED) {
+                       error = ENOTCONN;
+                       break;
+               }
+               tcp_output(tp);
                break;
 
        case PRU_SEND:
                break;
 
        case PRU_SEND:
-               switch (nstate) {
-
-               case ESTAB:
-               case CLOSE_WAIT:
-                       tcp_usrsend(tp, m);
+               if (tp->t_state < TCPS_ESTABLISHED) {
+                       error = ENOTCONN;
                        break;
                        break;
-               
-               default:
-                       if (nstate < ESTAB)
-                               goto bad;
+               }
+               if (tp->t_state > TCPS_CLOSE_WAIT) {
+                       error = EISDISCONN;
                        m_freem(m);
                        m_freem(m);
-                       error = ENOTCONN;
                        break;
                }
                        break;
                }
+               sbappend(&so->so_snd, m);
+               if (tp->t_options & TO_EOL)
+                       tp->snd_end = tp->snd_una + so->so_snd.sb_cc;
+               if (tp->t_options & TO_URG)
+                       tp->snd_urp = tp->snd_una + so->so_snd.sb_cc + 1;
+               tcp_output(tp);
                break;
 
        case PRU_ABORT:
                break;
 
        case PRU_ABORT:
-               tcp_abort(tp);
-               nstate = CLOSED;
+               tcp_drop(tp, ECONNABORTED);
                break;
 
        case PRU_CONTROL:
                break;
 
        case PRU_CONTROL:
@@ -176,183 +164,12 @@ COUNT(TCP_USRREQ);
                break;
 
        case PRU_SLOWTIMO:
                break;
 
        case PRU_SLOWTIMO:
-               switch (nstate) {
-
-               case 0:
-               case CLOSED:
-               case LISTEN:
-                       goto bad;
-
-               default:
-                       nstate = tcp_timers(tp, (int)addr);
-               }
+               tcp_timers(tp, (int)addr);
                break;
 
        default:
                panic("tcp_usrreq");
                break;
 
        default:
                panic("tcp_usrreq");
-       bad:
-               printf("tcp: bad state: tcb=%x state=%d input=%d\n",
-                   tp, tp->t_state, req);
-               nstate = EFAILEC;
-               break;
-       }
-       switch (nstate) {
-
-       case CLOSED:
-       case SAME:
-               break;
-
-       case EFAILEC:
-               if (m)
-                       m_freem(dtom(m));
-               break;
-
-       default:
-               tp->t_state = nstate;
-               break;
        }
        splx(s);
        return (error);
 }
        }
        splx(s);
        return (error);
 }
-
-struct tcpcb *
-tcp_newtcpcb(inp)
-       struct inpcb *inp;
-{
-       struct mbuf *m = m_getclr(0);
-       register struct tcpcb *tp;
-COUNT(TCP_NEWTCPCB);
-
-       if (m == 0)
-               return (0);
-       tp = mtod(m, struct tcpcb *);
-
-       /*
-        * Make empty reassembly queue.
-        */
-       tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp;
-
-       /*
-        * Initialize sequence numbers and round trip retransmit timer.
-        */
-       tp->t_xmtime = T_REXMT;
-       tp->snd_end = tp->seq_fin = tp->snd_nxt = tp->snd_hi = tp->snd_una =
-           tp->iss = tcp_iss;
-       tp->snd_off = tp->iss + 1;
-       tcp_iss += (ISSINCR >> 1) + 1;
-
-       /*
-        * Hook to inpcb.
-        */
-       tp->t_inpcb = inp;
-       inp->inp_ppcb = (caddr_t)tp;
-       return (tp);
-}
-
-tcp_disconnect(tp)
-       register struct tcpcb *tp;
-{
-       register struct tcpiphdr *t;
-
-COUNT(TCP_DISCONNECT);
-       tcp_tcancel(tp);
-       t = tp->seg_next;
-       for (; t != (struct tcpiphdr *)tp; t = (struct tcpiphdr *)t->ti_next)
-               m_freem(dtom(t));
-       tcp_drainunack(tp);
-       if (tp->t_template) {
-               (void) m_free(dtom(tp->t_template));
-               tp->t_template = 0;
-       }
-       in_pcbfree(tp->t_inpcb);
-       (void) m_free(dtom(tp));
-}
-
-tcp_abort(tp)
-       register struct tcpcb *tp;
-{
-
-COUNT(TCP_ABORT);
-       switch (tp->t_state) {
-
-       case SYN_RCVD:
-       case ESTAB:
-       case FIN_W1:
-       case FIN_W2:
-       case CLOSE_WAIT:
-               tp->tc_flags |= TC_SND_RST;
-               tcp_sndnull(tp);
-       }
-       soisdisconnected(tp->t_inpcb->inp_socket);
-       tcp_disconnect(tp);
-}
-
-/*
- * Send data queue headed by m0 into the protocol.
- */
-tcp_usrsend(tp, m0)
-       register struct tcpcb *tp;
-       struct mbuf *m0;
-{
-       register struct socket *so = tp->t_inpcb->inp_socket;
-COUNT(TCP_USRSEND);
-
-       sbappend(&so->so_snd, m0);
-       if (tp->t_options & TO_EOL)
-               tp->snd_end = tp->snd_off + so->so_snd.sb_cc;
-       if (tp->t_options & TO_URG) {
-               tp->snd_urp = tp->snd_off + so->so_snd.sb_cc + 1;
-               tp->tc_flags |= TC_SND_URG;
-       }
-       (void) tcp_send(tp);
-}
-
-/*ARGSUSED*/
-tcp_sense(m)
-       struct mbuf *m;
-{
-
-COUNT(TCP_SENSE);
-       return (EOPNOTSUPP);
-}
-
-tcp_drop(tp, errno)
-       struct tcpcb *tp;
-       int errno;
-{
-       struct socket *so = tp->t_inpcb->inp_socket;
-
-COUNT(TCP_ERROR);
-       so->so_error = errno;
-       sorwakeup(so);
-       sowwakeup(so);
-       tcp_disconnect(tp);
-}
-
-tcp_drain()
-{
-       register struct inpcb *ip;
-
-COUNT(TCP_DRAIN);
-       for (ip = tcb.inp_next; ip != &tcb; ip = ip->inp_next)
-               tcp_drainunack(intotcpcb(ip));
-}
-
-tcp_drainunack(tp)
-       register struct tcpcb *tp;
-{
-       register struct mbuf *m;
-
-COUNT(TCP_DRAINUNACK);
-       for (m = tp->seg_unack; m; m = m->m_act)
-               m_freem(m);
-       tp->seg_unack = 0;
-}
-       
-tcp_ctlinput(m)
-       struct mbuf *m;
-{
-
-COUNT(TCP_CTLINPUT);
-       m_freem(m);
-}
index 16ccc00..c2aa183 100644 (file)
@@ -1,4 +1,4 @@
-/*     tcp_var.h       4.7     81/11/24        */
+/*     tcp_var.h       4.8     81/11/25        */
 
 /*
  * Kernel variables for tcp.
 
 /*
  * Kernel variables for tcp.
@@ -43,31 +43,29 @@ struct tcpiphdr {
  * Definitions of the TCP timers.  These timers are counted
  * down PR_SLOWHZ times a second.
  */
  * Definitions of the TCP timers.  These timers are counted
  * down PR_SLOWHZ times a second.
  */
-#define        TCPT_NTIMERS    7
+#define        TCPT_NTIMERS    4
 
 
-#define        TCPT_INIT       0               /* initialization */
-#define        TCPT_REXMT      1               /* retransmit */
-#define        TCPT_REXMTTL    2               /* retransmit too long */
+#define        TCPT_REXMT      0               /* retransmit */
+#define        TCPT_2MSL       1               /* 2*msl quiet time timer */
+#define        TCPT_PERSIST    2               /* retransmit persistance */
 #define        TCPT_KEEP       3               /* keep alive */
 #define        TCPT_KEEP       3               /* keep alive */
-#define        TCPT_KEEPTTL    4               /* keep alive too long */
-#define        TCPT_PERSIST    5               /* retransmit persistance */
-#define        TCPT_2MSL       6               /* 2*msl quiet time timer */
 
 /*
  * Tcp control block.
  */
 struct tcpcb {
 
 /*
  * Tcp control block.
  */
 struct tcpcb {
-       struct  tcpiphdr *seg_next,*seg_prev;   /* seq queue */
-       short   seqcnt;                 /* count of chars in seq queue */
-       u_char  t_state;                /* state of this connection */
+       struct  tcpiphdr *seg_next;     /* sequencing queue */
+       struct  tcpiphdr *seg_prev;
+       int     t_state;                /* state of this connection */
+       int     seqcnt;                 /* count of chars in seq queue */
        short   t_timers[TCPT_NTIMERS]; /* tcp timers */
        short   t_timers[TCPT_NTIMERS]; /* tcp timers */
-       u_char  t_options;              /* connection options: */
+       short   t_options;              /* connection options: */
 #define        TO_PUSH         0x01                    /* push mode */
 #define        TO_URG          0x02                    /* urgent mode */
 #define        TO_KEEP         0x04                    /* use keep-alives */
        u_char  t_flags;
 #define        TF_OWEACK       0x01                    /* owe ack to peer */
 #define        TO_PUSH         0x01                    /* push mode */
 #define        TO_URG          0x02                    /* urgent mode */
 #define        TO_KEEP         0x04                    /* use keep-alives */
        u_char  t_flags;
 #define        TF_OWEACK       0x01                    /* owe ack to peer */
-       struct  mbuf *seg_unack;        /* unacked message queue */
+#define        TF_DELACK       0x02                    /* delaying ack to peer */
        struct  tcpiphdr *t_template;   /* skeletal packet for transmit */
        struct  inpcb *t_inpcb;         /* back pointer to internet pcb */
 /*
        struct  tcpiphdr *t_template;   /* skeletal packet for transmit */
        struct  inpcb *t_inpcb;         /* back pointer to internet pcb */
 /*
@@ -90,44 +88,31 @@ struct tcpcb {
 /*
  * Additional variables for this implementation.
  */
 /*
  * Additional variables for this implementation.
  */
-/* send variables */
-       tcp_seq snd_off;        /*??*/  /* seq # of first datum in send buf */
-       tcp_seq seq_fin;        /*??*/  /* seq # of FIN sent */
-       tcp_seq snd_hi;         /*??*/  /* highest seq # sent */
-       tcp_seq snd_end;        /*??*/  /* send eol pointer */
-       tcp_seq snd_lst;        /*??*/  /* seq # of last sent datum */
-       tcp_seq snd_wl;         /*??*/  /* seq # of last sent window */
-       tcp_seq snd_wnd;        /*??*/  /* send window max */
-/* retransmit variables */
-       tcp_seq t_rexmt_val;    /*??*/  /* val saved in rexmt timer */
-       tcp_seq t_rtl_val;      /*??*/  /* val saved in rexmt too long timer */
-       tcp_seq t_xmt_val;      /*??*/  /* seq # sent when xmt timer started */
-       u_char  t_xmtime;       /*??*/  /* current rexmt time */
-       short   t_xmt;          /*??*/  /* round trip transmission time */
 /* receive variables */
 /* receive variables */
-       tcp_seq rcv_end;        /*??*/  /* rcv eol pointer */
-       tcp_seq rcv_adv;        /*??*/  /* advertised window */
+       tcp_seq rcv_adv;                /* advertised window */
+/* retransmit variables */
+       tcp_seq snd_max;                /* highest sequence number sent */
+                                          used to recognize retransmits */
 };
 
 #define        intotcpcb(ip)   ((struct tcpcb *)(ip)->inp_ppcb)
 #define        sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
 
 #define        ISSINCR         128             /* increment for iss each second */
 };
 
 #define        intotcpcb(ip)   ((struct tcpcb *)(ip)->inp_ppcb)
 #define        sototcpcb(so)   (intotcpcb(sotoinpcb(so)))
 
 #define        ISSINCR         128             /* increment for iss each second */
-#define        TCPSIZE         20              /* size of TCP leader (bytes) */
 
 
-#define        TCP_TTL         30              /* time to live for TCP segs: 30s */
+#define        TCP_TTL         60              /* time to live for TCP segs */
 /*
  * TCPSC constants give various timeouts in ``slow-clock'' ticks.
  */
 /*
  * TCPSC constants give various timeouts in ``slow-clock'' ticks.
  */
-#define        TCPSC_MSL       (TCP_TTL*PR_SLOWHZ)     /* max seg lifetime */
-#define        TCPSC_REXMT     (1*PR_SLOWHZ)           /* base retransmit time */
-#define        TCPSC_REXMTTL   (TCP_TTL*2*PR_SLOWHZ)   /* retransmit too long */
-#define        TCPSC_KEEP      (TCP_TTL*4*PR_SLOWHZ)   /* keep alive */
-#define        TCPSC_KEEPTTL   (4*TCPSC_KEEP)          /* keep alive too long */
-#define        TCPSC_PERSIST   (5*PR_SLOWHZ)           /* retransmit persistance */
-#define        TCPSC_2MSL      (TCP_TTL*2*PR_SLOWHZ)   /* 2*msl quiet time timer */
+#define        TCPSC_MSL       (120*PR_SLOWHZ)         /* max seg lifetime */
+#define        TCPSC_REXMT     (  1*PR_SLOWHZ)         /* base retransmit time */
+#define        TCPSC_KEEP      (240*PR_SLOWHZ)         /* keep alive */
+#define        TCPSC_PERSIST   (  5*PR_SLOWHZ)         /* retransmit persistance */
+
+#define        TCPSC_KEEPTTL   (  4*TCPSC_KEEP)        /* keep alive too long */
+#define        TCPSC_2MSL      (  2*TCPSC_MSL)         /* 2*msl quiet time timer */
 
 
-#define        TCPSC_REMAX     (TCP_TTL*PR_SLOWHZ)     /* maximum rexmt time */
+#define        TCPSC_TOOLONG   (480*PR_SLOWHZ)
 
 struct tcpstat {
        int     tcps_badsum;
 
 struct tcpstat {
        int     tcps_badsum;