Author: rwatson
Date: Sat Jun 20 18:24:25 2009
New Revision: 194547
URL: http://svn.freebsd.org/changeset/base/194547

Log:
  Rework SPX segment reassembly, which was originally based on our TCP
  reassembly but failed to be modernized over time:
  
  - Use queue(9).
  - Specifically allocate queue entries of type M_SPXREASSQ to point at
    member mbufs, rather than casting mbuf data to 'spx_q'.
  - Maintain the mbuf pointer as part of the queue entry so that we can
    later free the mbuf without using dtom().

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

Modified: head/sys/netipx/spx.h
==============================================================================
--- head/sys/netipx/spx.h       Sat Jun 20 18:13:20 2009        (r194546)
+++ head/sys/netipx/spx.h       Sat Jun 20 18:24:25 2009        (r194547)
@@ -91,8 +91,9 @@ struct spx {
        struct spxhdr   si_s;
 } __packed;
 struct spx_q {
-       struct spx_q    *si_next;
-       struct spx_q    *si_prev;
+       struct mbuf             *sq_msi;
+       struct spx              *sq_si;
+       LIST_ENTRY(spx_q)        sq_entry;
 };
 #define SI(x)  ((struct spx *)x)
 #define si_sum si_i.ipx_sum
@@ -114,7 +115,7 @@ struct spx_q {
  * SPX control block, one per connection
  */
 struct spxpcb {
-       struct  spx_q   s_q;            /* queue for out-of-order receipt */
+       LIST_HEAD(, spx_q)      s_q;    /* queue for out-of-order receipt */
        struct  ipxpcb  *s_ipxpcb;      /* backpointer to internet pcb */
        u_char  s_state;
        u_char  s_flags;

Modified: head/sys/netipx/spx_reass.c
==============================================================================
--- head/sys/netipx/spx_reass.c Sat Jun 20 18:13:20 2009        (r194546)
+++ head/sys/netipx/spx_reass.c Sat Jun 20 18:24:25 2009        (r194547)
@@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/lock.h>
+#include <sys/kernel.h>
 #include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mutex.h>
@@ -92,24 +93,7 @@ __FBSDID("$FreeBSD$");
 static int     spx_use_delack = 0;
 static int     spxrexmtthresh = 3;
 
-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 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;
-}
+MALLOC_DEFINE(M_SPXREASSQ, "spxreassq", "SPX reassembly queue entry");
 
 /*
  * Flesh pending queued segments on SPX close.
@@ -117,15 +101,12 @@ spx_remque(struct spx_q *element)
 void
 spx_reass_flush(struct spxpcb *cb)
 {
-       struct spx_q *s;
-       struct mbuf *m;
+       struct spx_q *q;
 
-       s = cb->s_q.si_next;
-       while (s != &(cb->s_q)) {
-               s = s->si_next;
-               spx_remque(s);
-               m = dtom(s);
-               m_freem(m);
+       while ((q = LIST_FIRST(&cb->s_q)) != NULL) {
+               LIST_REMOVE(q, sq_entry);
+               m_freem(q->sq_msi);
+               free(q, M_SPXREASSQ);
        }
 }
 
@@ -136,7 +117,7 @@ void
 spx_reass_init(struct spxpcb *cb)
 {
 
-       cb->s_q.si_next = cb->s_q.si_prev = &cb->s_q;
+       LIST_INIT(&cb->s_q);
 }
 
 /*
@@ -145,9 +126,9 @@ spx_reass_init(struct spxpcb *cb)
  * suppresses duplicates.
  */
 int
-spx_reass(struct spxpcb *cb, struct spx *si)
+spx_reass(struct spxpcb *cb, struct mbuf *msi, struct spx *si)
 {
-       struct spx_q *q;
+       struct spx_q *q, *q_new, *q_temp;
        struct mbuf *m;
        struct socket *so = cb->s_ipxpcb->ipxp_socket;
        char packetp = cb->s_flags & SF_HI;
@@ -352,17 +333,26 @@ update_window:
         * 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) {
+       q_new = malloc(sizeof(*q_new), M_SPXREASSQ, M_NOWAIT | M_ZERO);
+       if (q_new == NULL)
+               return (1);
+       q_new->sq_si = si;
+       q_new->sq_msi = msi;
+       LIST_FOREACH(q, &cb->s_q, sq_entry) {
+               if (si->si_seq == q->sq_si->si_seq) {
+                       free(q_new, M_SPXREASSQ);
                        spxstat.spxs_rcvduppack++;
                        return (1);
                }
-               if (SSEQ_LT(si->si_seq, SI(q)->si_seq)) {
+               if (SSEQ_LT(si->si_seq, q->sq_si->si_seq)) {
                        spxstat.spxs_rcvoopack++;
                        break;
                }
        }
-       spx_insque((struct spx_q *)si, q->si_prev);
+       if (q != NULL)
+               LIST_INSERT_BEFORE(q, q_new, sq_entry);
+       else
+               LIST_INSERT_HEAD(&cb->s_q, q_new, sq_entry);
 
        /*
         * If this packet is urgent, inform process
@@ -381,25 +371,31 @@ present:
         * 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) {
+       LIST_FOREACH_SAFE(q, &cb->s_q, sq_entry, q_temp) {
+               struct spx *qsi;
+               struct mbuf *mqsi;
+
+               qsi = q->sq_si;
+               mqsi = q->sq_msi;
+               if (qsi->si_seq == cb->s_ack) {
                        cb->s_ack++;
-                       m = dtom(q);
-                       if (SI(q)->si_cc & SPX_OB) {
+                       if (qsi->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);
+                       LIST_REMOVE(q, sq_entry);
+                       free(q, M_SPXREASSQ);
                        wakeup = 1;
                        spxstat.spxs_rcvpack++;
 #ifdef SF_NEWCALL
                        if (cb->s_flags2 & SF_NEWCALL) {
-                               struct spxhdr *sp = mtod(m, struct spxhdr *);
+                               struct spxhdr *sp =
+                                   mtod(mqsi, struct spxhdr *);
                                u_char dt = sp->spx_dt;
+
                                spx_newchecks[4]++;
                                if (dt != cb->s_rhdr.spx_dt) {
                                        struct mbuf *mm =
@@ -417,31 +413,32 @@ present:
                                        }
                                }
                                if (sp->spx_cc & SPX_OB) {
-                                       MCHTYPE(m, MT_OOBDATA);
+                                       MCHTYPE(mqsi, 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;
+                                       mqsi->m_data += SPINC;
+                                       mqsi->m_len -= SPINC;
+                                       mqsi->m_pkthdr.len -= SPINC;
                                }
                                if ((sp->spx_cc & SPX_EM) || packetp) {
-                                       sbappendrecord_locked(&so->so_rcv, m);
+                                       sbappendrecord_locked(&so->so_rcv,
+                                           mqsi);
                                        spx_newchecks[9]++;
                                } else
-                                       sbappend_locked(&so->so_rcv, m);
+                                       sbappend_locked(&so->so_rcv, mqsi);
                        } else
 #endif
                        if (packetp)
-                               sbappendrecord_locked(&so->so_rcv, m);
+                               sbappendrecord_locked(&so->so_rcv, mqsi);
                        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);
+                               cb->s_rhdr = *mtod(mqsi, struct spxhdr *);
+                               mqsi->m_data += SPINC;
+                               mqsi->m_len -= SPINC;
+                               mqsi->m_pkthdr.len -= SPINC;
+                               sbappend_locked(&so->so_rcv, mqsi);
                        }
                  } else
                        break;

Modified: head/sys/netipx/spx_usrreq.c
==============================================================================
--- head/sys/netipx/spx_usrreq.c        Sat Jun 20 18:13:20 2009        
(r194546)
+++ head/sys/netipx/spx_usrreq.c        Sat Jun 20 18:24:25 2009        
(r194547)
@@ -378,7 +378,7 @@ spx_input(struct mbuf *m, struct ipxpcb 
        m->m_pkthdr.len -= sizeof(struct ipx);
        m->m_data += sizeof(struct ipx);
 
-       if (spx_reass(cb, si))
+       if (spx_reass(cb, m, si))
                m_freem(m);
        if (cb->s_force || (cb->s_flags & (SF_ACKNOW|SF_WIN|SF_RXT)))
                spx_output(cb, NULL);

Modified: head/sys/netipx/spx_var.h
==============================================================================
--- head/sys/netipx/spx_var.h   Sat Jun 20 18:13:20 2009        (r194546)
+++ head/sys/netipx/spx_var.h   Sat Jun 20 18:24:25 2009        (r194547)
@@ -152,7 +152,7 @@ extern struct spx_istat     spx_istat;
 extern u_short spx_newchecks[50];
 
 int    spx_output(struct spxpcb *cb, struct mbuf *m0);
-int    spx_reass(struct spxpcb *cb, struct spx *si);
+int    spx_reass(struct spxpcb *cb, struct mbuf *msi, struct spx *si);
 void   spx_reass_flush(struct spxpcb *cb);
 void   spx_reass_init(struct spxpcb *cb);
 #endif
_______________________________________________
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