Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 25 May 2009 09:28:55 +0000 (UTC)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r192746 - in head/sys: conf netipx
Message-ID:  <200905250928.n4P9StAR017933@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rwatson
Date: Mon May 25 09:28:54 2009
New Revision: 192746
URL: http://svn.freebsd.org/changeset/base/192746

Log:
  Complete move of SPX reassembly from spx_usrreq.c to spx_reass.c.
  
  MFC after:	1 month

Modified:
  head/sys/conf/files
  head/sys/netipx/spx_reass.c
  head/sys/netipx/spx_usrreq.c
  head/sys/netipx/spx_var.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Mon May 25 09:23:26 2009	(r192745)
+++ head/sys/conf/files	Mon May 25 09:28:54 2009	(r192746)
@@ -2427,6 +2427,7 @@ netipx/ipx_pcb.c		optional ipx
 netipx/ipx_proto.c		optional ipx
 netipx/ipx_usrreq.c		optional ipx
 netipx/spx_debug.c		optional ipx
+netipx/spx_reass.c		optional ipx
 netipx/spx_usrreq.c		optional ipx
 netnatm/natm.c			optional natm
 netnatm/natm_pcb.c		optional natm

Modified: head/sys/netipx/spx_reass.c
==============================================================================
--- head/sys/netipx/spx_reass.c	Mon May 25 09:23:26 2009	(r192745)
+++ head/sys/netipx/spx_reass.c	Mon May 25 09:28:54 2009	(r192746)
@@ -89,97 +89,9 @@ __FBSDID("$FreeBSD$");
 #include <netipx/spx_timer.h>
 #include <netipx/spx_var.h>
 
-/*
- * SPX protocol implementation.
- */
-static struct	mtx spx_mtx;			/* Protects only spx_iss. */
-static u_short 	spx_iss;
-static u_short	spx_newchecks[50];
-static int	spx_hardnosed;
 static int	spx_use_delack = 0;
-static int	traceallspxs = 0;
-static struct	spx_istat spx_istat;
 static int	spxrexmtthresh = 3;
 
-#define	SPX_LOCK_INIT()	mtx_init(&spx_mtx, "spx_mtx", NULL, MTX_DEF)
-#define	SPX_LOCK()	mtx_lock(&spx_mtx)
-#define	SPX_UNLOCK()	mtx_unlock(&spx_mtx)
-
-/* Following was struct spxstat spxstat; */
-#ifndef spxstat
-#define spxstat spx_istat.newstats
-#endif
-
-static const int spx_backoff[SPX_MAXRXTSHIFT+1] =
-    { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
-
-static	void spx_close(struct spxpcb *cb);
-static	void spx_disconnect(struct spxpcb *cb);
-static	void spx_drop(struct spxpcb *cb, int errno);
-static	int spx_output(struct spxpcb *cb, struct mbuf *m0);
-static	int spx_reass(struct spxpcb *cb, struct spx *si);
-static	void spx_setpersist(struct spxpcb *cb);
-static	void spx_template(struct spxpcb *cb);
-static	void spx_timers(struct spxpcb *cb, int timer);
-static	void spx_usrclosed(struct spxpcb *cb);
-
-static	void spx_usr_abort(struct socket *so);
-static	int spx_accept(struct socket *so, struct sockaddr **nam);
-static	int spx_attach(struct socket *so, int proto, struct thread *td);
-static	int spx_bind(struct socket *so, struct sockaddr *nam, struct thread *td);
-static	void spx_usr_close(struct socket *so);
-static	int spx_connect(struct socket *so, struct sockaddr *nam,
-			struct thread *td);
-static	void spx_detach(struct socket *so);
-static	void spx_pcbdetach(struct ipxpcb *ipxp);
-static	int spx_usr_disconnect(struct socket *so);
-static	int spx_listen(struct socket *so, int backlog, struct thread *td);
-static	int spx_rcvd(struct socket *so, int flags);
-static	int spx_rcvoob(struct socket *so, struct mbuf *m, int flags);
-static	int spx_send(struct socket *so, int flags, struct mbuf *m,
-		     struct sockaddr *addr, struct mbuf *control,
-		     struct thread *td);
-static	int spx_shutdown(struct socket *so);
-static	int spx_sp_attach(struct socket *so, int proto, struct thread *td);
-
-struct	pr_usrreqs spx_usrreqs = {
-	.pru_abort =		spx_usr_abort,
-	.pru_accept =		spx_accept,
-	.pru_attach =		spx_attach,
-	.pru_bind =		spx_bind,
-	.pru_connect =		spx_connect,
-	.pru_control =		ipx_control,
-	.pru_detach =		spx_detach,
-	.pru_disconnect =	spx_usr_disconnect,
-	.pru_listen =		spx_listen,
-	.pru_peeraddr =		ipx_peeraddr,
-	.pru_rcvd =		spx_rcvd,
-	.pru_rcvoob =		spx_rcvoob,
-	.pru_send =		spx_send,
-	.pru_shutdown =		spx_shutdown,
-	.pru_sockaddr =		ipx_sockaddr,
-	.pru_close =		spx_usr_close,
-};
-
-struct	pr_usrreqs spx_usrreq_sps = {
-	.pru_abort =		spx_usr_abort,
-	.pru_accept =		spx_accept,
-	.pru_attach =		spx_sp_attach,
-	.pru_bind =		spx_bind,
-	.pru_connect =		spx_connect,
-	.pru_control =		ipx_control,
-	.pru_detach =		spx_detach,
-	.pru_disconnect =	spx_usr_disconnect,
-	.pru_listen =		spx_listen,
-	.pru_peeraddr =		ipx_peeraddr,
-	.pru_rcvd =		spx_rcvd,
-	.pru_rcvoob =		spx_rcvoob,
-	.pru_send =		spx_send,
-	.pru_shutdown =		spx_shutdown,
-	.pru_sockaddr =		ipx_sockaddr,
-	.pru_close =		spx_usr_close,
-};
-
 static __inline void
 spx_insque(struct spx_q *element, struct spx_q *head)
 {
@@ -189,8 +101,8 @@ spx_insque(struct spx_q *element, struct
 	head->si_next = element;
 	element->si_next->si_prev = element;
 }
-
-static __inline void
+ 
+void
 spx_remque(struct spx_q *element)
 {
 
@@ -199,258 +111,12 @@ spx_remque(struct spx_q *element)
 	element->si_prev = NULL;
 }
 
-void
-spx_init(void)
-{
-
-	SPX_LOCK_INIT();
-	spx_iss = 1; /* WRONG !! should fish it out of TODR */
-}
-
-void
-spx_input(struct mbuf *m, struct ipxpcb *ipxp)
-{
-	struct spxpcb *cb;
-	struct spx *si = mtod(m, struct spx *);
-	struct socket *so;
-	struct spx spx_savesi;
-	int dropsocket = 0;
-	short ostate = 0;
-
-	spxstat.spxs_rcvtotal++;
-	KASSERT(ipxp != NULL, ("spx_input: ipxpcb == NULL"));
-
-	/*
-	 * spx_input() assumes that the caller will hold both the pcb list
-	 * lock and also the ipxp lock.  spx_input() will release both before
-	 * returning, and may in fact trade in the ipxp lock for another pcb
-	 * lock following sonewconn().
-	 */
-	IPX_LIST_LOCK_ASSERT();
-	IPX_LOCK_ASSERT(ipxp);
-
-	cb = ipxtospxpcb(ipxp);
-	KASSERT(cb != NULL, ("spx_input: cb == NULL"));
-
-	if (ipxp->ipxp_flags & IPXP_DROPPED)
-		goto drop;
-
-	if (m->m_len < sizeof(*si)) {
-		if ((m = m_pullup(m, sizeof(*si))) == NULL) {
-			IPX_UNLOCK(ipxp);
-			IPX_LIST_UNLOCK();
-			spxstat.spxs_rcvshort++;
-			return;
-		}
-		si = mtod(m, struct spx *);
-	}
-	si->si_seq = ntohs(si->si_seq);
-	si->si_ack = ntohs(si->si_ack);
-	si->si_alo = ntohs(si->si_alo);
-
-	so = ipxp->ipxp_socket;
-	KASSERT(so != NULL, ("spx_input: so == NULL"));
-
-	if (so->so_options & SO_DEBUG || traceallspxs) {
-		ostate = cb->s_state;
-		spx_savesi = *si;
-	}
-	if (so->so_options & SO_ACCEPTCONN) {
-		struct spxpcb *ocb = cb;
-
-		so = sonewconn(so, 0);
-		if (so == NULL)
-			goto drop;
-
-		/*
-		 * This is ugly, but ....
-		 *
-		 * Mark socket as temporary until we're committed to keeping
-		 * it.  The code at ``drop'' and ``dropwithreset'' check the
-		 * flag dropsocket to see if the temporary socket created
-		 * here should be discarded.  We mark the socket as
-		 * discardable until we're committed to it below in
-		 * TCPS_LISTEN.
-		 *
-		 * XXXRW: In the new world order of real kernel parallelism,
-		 * temporarily allocating the socket when we're "not sure"
-		 * seems like a bad idea, as we might race to remove it if
-		 * the listen socket is closed...?
-		 *
-		 * We drop the lock of the listen socket ipxp, and acquire
-		 * the lock of the new socket ippx.
-		 */
-		dropsocket++;
-		IPX_UNLOCK(ipxp);
-		ipxp = (struct ipxpcb *)so->so_pcb;
-		IPX_LOCK(ipxp);
-		ipxp->ipxp_laddr = si->si_dna;
-		cb = ipxtospxpcb(ipxp);
-		cb->s_mtu = ocb->s_mtu;		/* preserve sockopts */
-		cb->s_flags = ocb->s_flags;	/* preserve sockopts */
-		cb->s_flags2 = ocb->s_flags2;	/* preserve sockopts */
-		cb->s_state = TCPS_LISTEN;
-	}
-	IPX_LOCK_ASSERT(ipxp);
-
-	/*
-	 * Packet received on connection.  Reset idle time and keep-alive
-	 * timer.
-	 */
-	cb->s_idle = 0;
-	cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
-
-	switch (cb->s_state) {
-	case TCPS_LISTEN:{
-		struct sockaddr_ipx *sipx, ssipx;
-		struct ipx_addr laddr;
-
-		/*
-		 * If somebody here was carying on a conversation and went
-		 * away, and his pen pal thinks he can still talk, we get the
-		 * misdirected packet.
-		 */
-		if (spx_hardnosed && (si->si_did != 0 || si->si_seq != 0)) {
-			spx_istat.gonawy++;
-			goto dropwithreset;
-		}
-		sipx = &ssipx;
-		bzero(sipx, sizeof *sipx);
-		sipx->sipx_len = sizeof(*sipx);
-		sipx->sipx_family = AF_IPX;
-		sipx->sipx_addr = si->si_sna;
-		laddr = ipxp->ipxp_laddr;
-		if (ipx_nullhost(laddr))
-			ipxp->ipxp_laddr = si->si_dna;
-		if (ipx_pcbconnect(ipxp, (struct sockaddr *)sipx, &thread0)) {
-			ipxp->ipxp_laddr = laddr;
-			spx_istat.noconn++;
-			goto drop;
-		}
-		spx_template(cb);
-		dropsocket = 0;		/* committed to socket */
-		cb->s_did = si->si_sid;
-		cb->s_rack = si->si_ack;
-		cb->s_ralo = si->si_alo;
-#define THREEWAYSHAKE
-#ifdef THREEWAYSHAKE
-		cb->s_state = TCPS_SYN_RECEIVED;
-		cb->s_force = 1 + SPXT_KEEP;
-		spxstat.spxs_accepts++;
-		cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
-		}
-		break;
-
-	 case TCPS_SYN_RECEIVED: {
-		/*
-		 * This state means that we have heard a response to our
-		 * acceptance of their connection.  It is probably logically
-		 * unnecessary in this implementation.
-		 */
-		if (si->si_did != cb->s_sid) {
-			spx_istat.wrncon++;
-			goto drop;
-		}
-#endif
-		ipxp->ipxp_fport =  si->si_sport;
-		cb->s_timer[SPXT_REXMT] = 0;
-		cb->s_timer[SPXT_KEEP] = SPXTV_KEEP;
-		soisconnected(so);
-		cb->s_state = TCPS_ESTABLISHED;
-		spxstat.spxs_accepts++;
-		}
-		break;
-
-	case TCPS_SYN_SENT:
-		/*
-		 * This state means that we have gotten a response to our
-		 * attempt to establish a connection.  We fill in the data
-		 * from the other side, telling us which port to respond to,
-		 * instead of the well-known one we might have sent to in the
-		 * first place.  We also require that this is a response to
-		 * our connection id.
-		 */
-		if (si->si_did != cb->s_sid) {
-			spx_istat.notme++;
-			goto drop;
-		}
-		spxstat.spxs_connects++;
-		cb->s_did = si->si_sid;
-		cb->s_rack = si->si_ack;
-		cb->s_ralo = si->si_alo;
-		cb->s_dport = ipxp->ipxp_fport =  si->si_sport;
-		cb->s_timer[SPXT_REXMT] = 0;
-		cb->s_flags |= SF_ACKNOW;
-		soisconnected(so);
-		cb->s_state = TCPS_ESTABLISHED;
-
-		/*
-		 * Use roundtrip time of connection request for initial rtt.
-		 */
-		if (cb->s_rtt) {
-			cb->s_srtt = cb->s_rtt << 3;
-			cb->s_rttvar = cb->s_rtt << 1;
-			SPXT_RANGESET(cb->s_rxtcur,
-			    ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1,
-			    SPXTV_MIN, SPXTV_REXMTMAX);
-			    cb->s_rtt = 0;
-		}
-	}
-
-	if (so->so_options & SO_DEBUG || traceallspxs)
-		spx_trace(SA_INPUT, (u_char)ostate, cb, &spx_savesi, 0);
-
-	m->m_len -= sizeof(struct ipx);
-	m->m_pkthdr.len -= sizeof(struct ipx);
-	m->m_data += sizeof(struct ipx);
-
-	if (spx_reass(cb, si))
-		m_freem(m);
-	if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT)))
-		spx_output(cb, NULL);
-	cb->s_flags &= ~(SF_WIN|SF_RXT);
-	IPX_UNLOCK(ipxp);
-	IPX_LIST_UNLOCK();
-	return;
-
-dropwithreset:
-	IPX_LOCK_ASSERT(ipxp);
-	if (cb == NULL || (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG ||
-	    traceallspxs))
-		spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
-	IPX_UNLOCK(ipxp);
-	if (dropsocket) {
-		struct socket *head;
-		ACCEPT_LOCK();
-		KASSERT((so->so_qstate & SQ_INCOMP) != 0,
-		    ("spx_input: nascent socket not SQ_INCOMP on soabort()"));
-		head = so->so_head;
-		TAILQ_REMOVE(&head->so_incomp, so, so_list);
-		head->so_incqlen--;
-		so->so_qstate &= ~SQ_INCOMP;
-		so->so_head = NULL;
-		ACCEPT_UNLOCK();
-		soabort(so);
-	}
-	IPX_LIST_UNLOCK();
-	m_freem(m);
-	return;
-
-drop:
-	IPX_LOCK_ASSERT(ipxp);
-	if (cb->s_ipxpcb->ipxp_socket->so_options & SO_DEBUG || traceallspxs)
-		spx_trace(SA_DROP, (u_char)ostate, cb, &spx_savesi, 0);
-	IPX_UNLOCK(ipxp);
-	IPX_LIST_UNLOCK();
-	m_freem(m);
-}
-
 /*
  * This is structurally similar to the tcp reassembly routine but its
  * function is somewhat different: it merely queues packets up, and
  * suppresses duplicates.
  */
-static int
+int
 spx_reass(struct spxpcb *cb, struct spx *si)
 {
 	struct spx_q *q;
@@ -758,1375 +424,3 @@ present:
 		SOCKBUF_UNLOCK(&so->so_rcv);
 	return (0);
 }
-
-void
-spx_ctlinput(int cmd, struct sockaddr *arg_as_sa, void *dummy)
-{
-
-	/* Currently, nothing. */
-}
-
-static int
-spx_output(struct spxpcb *cb, struct mbuf *m0)
-{
-	struct socket *so = cb->s_ipxpcb->ipxp_socket;
-	struct mbuf *m;
-	struct spx *si = NULL;
-	struct sockbuf *sb = &so->so_snd;
-	int len = 0, win, rcv_win;
-	short span, off, recordp = 0;
-	u_short alo;
-	int error = 0, sendalot;
-#ifdef notdef
-	int idle;
-#endif
-	struct mbuf *mprev;
-
-	IPX_LOCK_ASSERT(cb->s_ipxpcb);
-
-	if (m0 != NULL) {
-		int mtu = cb->s_mtu;
-		int datalen;
-
-		/*
-		 * Make sure that packet isn't too big.
-		 */
-		for (m = m0; m != NULL; m = m->m_next) {
-			mprev = m;
-			len += m->m_len;
-			if (m->m_flags & M_EOR)
-				recordp = 1;
-		}
-		datalen = (cb->s_flags & SF_HO) ?
-				len - sizeof(struct spxhdr) : len;
-		if (datalen > mtu) {
-			if (cb->s_flags & SF_PI) {
-				m_freem(m0);
-				return (EMSGSIZE);
-			} else {
-				int oldEM = cb->s_cc & SPX_EM;
-
-				cb->s_cc &= ~SPX_EM;
-				while (len > mtu) {
-					m = m_copym(m0, 0, mtu, M_DONTWAIT);
-					if (m == NULL) {
-					    cb->s_cc |= oldEM;
-					    m_freem(m0);
-					    return (ENOBUFS);
-					}
-					if (cb->s_flags & SF_NEWCALL) {
-					    struct mbuf *mm = m;
-					    spx_newchecks[7]++;
-					    while (mm != NULL) {
-						mm->m_flags &= ~M_EOR;
-						mm = mm->m_next;
-					    }
-					}
-					error = spx_output(cb, m);
-					if (error) {
-						cb->s_cc |= oldEM;
-						m_freem(m0);
-						return (error);
-					}
-					m_adj(m0, mtu);
-					len -= mtu;
-				}
-				cb->s_cc |= oldEM;
-			}
-		}
-
-		/*
-		 * Force length even, by adding a "garbage byte" if
-		 * necessary.
-		 */
-		if (len & 1) {
-			m = mprev;
-			if (M_TRAILINGSPACE(m) >= 1)
-				m->m_len++;
-			else {
-				struct mbuf *m1 = m_get(M_DONTWAIT, MT_DATA);
-
-				if (m1 == NULL) {
-					m_freem(m0);
-					return (ENOBUFS);
-				}
-				m1->m_len = 1;
-				*(mtod(m1, u_char *)) = 0;
-				m->m_next = m1;
-			}
-		}
-		m = m_gethdr(M_DONTWAIT, MT_DATA);
-		if (m == NULL) {
-			m_freem(m0);
-			return (ENOBUFS);
-		}
-
-		/*
-		 * Fill in mbuf with extended SP header and addresses and
-		 * length put into network format.
-		 */
-		MH_ALIGN(m, sizeof(struct spx));
-		m->m_len = sizeof(struct spx);
-		m->m_next = m0;
-		si = mtod(m, struct spx *);
-		si->si_i = *cb->s_ipx;
-		si->si_s = cb->s_shdr;
-		if ((cb->s_flags & SF_PI) && (cb->s_flags & SF_HO)) {
-			struct spxhdr *sh;
-			if (m0->m_len < sizeof(*sh)) {
-				if((m0 = m_pullup(m0, sizeof(*sh))) == NULL) {
-					m_free(m);
-					m_freem(m0);
-					return (EINVAL);
-				}
-				m->m_next = m0;
-			}
-			sh = mtod(m0, struct spxhdr *);
-			si->si_dt = sh->spx_dt;
-			si->si_cc |= sh->spx_cc & SPX_EM;
-			m0->m_len -= sizeof(*sh);
-			m0->m_data += sizeof(*sh);
-			len -= sizeof(*sh);
-		}
-		len += sizeof(*si);
-		if ((cb->s_flags2 & SF_NEWCALL) && recordp) {
-			si->si_cc |= SPX_EM;
-			spx_newchecks[8]++;
-		}
-		if (cb->s_oobflags & SF_SOOB) {
-			/*
-			 * Per jqj@cornell: Make sure OB packets convey
-			 * exactly 1 byte.  If the packet is 1 byte or
-			 * larger, we have already guaranted there to be at
-			 * least one garbage byte for the checksum, and extra
-			 * bytes shouldn't hurt!
-			 */
-			if (len > sizeof(*si)) {
-				si->si_cc |= SPX_OB;
-				len = (1 + sizeof(*si));
-			}
-		}
-		si->si_len = htons((u_short)len);
-		m->m_pkthdr.len = ((len - 1) | 1) + 1;
-
-		/*
-		 * Queue stuff up for output.
-		 */
-		sbappendrecord(sb, m);
-		cb->s_seq++;
-	}
-#ifdef notdef
-	idle = (cb->s_smax == (cb->s_rack - 1));
-#endif
-again:
-	sendalot = 0;
-	off = cb->s_snxt - cb->s_rack;
-	win = min(cb->s_swnd, (cb->s_cwnd / CUNIT));
-
-	/*
-	 * If in persist timeout with window of 0, send a probe.  Otherwise,
-	 * if window is small but non-zero and timer expired, send what we
-	 * can and go into transmit state.
-	 */
-	if (cb->s_force == 1 + SPXT_PERSIST) {
-		if (win != 0) {
-			cb->s_timer[SPXT_PERSIST] = 0;
-			cb->s_rxtshift = 0;
-		}
-	}
-	span = cb->s_seq - cb->s_rack;
-	len = min(span, win) - off;
-
-	if (len < 0) {
-		/*
-		 * Window shrank after we went into it.  If window shrank to
-		 * 0, cancel pending restransmission and pull s_snxt back to
-		 * (closed) window.  We will enter persist state below.  If
-		 * the widndow didn't close completely, just wait for an ACK.
-		 */
-		len = 0;
-		if (win == 0) {
-			cb->s_timer[SPXT_REXMT] = 0;
-			cb->s_snxt = cb->s_rack;
-		}
-	}
-	if (len > 1)
-		sendalot = 1;
-	rcv_win = sbspace(&so->so_rcv);
-
-	/*
-	 * Send if we owe peer an ACK.
-	 */
-	if (cb->s_oobflags & SF_SOOB) {
-		/*
-		 * Must transmit this out of band packet.
-		 */
-		cb->s_oobflags &= ~ SF_SOOB;
-		sendalot = 1;
-		spxstat.spxs_sndurg++;
-		goto found;
-	}
-	if (cb->s_flags & SF_ACKNOW)
-		goto send;
-	if (cb->s_state < TCPS_ESTABLISHED)
-		goto send;
-
-	/*
-	 * Silly window can't happen in spx.  Code from TCP deleted.
-	 */
-	if (len)
-		goto send;
-
-	/*
-	 * Compare available window to amount of window known to peer (as
-	 * advertised window less next expected input.)  If the difference is
-	 * at least two packets or at least 35% of the mximum possible
-	 * window, then want to send a window update to peer.
-	 */
-	if (rcv_win > 0) {
-		u_short delta =  1 + cb->s_alo - cb->s_ack;
-		int adv = rcv_win - (delta * cb->s_mtu);
-
-		if ((so->so_rcv.sb_cc == 0 && adv >= (2 * cb->s_mtu)) ||
-		    (100 * adv / so->so_rcv.sb_hiwat >= 35)) {
-			spxstat.spxs_sndwinup++;
-			cb->s_flags |= SF_ACKNOW;
-			goto send;
-		}
-
-	}
-
-	/*
-	 * Many comments from tcp_output.c are appropriate here including ...
-	 * If send window is too small, there is data to transmit, and no
-	 * retransmit or persist is pending, then go to persist state.  If
-	 * nothing happens soon, send when timer expires: if window is
-	 * non-zero, transmit what we can, otherwise send a probe.
-	 */
-	if (so->so_snd.sb_cc && cb->s_timer[SPXT_REXMT] == 0 &&
-	    cb->s_timer[SPXT_PERSIST] == 0) {
-		cb->s_rxtshift = 0;
-		spx_setpersist(cb);
-	}
-
-	/*
-	 * No reason to send a packet, just return.
-	 */
-	cb->s_outx = 1;
-	return (0);
-
-send:
-	/*
-	 * Find requested packet.
-	 */
-	si = 0;
-	if (len > 0) {
-		cb->s_want = cb->s_snxt;
-		for (m = sb->sb_mb; m != NULL; m = m->m_act) {
-			si = mtod(m, struct spx *);
-			if (SSEQ_LEQ(cb->s_snxt, si->si_seq))
-				break;
-		}
-	found:
-		if (si != NULL) {
-			if (si->si_seq == cb->s_snxt)
-					cb->s_snxt++;
-				else
-					spxstat.spxs_sndvoid++, si = 0;
-		}
-	}
-
-	/*
-	 * Update window.
-	 */
-	if (rcv_win < 0)
-		rcv_win = 0;
-	alo = cb->s_ack - 1 + (rcv_win / ((short)cb->s_mtu));
-	if (SSEQ_LT(alo, cb->s_alo))
-		alo = cb->s_alo;
-
-	if (si != NULL) {
-		/*
-		 * Must make a copy of this packet for ipx_output to monkey
-		 * with.
-		 */
-		m = m_copy(dtom(si), 0, (int)M_COPYALL);
-		if (m == NULL)
-			return (ENOBUFS);
-		si = mtod(m, struct spx *);
-		if (SSEQ_LT(si->si_seq, cb->s_smax))
-			spxstat.spxs_sndrexmitpack++;
-		else
-			spxstat.spxs_sndpack++;
-	} else if (cb->s_force || cb->s_flags & SF_ACKNOW) {
-		/*
-		 * Must send an acknowledgement or a probe.
-		 */
-		if (cb->s_force)
-			spxstat.spxs_sndprobe++;
-		if (cb->s_flags & SF_ACKNOW)
-			spxstat.spxs_sndacks++;
-		m = m_gethdr(M_DONTWAIT, MT_DATA);
-		if (m == NULL)
-			return (ENOBUFS);
-
-		/*
-		 * Fill in mbuf with extended SP header and addresses and
-		 * length put into network format.
-		 */
-		MH_ALIGN(m, sizeof(struct spx));
-		m->m_len = sizeof(*si);
-		m->m_pkthdr.len = sizeof(*si);
-		si = mtod(m, struct spx *);
-		si->si_i = *cb->s_ipx;
-		si->si_s = cb->s_shdr;
-		si->si_seq = cb->s_smax + 1;
-		si->si_len = htons(sizeof(*si));
-		si->si_cc |= SPX_SP;
-	} else {
-		cb->s_outx = 3;
-		if (so->so_options & SO_DEBUG || traceallspxs)
-			spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
-		return (0);
-	}
-
-	/*
-	 * Stuff checksum and output datagram.
-	 */
-	if ((si->si_cc & SPX_SP) == 0) {
-		if (cb->s_force != (1 + SPXT_PERSIST) ||
-		    cb->s_timer[SPXT_PERSIST] == 0) {
-			/*
-			 * If this is a new packet and we are not currently
-			 * timing anything, time this one.
-			 */
-			if (SSEQ_LT(cb->s_smax, si->si_seq)) {
-				cb->s_smax = si->si_seq;
-				if (cb->s_rtt == 0) {
-					spxstat.spxs_segstimed++;
-					cb->s_rtseq = si->si_seq;
-					cb->s_rtt = 1;
-				}
-			}
-
-			/*
-			 * Set rexmt timer if not currently set, initial
-			 * value for retransmit timer is smoothed round-trip
-			 * time + 2 * round-trip time variance.  Initialize
-			 * shift counter which is used for backoff of
-			 * retransmit time.
-			 */
-			if (cb->s_timer[SPXT_REXMT] == 0 &&
-			    cb->s_snxt != cb->s_rack) {
-				cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
-				if (cb->s_timer[SPXT_PERSIST]) {
-					cb->s_timer[SPXT_PERSIST] = 0;
-					cb->s_rxtshift = 0;
-				}
-			}
-		} else if (SSEQ_LT(cb->s_smax, si->si_seq))
-			cb->s_smax = si->si_seq;
-	} else if (cb->s_state < TCPS_ESTABLISHED) {
-		if (cb->s_rtt == 0)
-			cb->s_rtt = 1; /* Time initial handshake */
-		if (cb->s_timer[SPXT_REXMT] == 0)
-			cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
-	}
-
-	/*
-	 * Do not request acks when we ack their data packets or when we do a
-	 * gratuitous window update.
-	 */
-	if (((si->si_cc & SPX_SP) == 0) || cb->s_force)
-		si->si_cc |= SPX_SA;
-	si->si_seq = htons(si->si_seq);
-	si->si_alo = htons(alo);
-	si->si_ack = htons(cb->s_ack);
-
-	if (ipxcksum)
-		si->si_sum = ipx_cksum(m, ntohs(si->si_len));
-	else
-		si->si_sum = 0xffff;
-
-	cb->s_outx = 4;
-	if (so->so_options & SO_DEBUG || traceallspxs)
-		spx_trace(SA_OUTPUT, cb->s_state, cb, si, 0);
-
-	if (so->so_options & SO_DONTROUTE)
-		error = ipx_outputfl(m, NULL, IPX_ROUTETOIF);
-	else
-		error = ipx_outputfl(m, &cb->s_ipxpcb->ipxp_route, 0);
-	if (error)
-		return (error);
-	spxstat.spxs_sndtotal++;
-
-	/*
-	 * Data sent (as far as we can tell).  If this advertises a larger
-	 * window than any other segment, then remember the size of the
-	 * advertized window.  Any pending ACK has now been sent.
-	 */
-	cb->s_force = 0;
-	cb->s_flags &= ~(SF_ACKNOW|SF_DELACK);
-	if (SSEQ_GT(alo, cb->s_alo))
-		cb->s_alo = alo;
-	if (sendalot)
-		goto again;
-	cb->s_outx = 5;
-	return (0);
-}
-
-static int spx_do_persist_panics = 0;
-
-static void
-spx_setpersist(struct spxpcb *cb)
-{
-	int t = ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1;
-
-	IPX_LOCK_ASSERT(cb->s_ipxpcb);
-
-	if (cb->s_timer[SPXT_REXMT] && spx_do_persist_panics)
-		panic("spx_output REXMT");
-
-	/*
-	 * Start/restart persistance timer.
-	 */
-	SPXT_RANGESET(cb->s_timer[SPXT_PERSIST],
-	    t*spx_backoff[cb->s_rxtshift],
-	    SPXTV_PERSMIN, SPXTV_PERSMAX);
-	if (cb->s_rxtshift < SPX_MAXRXTSHIFT)
-		cb->s_rxtshift++;
-}
-
-int
-spx_ctloutput(struct socket *so, struct sockopt *sopt)
-{
-	struct spxhdr spxhdr;
-	struct ipxpcb *ipxp;
-	struct spxpcb *cb;
-	int mask, error;
-	short soptval;
-	u_short usoptval;
-	int optval;
-
-	ipxp = sotoipxpcb(so);
-	KASSERT(ipxp != NULL, ("spx_ctloutput: ipxp == NULL"));
-
-	/*
-	 * This will have to be changed when we do more general stacking of
-	 * protocols.
-	 */
-	if (sopt->sopt_level != IPXPROTO_SPX)
-		return (ipx_ctloutput(so, sopt));
-
-	IPX_LOCK(ipxp);
-	if (ipxp->ipxp_flags & IPXP_DROPPED) {
-		IPX_UNLOCK(ipxp);
-		return (ECONNRESET);
-	}
-
-	IPX_LOCK(ipxp);
-	cb = ipxtospxpcb(ipxp);
-	KASSERT(cb != NULL, ("spx_ctloutput: cb == NULL"));
-
-	error = 0;
-	switch (sopt->sopt_dir) {
-	case SOPT_GET:
-		switch (sopt->sopt_name) {
-		case SO_HEADERS_ON_INPUT:
-			mask = SF_HI;
-			goto get_flags;
-
-		case SO_HEADERS_ON_OUTPUT:
-			mask = SF_HO;
-		get_flags:
-			soptval = cb->s_flags & mask;
-			IPX_UNLOCK(ipxp);
-			error = sooptcopyout(sopt, &soptval,
-			    sizeof(soptval));
-			break;
-
-		case SO_MTU:
-			usoptval = cb->s_mtu;
-			IPX_UNLOCK(ipxp);
-			error = sooptcopyout(sopt, &usoptval,
-			    sizeof(usoptval));
-			break;
-
-		case SO_LAST_HEADER:
-			spxhdr = cb->s_rhdr;
-			IPX_UNLOCK(ipxp);
-			error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
-			break;
-
-		case SO_DEFAULT_HEADERS:
-			spxhdr = cb->s_shdr;
-			IPX_UNLOCK(ipxp);
-			error = sooptcopyout(sopt, &spxhdr, sizeof(spxhdr));
-			break;
-
-		default:
-			IPX_UNLOCK(ipxp);
-			error = ENOPROTOOPT;
-		}
-		break;
-
-	case SOPT_SET:
-		/*
-		 * XXX Why are these shorts on get and ints on set?  That
-		 * doesn't make any sense...
-		 *
-		 * XXXRW: Note, when we re-acquire the ipxp lock, we should
-		 * re-check that it's not dropped.
-		 */
-		IPX_UNLOCK(ipxp);
-		switch (sopt->sopt_name) {
-		case SO_HEADERS_ON_INPUT:
-			mask = SF_HI;
-			goto set_head;
-
-		case SO_HEADERS_ON_OUTPUT:
-			mask = SF_HO;
-		set_head:
-			error = sooptcopyin(sopt, &optval, sizeof optval,
-					    sizeof optval);
-			if (error)
-				break;
-
-			IPX_LOCK(ipxp);
-			if (cb->s_flags & SF_PI) {
-				if (optval)
-					cb->s_flags |= mask;
-				else
-					cb->s_flags &= ~mask;
-			} else error = EINVAL;
-			IPX_UNLOCK(ipxp);
-			break;
-
-		case SO_MTU:
-			error = sooptcopyin(sopt, &usoptval, sizeof usoptval,
-					    sizeof usoptval);
-			if (error)
-				break;
-			/* Unlocked write. */
-			cb->s_mtu = usoptval;
-			break;
-
-#ifdef SF_NEWCALL
-		case SO_NEWCALL:
-			error = sooptcopyin(sopt, &optval, sizeof optval,
-					    sizeof optval);
-			if (error)
-				break;
-			IPX_LOCK(ipxp);
-			if (optval) {
-				cb->s_flags2 |= SF_NEWCALL;
-				spx_newchecks[5]++;
-			} else {
-				cb->s_flags2 &= ~SF_NEWCALL;
-				spx_newchecks[6]++;
-			}
-			IPX_UNLOCK(ipxp);
-			break;
-#endif
-
-		case SO_DEFAULT_HEADERS:
-			{
-				struct spxhdr sp;
-
-				error = sooptcopyin(sopt, &sp, sizeof sp,
-						    sizeof sp);
-				if (error)
-					break;
-				IPX_LOCK(ipxp);
-				cb->s_dt = sp.spx_dt;
-				cb->s_cc = sp.spx_cc & SPX_EM;
-				IPX_UNLOCK(ipxp);
-			}
-			break;
-
-		default:
-			error = ENOPROTOOPT;
-		}
-		break;
-
-	default:
-		panic("spx_ctloutput: bad socket option direction");
-	}
-	return (error);
-}
-
-static void
-spx_usr_abort(struct socket *so)
-{
-	struct ipxpcb *ipxp;
-	struct spxpcb *cb;
-
-	ipxp = sotoipxpcb(so);
-	KASSERT(ipxp != NULL, ("spx_usr_abort: ipxp == NULL"));
-
-	cb = ipxtospxpcb(ipxp);
-	KASSERT(cb != NULL, ("spx_usr_abort: cb == NULL"));
-
-	IPX_LIST_LOCK();
-	IPX_LOCK(ipxp);
-	spx_drop(cb, ECONNABORTED);
-	IPX_UNLOCK(ipxp);
-	IPX_LIST_UNLOCK();
-}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200905250928.n4P9StAR017933>