SCCS-vsn: sys/vax/if/if_en.c 4.4
SCCS-vsn: sys/kern/uipc_mbuf.c 1.7
SCCS-vsn: sys/netinet/tcp.h 1.13
SCCS-vsn: sys/netinet/tcp_input.c 1.19
SCCS-vsn: sys/netinet/tcp_output.c 4.9
SCCS-vsn: sys/netinet/tcp_usrreq.c 1.24
-/* uipc_mbuf.c 1.6 81/10/30 */
+/* uipc_mbuf.c 1.7 81/11/04 */
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/param.h"
#include "../h/dir.h"
#include "../inet/tcp.h"
#include "../h/vm.h"
#include "../inet/tcp.h"
#include "../h/vm.h"
+m_reserve(mbufs)
+ int mbufs;
+{
+
+ if (mbstat.m_lowat + mbufs > NNETPAGES * NMBPG - 32)
+ return (0);
+ mbstat.m_lowat += mbufs;
+ mbstat.m_hiwat = 2 * mbstat.m_lowat;
+}
+
+m_release(mbufs)
+ int mbufs;
+{
+
+ mbstat.m_lowat -= mbufs;
+ mbstat.m_hiwat = 2 * mbstat.m_lowat;
+}
+
struct mbuf *
m_get(canwait)
int canwait;
struct mbuf *
m_get(canwait)
int canwait;
-/* tcp.h 1.12 81/11/03 */
+/* tcp.h 1.13 81/11/04 */
/*
* Tcp header. Fits over the ip header after option removed.
/*
* Tcp header. Fits over the ip header after option removed.
* Tcp control block.
*/
struct tcb {
* Tcp control block.
*/
struct tcb {
+/* first four elements of this struct must match tcphead below */
struct th *t_rcv_next; /* first el on rcv queue */
struct th *t_rcv_prev; /* last el on rcv queue */
struct tcb *tcb_next; /* next tcb */
struct tcb *tcb_prev; /* next tcb */
struct th *t_rcv_next; /* first el on rcv queue */
struct th *t_rcv_prev; /* last el on rcv queue */
struct tcb *tcb_next; /* next tcb */
struct tcb *tcb_prev; /* next tcb */
+/* end must match */
+ struct th *t_template; /* skeletal packet for transmit */
struct ucb *t_ucb; /* ucb */
struct mbuf *t_rcv_unack; /* unacked message queue */
short seqcnt;
struct ucb *t_ucb; /* ucb */
struct mbuf *t_rcv_unack; /* unacked message queue */
short seqcnt;
(((x)->tc_flags&TC_USR_ABORT) || \
((x)->t_ucb->uc_rbuf == NULL && (x)->t_rcv_next == (x)->t_rcv_prev))
(((x)->tc_flags&TC_USR_ABORT) || \
((x)->t_ucb->uc_rbuf == NULL && (x)->t_rcv_next == (x)->t_rcv_prev))
+#define ISSINCR 128 /* increment for iss each second */
+#define TCPSIZE 20 /* size of TCP leader (bytes) */
+
/*
* THESE NEED TO BE JUSTIFIED!
*/
/*
* THESE NEED TO BE JUSTIFIED!
*/
-#define ISSINCR 128 /* increment for iss each second */
-#define TCPROTO 6 /* TCP-4 protocol number */
-#define TCPSIZE 20 /* size of TCP leader (bytes) */
#define T_2ML 10 /* 2*maximum packet lifetime */
#define T_PERS 5 /* persist time */
#define T_INIT 30 /* init too long timeout */
#define T_REXMT 1 /* base for retransmission time */
#define T_REXMTTL 30 /* retransmit too long timeout */
#define T_REMAX 30 /* maximum retransmission time */
#define T_2ML 10 /* 2*maximum packet lifetime */
#define T_PERS 5 /* persist time */
#define T_INIT 30 /* init too long timeout */
#define T_REXMT 1 /* base for retransmission time */
#define T_REXMTTL 30 /* retransmit too long timeout */
#define T_REMAX 30 /* maximum retransmission time */
#define ACTIVE 1 /* active open */
#define PASSIVE 0 /* passive open */
#define ACTIVE 1 /* active open */
#define PASSIVE 0 /* passive open */
#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
#define SEQ_LEQ(a,b) ((int)((a)-(b)) <= 0)
#define SEQ_GT(a,b) ((int)((a)-(b)) > 0)
#define SEQ_GEQ(a,b) ((int)((a)-(b)) >= 0)
+struct th *tcp_template();
-/* tcp_input.c 1.18 81/11/03 */
+/* tcp_input.c 1.19 81/11/04 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
goto done;
}
tp->t_fport = n->t_src;
goto done;
}
tp->t_fport = n->t_src;
- tp->t_ucb->uc_template = tcp_template(tp);
+ tp->t_template = tcp_template(tp);
tcp_ctldat(tp, n, 1);
if (tp->tc_flags&TC_FIN_RCVD) {
tp->t_finack = T_2ML; /* 3 */
tcp_ctldat(tp, n, 1);
if (tp->tc_flags&TC_FIN_RCVD) {
tp->t_finack = T_2ML; /* 3 */
-/* tcp_output.c 4.8 81/11/01 */
+/* tcp_output.c 4.9 81/11/04 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
n = mtod(m, struct th *);
n->t_next = n->t_prev = 0;
n->t_x1 = 0;
n = mtod(m, struct th *);
n->t_next = n->t_prev = 0;
n->t_x1 = 0;
n->t_len = htons(sizeof (struct th) - sizeof (struct ip));
n->t_s.s_addr = n_lhost.s_addr;
n->t_d.s_addr = h->h_addr.s_addr;
n->t_len = htons(sizeof (struct th) - sizeof (struct ip));
n->t_s.s_addr = n_lhost.s_addr;
n->t_d.s_addr = h->h_addr.s_addr;
#endif
COUNT(TCP_OUTPUT);
#endif
COUNT(TCP_OUTPUT);
- if ((t = tp->t_ucb->uc_template) == 0)
+ if ((t = tp->t_template) == 0)
return (0);
MGET(m, 0);
if (m == 0)
return (0);
MGET(m, 0);
if (m == 0)
-/* tcp_usrreq.c 1.23 81/11/03 */
+/* tcp_usrreq.c 1.24 81/11/04 */
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
#endif
#include "../inet/tcp_fsm.h"
#endif
#include "../inet/tcp_fsm.h"
+/*
+ * Tcp finite state machine entries for timer and user generated
+ * requests. These routines raise the ipl to that of the network
+ * to prevent reentry. In particluar, this requires that the software
+ * clock interrupt have lower priority than the network so that
+ * we can enter the network from timeout routines without improperly
+ * nesting the interrupt stack.
+ */
+
+/*
+ * Tcp protocol timeout routine called once per second.
+ * Updates the timers in all active tcb's and
+ * causes finite state machine actions if timers expire.
+ */
tcp_timeo()
{
register struct tcb *tp;
tcp_timeo()
{
register struct tcb *tp;
+/*
+ * Cancel all timers for tcp tp.
+ */
+tcp_tcancel(tp)
+ struct tcb *tp;
+{
+ register u_char *tmp = &tp->t_init;
+ register int i;
+
+ for (i = 0; i < TNTIMERS; i++)
+ *tmp++ = 0;
+}
+
/*
* Process a TCP user request for tcp tb. If this is a send request
* then m is the mbuf chain of send data. If this is a timer expiration
/*
* Process a TCP user request for tcp tb. If this is a send request
* then m is the mbuf chain of send data. If this is a timer expiration
* Passive open. Create a tcp control block
* and enter listen state.
*/
* Passive open. Create a tcp control block
* and enter listen state.
*/
if (nstate != 0 && nstate != CLOSED)
goto bad;
tcp_open(tp, PASSIVE);
if (nstate != 0 && nstate != CLOSED)
goto bad;
tcp_open(tp, PASSIVE);
* Active open. Create a tcp control block,
* send a SYN and enter SYN_SENT state.
*/
* Active open. Create a tcp control block,
* send a SYN and enter SYN_SENT state.
*/
if (nstate != 0 && nstate != CLOSED)
goto bad;
tcp_open(tp, ACTIVE);
if (nstate != 0 && nstate != CLOSED)
goto bad;
tcp_open(tp, ACTIVE);
* delete the tcb.
*/
case LISTEN:
* delete the tcb.
*/
case LISTEN:
- case SYN_SENT: /* 10 */
tcp_close(tp, UCLOSED);
nstate = CLOSED;
break;
tcp_close(tp, UCLOSED);
nstate = CLOSED;
break;
* (to TIME_WAIT), and then timeout.
* In any case this starts with a transition to FIN_W1 here.
*/
* (to TIME_WAIT), and then timeout.
* In any case this starts with a transition to FIN_W1 here.
*/
- case SYN_RCVD: /* 24,25 */
case L_SYN_RCVD:
case ESTAB:
case L_SYN_RCVD:
case ESTAB:
- case CLOSE_WAIT: /* 10 */
tp->tc_flags |= TC_SND_FIN;
tcp_sndctl(tp);
tp->tc_flags |= TC_USR_CLOSED;
tp->tc_flags |= TC_SND_FIN;
tcp_sndctl(tp);
tp->tc_flags |= TC_USR_CLOSED;
* Timers should expire only on open connections
* not in LISTEN state.
*/
* Timers should expire only on open connections
* not in LISTEN state.
*/
- case ISTIMER: /* 14,17,34,35,36,37,38 */
switch (nstate) {
case 0:
switch (nstate) {
case 0:
* out of the TCP buffers after foreign close) and there
* is no more data, institute a close.
*/
* out of the TCP buffers after foreign close) and there
* is no more data, institute a close.
*/
if (nstate < ESTAB || nstate == CLOSED)
goto bad;
if (nstate < ESTAB || nstate == CLOSED)
goto bad;
- tcp_sndwin(tp); /* send new window */
if ((tp->tc_flags&TC_FIN_RCVD) &&
(tp->tc_flags&TC_USR_CLOSED) == 0 &&
rcv_empty(tp))
if ((tp->tc_flags&TC_FIN_RCVD) &&
(tp->tc_flags&TC_USR_CLOSED) == 0 &&
rcv_empty(tp))
* Allowed only on ESTAB connection and after FIN from
* foreign peer.
*/
* Allowed only on ESTAB connection and after FIN from
* foreign peer.
*/
- case IUSEND: /* 40,41 */
switch (nstate) {
case ESTAB:
switch (nstate) {
case ESTAB:
* then we need to send an RST. In any case we then
* enter closed state.
*/
* then we need to send an RST. In any case we then
* enter closed state.
*/
- case IUABORT: /* 44,45 */
if (nstate == 0 || nstate == CLOSED)
break;
switch (nstate) {
if (nstate == 0 || nstate == CLOSED)
break;
switch (nstate) {
* Network down entry. Discard the tcb and force
* the state to be closed, ungracefully.
*/
* Network down entry. Discard the tcb and force
* the state to be closed, ungracefully.
*/
if (nstate == 0 || nstate == CLOSED)
break;
tcp_close(tp, UNETDWN);
if (nstate == 0 || nstate == CLOSED)
break;
tcp_close(tp, UNETDWN);
- * Cancel all timers.
- * SHOULD LOOP HERE !?!
- */
- tp->t_init = tp->t_rexmt = tp->t_rexmttl = tp->t_persist =
- tp->t_finack = 0;
-
- /*
- * Remque the tcb
+ * Remove from tcb queue and cancel timers.
*/
tp->tcb_prev->tcb_next = tp->tcb_next;
tp->tcb_next->tcb_prev = tp->tcb_prev;
*/
tp->tcb_prev->tcb_next = tp->tcb_next;
tp->tcb_next->tcb_prev = tp->tcb_prev;
- * Discard all buffers...
- *
- * SHOULD COUNT EACH RESOURCE TO 0 AND PANIC IF CONFUSED
*/
for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
m_freem(dtom(t));
*/
for (t = tp->t_rcv_next; t != (struct th *)tp; t = t->t_next)
m_freem(dtom(t));
- if (up->uc_rbuf != NULL) {
m_freem(up->uc_rbuf);
up->uc_rbuf = NULL;
}
up->uc_rcc = 0;
m_freem(up->uc_rbuf);
up->uc_rbuf = NULL;
}
up->uc_rcc = 0;
- if (up->uc_sbuf != NULL) {
m_freem(up->uc_sbuf);
up->uc_sbuf = NULL;
}
m_freem(up->uc_sbuf);
up->uc_sbuf = NULL;
}
- * Free tcp send template.
+ * Free tcp send template, the tcb itself,
+ * the routing table entry, and the space we had reserved
+ * in the meory pool.
- if (up->uc_template) {
- m_free(dtom(up->uc_template));
- up->uc_template = 0;
+ if (tp->t_template) {
+ m_free(dtom(tp->t_template));
+ tp->t_template = 0;
-
- /*
- * Free the tcb
- * WOULD THIS BETTER BE DONE AT USER CLOSE?
- */
wmemfree((caddr_t)tp, 1024);
wmemfree((caddr_t)tp, 1024);
- up->uc_tcb = NULL;
-
- /*
- * Lower buffer allocation.
- * SHOULD BE A M_ROUTINE CALL.
- */
- mbstat.m_lowat -= up->uc_snd + (up->uc_rhiwat/MSIZE) + 2;
- mbstat.m_hiwat = 2 * mbstat.m_lowat;
-
- /*
- * Free routing table entry.
- */
- if (up->uc_host != NULL) {
+ up->uc_pcb = 0;
+ if (up->uc_host) {
+ m_release(up->uc_snd + (up->uc_rhiwat/MSIZE) + 2);
/*
* If user has initiated close (via close call), delete ucb
* entry, otherwise just wakeup so user can issue close call
*/
/*
* If user has initiated close (via close call), delete ucb
* entry, otherwise just wakeup so user can issue close call
*/
- if (tp->tc_flags&TC_USR_ABORT)
- up->uc_proc = NULL;
- else
+ if (tp->tc_flags&TC_USR_ABORT) /* ### */
+ up->uc_proc = NULL; /* ### */
+ else /* ### */
to_user(up, state); /* ### */
}
/*
to_user(up, state); /* ### */
}
/*
- * User routine to send data queue headed by m0 into the protocol.
+ * Send data queue headed by m0 into the protocol.
*/
tcp_usrsend(tp, m0)
register struct tcb *tp;
*/
tcp_usrsend(tp, m0)
register struct tcb *tp;
-/* if_en.c 4.3 81/11/01 */
+/* if_en.c 4.4 81/11/04 */
hlen = L1822 + sizeof (struct ip);
switch (ip->ip_p) {
hlen = L1822 + sizeof (struct ip);
switch (ip->ip_p) {
hlen += ((struct th *)ip)->t_off * 4;
break;
}
hlen += ((struct th *)ip)->t_off * 4;
break;
}