On Feb 4, 2011, at 7:40 AM, Robert Watson wrote:

> 
> On Thu, 3 Feb 2011, Randall Stewart wrote:
> 
>> 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.
> 
> Hmm.  It might be better to add a new NETISR_SCTP and use netisr's support 
> for multithreading?
That sounds really good.

Is it possible that different network cards put packets in the same queue?
That would be helpful in the case of SCTP.
> 
> (I'm preparing a patch for review that enhances that a bit so that protocols 
> can be a bit more expressive in terms of specifying dispatch policy, etc, 
> currently).
Great!

Best regards
Michael
> 
> Robert
> 
> 
>> 
>> 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-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