svn commit: r218211 - in head/sys: conf netinet
Robert Watson
rwatson at FreeBSD.org
Fri Feb 4 06:40:48 UTC 2011
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?
(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).
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;
>
More information about the svn-src-all
mailing list