Date: Fri, 4 Feb 2011 06:40:46 +0000 (GMT) From: Robert Watson <rwatson@FreeBSD.org> To: Randall Stewart <rrs@FreeBSD.org> Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org Subject: Re: svn commit: r218211 - in head/sys: conf netinet Message-ID: <alpine.BSF.2.00.1102040639440.18938@fledge.watson.org> In-Reply-To: <201102031005.p13A5Vwi040803@svn.freebsd.org> References: <201102031005.p13A5Vwi040803@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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; >
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?alpine.BSF.2.00.1102040639440.18938>