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 j...@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 ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to