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)
This commit is contained in:
parent
7f6563d13c
commit
bfc46083b9
@ -439,6 +439,7 @@ SCTP_PACKET_LOGGING opt_sctp.h # Log to a packet buffer last N packets
|
||||
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
|
||||
#
|
||||
#
|
||||
#
|
||||
|
@ -68,6 +68,7 @@ MALLOC_DEFINE(SCTP_M_TIMW, "sctp_timw", "sctp time block");
|
||||
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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)); \
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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 sctp_tcb *stcb, struct sctp_ifa *ifa)
|
||||
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
|
||||
|
@ -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);
|
||||
|
@ -106,6 +106,31 @@ typedef void (*asoc_func) (struct sctp_inpcb *, struct sctp_tcb *, void *ptr,
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user