summaryrefslogtreecommitdiffstats
path: root/sys/netipx/spx_usrreq.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-05-25 09:28:54 +0000
committerrwatson <rwatson@FreeBSD.org>2009-05-25 09:28:54 +0000
commit0fa1d2d60304ec9e565e124f230edfd6144d4e0e (patch)
tree1824d1f5e82da65aa39cefa6239933197c94966a /sys/netipx/spx_usrreq.c
parentc60c7e0b06b9ba8e327e7c42a0125442344971d6 (diff)
downloadFreeBSD-src-0fa1d2d60304ec9e565e124f230edfd6144d4e0e.zip
FreeBSD-src-0fa1d2d60304ec9e565e124f230edfd6144d4e0e.tar.gz
Complete move of SPX reassembly from spx_usrreq.c to spx_reass.c.
MFC after: 1 month
Diffstat (limited to 'sys/netipx/spx_usrreq.c')
-rw-r--r--sys/netipx/spx_usrreq.c355
1 files changed, 3 insertions, 352 deletions
diff --git a/sys/netipx/spx_usrreq.c b/sys/netipx/spx_usrreq.c
index 7bfa88e..8ca3ce4 100644
--- a/sys/netipx/spx_usrreq.c
+++ b/sys/netipx/spx_usrreq.c
@@ -94,30 +94,21 @@ __FBSDID("$FreeBSD$");
*/
static struct mtx spx_mtx; /* Protects only spx_iss. */
static u_short spx_iss;
-static u_short spx_newchecks[50];
+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;
+struct spx_istat spx_istat;
#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);
@@ -180,25 +171,6 @@ struct pr_usrreqs spx_usrreq_sps = {
.pru_close = spx_usr_close,
};
-static __inline void
-spx_insque(struct spx_q *element, struct spx_q *head)
-{
-
- element->si_next = head->si_next;
- element->si_prev = head;
- head->si_next = element;
- element->si_next->si_prev = element;
-}
-
-static __inline void
-spx_remque(struct spx_q *element)
-{
-
- element->si_next->si_prev = element->si_prev;
- element->si_prev->si_next = element->si_next;
- element->si_prev = NULL;
-}
-
void
spx_init(void)
{
@@ -445,328 +417,7 @@ drop:
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
-spx_reass(struct spxpcb *cb, struct spx *si)
-{
- struct spx_q *q;
- struct mbuf *m;
- struct socket *so = cb->s_ipxpcb->ipxp_socket;
- char packetp = cb->s_flags & SF_HI;
- int incr;
- char wakeup = 0;
-
- IPX_LOCK_ASSERT(cb->s_ipxpcb);
-
- if (si == SI(0))
- goto present;
-
- /*
- * Update our news from them.
- */
- if (si->si_cc & SPX_SA)
- cb->s_flags |= (spx_use_delack ? SF_DELACK : SF_ACKNOW);
- if (SSEQ_GT(si->si_alo, cb->s_ralo))
- cb->s_flags |= SF_WIN;
- if (SSEQ_LEQ(si->si_ack, cb->s_rack)) {
- if ((si->si_cc & SPX_SP) && cb->s_rack != (cb->s_smax + 1)) {
- spxstat.spxs_rcvdupack++;
-
- /*
- * If this is a completely duplicate ack and other
- * conditions hold, we assume a packet has been
- * dropped and retransmit it exactly as in
- * tcp_input().
- */
- if (si->si_ack != cb->s_rack ||
- si->si_alo != cb->s_ralo)
- cb->s_dupacks = 0;
- else if (++cb->s_dupacks == spxrexmtthresh) {
- u_short onxt = cb->s_snxt;
- int cwnd = cb->s_cwnd;
-
- cb->s_snxt = si->si_ack;
- cb->s_cwnd = CUNIT;
- cb->s_force = 1 + SPXT_REXMT;
- spx_output(cb, NULL);
- cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
- cb->s_rtt = 0;
- if (cwnd >= 4 * CUNIT)
- cb->s_cwnd = cwnd / 2;
- if (SSEQ_GT(onxt, cb->s_snxt))
- cb->s_snxt = onxt;
- return (1);
- }
- } else
- cb->s_dupacks = 0;
- goto update_window;
- }
- cb->s_dupacks = 0;
-
- /*
- * If our correspondent acknowledges data we haven't sent TCP would
- * drop the packet after acking. We'll be a little more permissive.
- */
- if (SSEQ_GT(si->si_ack, (cb->s_smax + 1))) {
- spxstat.spxs_rcvacktoomuch++;
- si->si_ack = cb->s_smax + 1;
- }
- spxstat.spxs_rcvackpack++;
-
- /*
- * If transmit timer is running and timed sequence number was acked,
- * update smoothed round trip time. See discussion of algorithm in
- * tcp_input.c
- */
- if (cb->s_rtt && SSEQ_GT(si->si_ack, cb->s_rtseq)) {
- spxstat.spxs_rttupdated++;
- if (cb->s_srtt != 0) {
- short delta;
- delta = cb->s_rtt - (cb->s_srtt >> 3);
- if ((cb->s_srtt += delta) <= 0)
- cb->s_srtt = 1;
- if (delta < 0)
- delta = -delta;
- delta -= (cb->s_rttvar >> 2);
- if ((cb->s_rttvar += delta) <= 0)
- cb->s_rttvar = 1;
- } else {
- /*
- * No rtt measurement yet.
- */
- cb->s_srtt = cb->s_rtt << 3;
- cb->s_rttvar = cb->s_rtt << 1;
- }
- cb->s_rtt = 0;
- cb->s_rxtshift = 0;
- SPXT_RANGESET(cb->s_rxtcur,
- ((cb->s_srtt >> 2) + cb->s_rttvar) >> 1,
- SPXTV_MIN, SPXTV_REXMTMAX);
- }
-
- /*
- * If all outstanding data is acked, stop retransmit timer and
- * remember to restart (more output or persist). If there is more
- * data to be acked, restart retransmit timer, using current
- * (possibly backed-off) value;
- */
- if (si->si_ack == cb->s_smax + 1) {
- cb->s_timer[SPXT_REXMT] = 0;
- cb->s_flags |= SF_RXT;
- } else if (cb->s_timer[SPXT_PERSIST] == 0)
- cb->s_timer[SPXT_REXMT] = cb->s_rxtcur;
-
- /*
- * When new data is acked, open the congestion window. If the window
- * gives us less than ssthresh packets in flight, open exponentially
- * (maxseg at a time). Otherwise open linearly (maxseg^2 / cwnd at a
- * time).
- */
- incr = CUNIT;
- if (cb->s_cwnd > cb->s_ssthresh)
- incr = max(incr * incr / cb->s_cwnd, 1);
- cb->s_cwnd = min(cb->s_cwnd + incr, cb->s_cwmx);
-
- /*
- * Trim Acked data from output queue.
- */
- SOCKBUF_LOCK(&so->so_snd);
- while ((m = so->so_snd.sb_mb) != NULL) {
- if (SSEQ_LT((mtod(m, struct spx *))->si_seq, si->si_ack))
- sbdroprecord_locked(&so->so_snd);
- else
- break;
- }
- sowwakeup_locked(so);
- cb->s_rack = si->si_ack;
-update_window:
- if (SSEQ_LT(cb->s_snxt, cb->s_rack))
- cb->s_snxt = cb->s_rack;
- if (SSEQ_LT(cb->s_swl1, si->si_seq) || ((cb->s_swl1 == si->si_seq &&
- (SSEQ_LT(cb->s_swl2, si->si_ack))) ||
- (cb->s_swl2 == si->si_ack && SSEQ_LT(cb->s_ralo, si->si_alo)))) {
- /* keep track of pure window updates */
- if ((si->si_cc & SPX_SP) && cb->s_swl2 == si->si_ack
- && SSEQ_LT(cb->s_ralo, si->si_alo)) {
- spxstat.spxs_rcvwinupd++;
- spxstat.spxs_rcvdupack--;
- }
- cb->s_ralo = si->si_alo;
- cb->s_swl1 = si->si_seq;
- cb->s_swl2 = si->si_ack;
- cb->s_swnd = (1 + si->si_alo - si->si_ack);
- if (cb->s_swnd > cb->s_smxw)
- cb->s_smxw = cb->s_swnd;
- cb->s_flags |= SF_WIN;
- }
-
- /*
- * If this packet number is higher than that which we have allocated
- * refuse it, unless urgent.
- */
- if (SSEQ_GT(si->si_seq, cb->s_alo)) {
- if (si->si_cc & SPX_SP) {
- spxstat.spxs_rcvwinprobe++;
- return (1);
- } else
- spxstat.spxs_rcvpackafterwin++;
- if (si->si_cc & SPX_OB) {
- if (SSEQ_GT(si->si_seq, cb->s_alo + 60))
- return (1); /* else queue this packet; */
- } else {
-#ifdef BROKEN
- /*
- * XXXRW: This is broken on at least one count:
- * spx_close() will free the ipxp and related parts,
- * which are then touched by spx_input() after the
- * return from spx_reass().
- */
- /*struct socket *so = cb->s_ipxpcb->ipxp_socket;
- if (so->so_state && SS_NOFDREF) {
- spx_close(cb);
- } else
- would crash system*/
-#endif
- spx_istat.notyet++;
- return (1);
- }
- }
-
- /*
- * If this is a system packet, we don't need to queue it up, and
- * won't update acknowledge #.
- */
- if (si->si_cc & SPX_SP)
- return (1);
-
- /*
- * We have already seen this packet, so drop.
- */
- if (SSEQ_LT(si->si_seq, cb->s_ack)) {
- spx_istat.bdreas++;
- spxstat.spxs_rcvduppack++;
- if (si->si_seq == cb->s_ack - 1)
- spx_istat.lstdup++;
- return (1);
- }
-
- /*
- * Loop through all packets queued up to insert in appropriate
- * sequence.
- */
- for (q = cb->s_q.si_next; q != &cb->s_q; q = q->si_next) {
- if (si->si_seq == SI(q)->si_seq) {
- spxstat.spxs_rcvduppack++;
- return (1);
- }
- if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) {
- spxstat.spxs_rcvoopack++;
- break;
- }
- }
- spx_insque((struct spx_q *)si, q->si_prev);
-
- /*
- * If this packet is urgent, inform process
- */
- if (si->si_cc & SPX_OB) {
- cb->s_iobc = ((char *)si)[1 + sizeof(*si)];
- sohasoutofband(so);
- cb->s_oobflags |= SF_IOOB;
- }
-present:
-#define SPINC sizeof(struct spxhdr)
- SOCKBUF_LOCK(&so->so_rcv);
-
- /*
- * Loop through all packets queued up to update acknowledge number,
- * and present all acknowledged data to user; if in packet interface
- * mode, show packet headers.
- */
- for (q = cb->s_q.si_next; q != &cb->s_q; q = q->si_next) {
- if (SI(q)->si_seq == cb->s_ack) {
- cb->s_ack++;
- m = dtom(q);
- if (SI(q)->si_cc & SPX_OB) {
- cb->s_oobflags &= ~SF_IOOB;
- if (so->so_rcv.sb_cc)
- so->so_oobmark = so->so_rcv.sb_cc;
- else
- so->so_rcv.sb_state |= SBS_RCVATMARK;
- }
- q = q->si_prev;
- spx_remque(q->si_next);
- wakeup = 1;
- spxstat.spxs_rcvpack++;
-#ifdef SF_NEWCALL
- if (cb->s_flags2 & SF_NEWCALL) {
- struct spxhdr *sp = mtod(m, struct spxhdr *);
- u_char dt = sp->spx_dt;
- spx_newchecks[4]++;
- if (dt != cb->s_rhdr.spx_dt) {
- struct mbuf *mm =
- m_getclr(M_DONTWAIT, MT_CONTROL);
- spx_newchecks[0]++;
- if (mm != NULL) {
- u_short *s =
- mtod(mm, u_short *);
- cb->s_rhdr.spx_dt = dt;
- mm->m_len = 5; /*XXX*/
- s[0] = 5;
- s[1] = 1;
- *(u_char *)(&s[2]) = dt;
- sbappend_locked(&so->so_rcv, mm);
- }
- }
- if (sp->spx_cc & SPX_OB) {
- MCHTYPE(m, MT_OOBDATA);
- spx_newchecks[1]++;
- so->so_oobmark = 0;
- so->so_rcv.sb_state &= ~SBS_RCVATMARK;
- }
- if (packetp == 0) {
- m->m_data += SPINC;
- m->m_len -= SPINC;
- m->m_pkthdr.len -= SPINC;
- }
- if ((sp->spx_cc & SPX_EM) || packetp) {
- sbappendrecord_locked(&so->so_rcv, m);
- spx_newchecks[9]++;
- } else
- sbappend_locked(&so->so_rcv, m);
- } else
-#endif
- if (packetp)
- sbappendrecord_locked(&so->so_rcv, m);
- else {
- cb->s_rhdr = *mtod(m, struct spxhdr *);
- m->m_data += SPINC;
- m->m_len -= SPINC;
- m->m_pkthdr.len -= SPINC;
- sbappend_locked(&so->so_rcv, m);
- }
- } else
- break;
- }
- if (wakeup)
- sorwakeup_locked(so);
- else
- SOCKBUF_UNLOCK(&so->so_rcv);
- return (0);
-}
-
-void
-spx_ctlinput(int cmd, struct sockaddr *arg_as_sa, void *dummy)
-{
-
- /* Currently, nothing. */
-}
-
-static int
+int
spx_output(struct spxpcb *cb, struct mbuf *m0)
{
struct socket *so = cb->s_ipxpcb->ipxp_socket;
OpenPOWER on IntegriCloud