Author: rrs
Date: Thu Feb  3 10:05:30 2011
New Revision: 218211
URL: http://svn.freebsd.org/changeset/base/218211

Log:
  Adds an experimental option to create a pool of
  threads. These serve as input threads and are queued
  packets based on the V-tag number. This is similar to
  what a modern card can do with queue's for TCP... but
  alas modern cards know nothing about SCTP.
  
  MFC after:    3 months (maybe)

Modified:
  head/sys/conf/options
  head/sys/netinet/sctp_bsd_addr.c
  head/sys/netinet/sctp_constants.h
  head/sys/netinet/sctp_input.c
  head/sys/netinet/sctp_lock_bsd.h
  head/sys/netinet/sctp_os_bsd.h
  head/sys/netinet/sctp_pcb.c
  head/sys/netinet/sctp_pcb.h
  head/sys/netinet/sctp_structs.h

Modified: head/sys/conf/options
==============================================================================
--- head/sys/conf/options       Thu Feb  3 08:55:45 2011        (r218210)
+++ head/sys/conf/options       Thu Feb  3 10:05:30 2011        (r218211)
@@ -439,6 +439,7 @@ SCTP_PACKET_LOGGING opt_sctp.h # Log to 
 SCTP_LTRACE_CHUNKS     opt_sctp.h # Log to KTR chunks processed
 SCTP_LTRACE_ERRORS     opt_sctp.h # Log to KTR error returns.
 SCTP_USE_PERCPU_STAT    opt_sctp.h # Use per cpu stats.
+SCTP_MCORE_INPUT        opt_sctp.h # Have multiple input threads for input 
mbufs
 #
 #
 #

Modified: head/sys/netinet/sctp_bsd_addr.c
==============================================================================
--- head/sys/netinet/sctp_bsd_addr.c    Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_bsd_addr.c    Thu Feb  3 10:05:30 2011        
(r218211)
@@ -68,6 +68,7 @@ MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", 
 MALLOC_DEFINE(SCTP_M_MVRF, "sctp_mvrf", "sctp mvrf pcb list");
 MALLOC_DEFINE(SCTP_M_ITER, "sctp_iter", "sctp iterator control");
 MALLOC_DEFINE(SCTP_M_SOCKOPT, "sctp_socko", "sctp socket option");
+MALLOC_DEFINE(SCTP_M_MCORE, "sctp_mcore", "sctp mcore queue");
 
 /* Global NON-VNET structure that controls the iterator */
 struct iterator_control sctp_it_ctl;

Modified: head/sys/netinet/sctp_constants.h
==============================================================================
--- head/sys/netinet/sctp_constants.h   Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_constants.h   Thu Feb  3 10:05:30 2011        
(r218211)
@@ -91,6 +91,8 @@ __FBSDID("$FreeBSD$");
 #define SCTP_KTRHEAD_NAME "sctp_iterator"
 #define SCTP_KTHREAD_PAGES 0
 
+#define SCTP_MCORE_NAME "sctp_core_worker"
+
 
 /* If you support Multi-VRF how big to
  * make the initial array of VRF's to.

Modified: head/sys/netinet/sctp_input.c
==============================================================================
--- head/sys/netinet/sctp_input.c       Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_input.c       Thu Feb  3 10:05:30 2011        
(r218211)
@@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$");
 #include <netinet/sctp_timer.h>
 #include <netinet/sctp_crc32.h>
 #include <netinet/udp.h>
+#include <sys/smp.h>
 
 
 
@@ -5921,10 +5922,32 @@ bad:
        }
        return;
 }
+
+
 void
-sctp_input(i_pak, off)
-       struct mbuf *i_pak;
-       int off;
+sctp_input(struct mbuf *m, int off)
 {
-       sctp_input_with_port(i_pak, off, 0);
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+       struct ip *ip;
+       struct sctphdr *sh;
+       int offset;
+       int cpu_to_use;
+
+       if (mp_ncpus > 1) {
+               ip = mtod(m, struct ip *);
+               offset = off + sizeof(*sh);
+               if (SCTP_BUF_LEN(m) < offset) {
+                       if ((m = m_pullup(m, offset)) == 0) {
+                               SCTP_STAT_INCR(sctps_hdrops);
+                               return;
+                       }
+                       ip = mtod(m, struct ip *);
+               }
+               sh = (struct sctphdr *)((caddr_t)ip + off);
+               cpu_to_use = ntohl(sh->v_tag) % mp_ncpus;
+               sctp_queue_to_mcore(m, off, cpu_to_use);
+               return;
+       }
+#endif
+       sctp_input_with_port(m, off, 0);
 }

Modified: head/sys/netinet/sctp_lock_bsd.h
==============================================================================
--- head/sys/netinet/sctp_lock_bsd.h    Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_lock_bsd.h    Thu Feb  3 10:05:30 2011        
(r218211)
@@ -97,6 +97,48 @@ extern int sctp_logoff_stuff;
              rw_rlock(&SCTP_BASE_INFO(ipi_ep_mtx));                         \
 } while (0)
 
+#define SCTP_MCORE_QLOCK_INIT(cpstr) do { \
+               mtx_init(&(cpstr)->que_mtx,           \
+                        "sctp-mcore_queue","queue_lock",       \
+                        MTX_DEF|MTX_DUPOK);            \
+} while (0)
+
+#define SCTP_MCORE_QLOCK(cpstr)  do { \
+               mtx_lock(&(cpstr)->que_mtx);    \
+} while (0)
+
+#define SCTP_MCORE_QUNLOCK(cpstr)  do { \
+               mtx_unlock(&(cpstr)->que_mtx);  \
+} while (0)
+
+#define SCTP_MCORE_QDESTROY(cpstr)  do { \
+       if(mtx_owned(&(cpstr)->core_mtx)) {     \
+               mtx_unlock(&(cpstr)->que_mtx);  \
+        } \
+       mtx_destroy(&(cpstr)->que_mtx); \
+} while (0)
+
+
+#define SCTP_MCORE_LOCK_INIT(cpstr) do { \
+               mtx_init(&(cpstr)->core_mtx,          \
+                        "sctp-cpulck","cpu_proc_lock", \
+                        MTX_DEF|MTX_DUPOK);            \
+} while (0)
+
+#define SCTP_MCORE_LOCK(cpstr)  do { \
+               mtx_lock(&(cpstr)->core_mtx);   \
+} while (0)
+
+#define SCTP_MCORE_UNLOCK(cpstr)  do { \
+               mtx_unlock(&(cpstr)->core_mtx); \
+} while (0)
+
+#define SCTP_MCORE_DESTROY(cpstr)  do { \
+       if(mtx_owned(&(cpstr)->core_mtx)) {     \
+               mtx_unlock(&(cpstr)->core_mtx); \
+        } \
+       mtx_destroy(&(cpstr)->core_mtx);        \
+} while (0)
 
 #define SCTP_INP_INFO_WLOCK()  do {                                    \
             rw_wlock(&SCTP_BASE_INFO(ipi_ep_mtx));                         \

Modified: head/sys/netinet/sctp_os_bsd.h
==============================================================================
--- head/sys/netinet/sctp_os_bsd.h      Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_os_bsd.h      Thu Feb  3 10:05:30 2011        
(r218211)
@@ -123,6 +123,7 @@ MALLOC_DECLARE(SCTP_M_TIMW);
 MALLOC_DECLARE(SCTP_M_MVRF);
 MALLOC_DECLARE(SCTP_M_ITER);
 MALLOC_DECLARE(SCTP_M_SOCKOPT);
+MALLOC_DECLARE(SCTP_M_MCORE);
 
 #if defined(SCTP_LOCAL_TRACE_BUF)
 

Modified: head/sys/netinet/sctp_pcb.c
==============================================================================
--- head/sys/netinet/sctp_pcb.c Thu Feb  3 08:55:45 2011        (r218210)
+++ head/sys/netinet/sctp_pcb.c Thu Feb  3 10:05:30 2011        (r218211)
@@ -47,6 +47,9 @@ __FBSDID("$FreeBSD$");
 #include <netinet/sctp_bsd_addr.h>
 #include <netinet/sctp_dtrace_define.h>
 #include <netinet/udp.h>
+#include <sys/sched.h>
+#include <sys/smp.h>
+#include <sys/unistd.h>
 
 
 VNET_DEFINE(struct sctp_base_info, system_base_info);
@@ -5435,6 +5438,148 @@ sctp_del_local_addr_restricted(struct sc
 static int sctp_max_number_of_assoc = SCTP_MAX_NUM_OF_ASOC;
 static int sctp_scale_up_for_address = SCTP_SCALE_FOR_ADDR;
 
+
+
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+struct sctp_mcore_ctrl *sctp_mcore_workers = NULL;
+
+void
+sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use)
+{
+       /* Queue a packet to a processor for the specified core */
+       struct sctp_mcore_queue *qent;
+       struct sctp_mcore_ctrl *wkq;
+       int need_wake = 0;
+
+       if (sctp_mcore_workers == NULL) {
+               /* Something went way bad during setup */
+               sctp_input_with_port(m, off, 0);
+               return;
+       }
+       SCTP_MALLOC(qent, struct sctp_mcore_queue *,
+           (sizeof(struct sctp_mcore_queue)),
+           SCTP_M_MCORE);
+       if (qent == NULL) {
+               /* This is trouble  */
+               sctp_input_with_port(m, off, 0);
+               return;
+       }
+       qent->vn = curvnet;
+       qent->m = m;
+       qent->off = off;
+       qent->v6 = 0;
+       wkq = &sctp_mcore_workers[cpu_to_use];
+       SCTP_MCORE_QLOCK(wkq);
+
+       TAILQ_INSERT_TAIL(&wkq->que, qent, next);
+       if (wkq->running == 0) {
+               need_wake = 1;
+       }
+       SCTP_MCORE_QUNLOCK(wkq);
+       if (need_wake) {
+               wakeup(&wkq->running);
+       }
+}
+
+static void
+sctp_mcore_thread(void *arg)
+{
+
+       struct sctp_mcore_ctrl *wkq;
+       struct sctp_mcore_queue *qent;
+
+       wkq = (struct sctp_mcore_ctrl *)arg;
+       struct mbuf *m;
+       int off, v6;
+
+       /* Wait for first tickle */
+       SCTP_MCORE_LOCK(wkq);
+       wkq->running = 0;
+       msleep(&wkq->running,
+           &wkq->core_mtx,
+           0, "wait for pkt", 0);
+       SCTP_MCORE_UNLOCK(wkq);
+
+       /* Bind to our cpu */
+       thread_lock(curthread);
+       sched_bind(curthread, wkq->cpuid);
+       thread_unlock(curthread);
+
+       /* Now lets start working */
+       SCTP_MCORE_LOCK(wkq);
+       /* Now grab lock and go */
+       while (1) {
+               SCTP_MCORE_QLOCK(wkq);
+skip_sleep:
+               wkq->running = 1;
+               qent = TAILQ_FIRST(&wkq->que);
+               if (qent) {
+                       TAILQ_REMOVE(&wkq->que, qent, next);
+                       SCTP_MCORE_QUNLOCK(wkq);
+                       CURVNET_SET(qent->vn);
+                       m = qent->m;
+                       off = qent->off;
+                       v6 = qent->v6;
+                       SCTP_FREE(qent, SCTP_M_MCORE);
+                       if (v6 == 0) {
+                               sctp_input_with_port(m, off, 0);
+                       } else {
+                               printf("V6 not yet supported\n");
+                               sctp_m_freem(m);
+                       }
+                       CURVNET_RESTORE();
+                       SCTP_MCORE_QLOCK(wkq);
+               }
+               wkq->running = 0;
+               if (!TAILQ_EMPTY(&wkq->que)) {
+                       goto skip_sleep;
+               }
+               SCTP_MCORE_QUNLOCK(wkq);
+               msleep(&wkq->running,
+                   &wkq->core_mtx,
+                   0, "wait for pkt", 0);
+       };
+}
+
+static void
+sctp_startup_mcore_threads(void)
+{
+       int i;
+
+       if (mp_ncpus == 1)
+               return;
+
+       SCTP_MALLOC(sctp_mcore_workers, struct sctp_mcore_ctrl *,
+           (mp_ncpus * sizeof(struct sctp_mcore_ctrl)),
+           SCTP_M_MCORE);
+       if (sctp_mcore_workers == NULL) {
+               /* TSNH I hope */
+               return;
+       }
+       memset(sctp_mcore_workers, 0, (mp_ncpus *
+           sizeof(struct sctp_mcore_ctrl)));
+       /* Init the structures */
+       for (i = 0; i < mp_ncpus; i++) {
+               TAILQ_INIT(&sctp_mcore_workers[i].que);
+               SCTP_MCORE_LOCK_INIT(&sctp_mcore_workers[i]);
+               SCTP_MCORE_QLOCK_INIT(&sctp_mcore_workers[i]);
+               sctp_mcore_workers[i].cpuid = i;
+       }
+       /* Now start them all */
+       for (i = 0; i < mp_ncpus; i++) {
+               (void)kproc_create(sctp_mcore_thread,
+                   (void *)&sctp_mcore_workers[i],
+                   &sctp_mcore_workers[i].thread_proc,
+                   RFPROC,
+                   SCTP_KTHREAD_PAGES,
+                   SCTP_MCORE_NAME);
+
+       }
+}
+
+#endif
+
+
 void
 sctp_pcb_init()
 {
@@ -5565,6 +5710,10 @@ sctp_pcb_init()
 
        sctp_startup_iterator();
 
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+       sctp_startup_mcore_threads();
+#endif
+
        /*
         * INIT the default VRF which for BSD is the only one, other O/S's
         * may have more. But initially they must start with one and then

Modified: head/sys/netinet/sctp_pcb.h
==============================================================================
--- head/sys/netinet/sctp_pcb.h Thu Feb  3 08:55:45 2011        (r218210)
+++ head/sys/netinet/sctp_pcb.h Thu Feb  3 10:05:30 2011        (r218211)
@@ -624,6 +624,12 @@ sctp_initiate_iterator(inp_func inpf,
     struct sctp_inpcb *,
     uint8_t co_off);
 
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+void
+     sctp_queue_to_mcore(struct mbuf *m, int off, int cpu_to_use);
+
+#endif
+
 #ifdef INVARIANTS
 void
      sctp_validate_no_locks(struct sctp_inpcb *inp);

Modified: head/sys/netinet/sctp_structs.h
==============================================================================
--- head/sys/netinet/sctp_structs.h     Thu Feb  3 08:55:45 2011        
(r218210)
+++ head/sys/netinet/sctp_structs.h     Thu Feb  3 10:05:30 2011        
(r218211)
@@ -106,6 +106,31 @@ typedef void (*asoc_func) (struct sctp_i
 typedef int (*inp_func) (struct sctp_inpcb *, void *ptr, uint32_t val);
 typedef void (*end_func) (void *ptr, uint32_t val);
 
+#if defined(__FreeBSD__) && defined(SCTP_MCORE_INPUT) && defined(SMP)
+/* whats on the mcore control struct */
+struct sctp_mcore_queue {
+       TAILQ_ENTRY(sctp_mcore_queue) next;
+       struct vnet *vn;
+       struct mbuf *m;
+       int off;
+       int v6;
+};
+
+TAILQ_HEAD(sctp_mcore_qhead, sctp_mcore_queue);
+
+struct sctp_mcore_ctrl {
+       SCTP_PROCESS_STRUCT thread_proc;
+       struct sctp_mcore_qhead que;
+       struct mtx core_mtx;
+       struct mtx que_mtx;
+       int running;
+       int cpuid;
+};
+
+
+#endif
+
+
 struct sctp_iterator {
        TAILQ_ENTRY(sctp_iterator) sctp_nxt_itr;
        struct vnet *vn;
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to