Epochify SCTP.

This commit is contained in:
Michael Tuexen 2020-02-18 21:25:17 +00:00
parent 9a4a1be02c
commit 868b51f234
5 changed files with 59 additions and 16 deletions

View File

@ -412,7 +412,6 @@ typedef struct rtentry sctp_rtentry_t;
*/
#define SCTP_IP_OUTPUT(result, o_pak, ro, stcb, vrf_id) \
{ \
struct epoch_tracker et; \
int o_flgs = IP_RAWOUTPUT; \
struct sctp_tcb *local_stcb = stcb; \
if (local_stcb && \
@ -420,24 +419,19 @@ typedef struct rtentry sctp_rtentry_t;
local_stcb->sctp_ep->sctp_socket) \
o_flgs |= local_stcb->sctp_ep->sctp_socket->so_options & SO_DONTROUTE; \
m_clrprotoflags(o_pak); \
NET_EPOCH_ENTER(et); \
result = ip_output(o_pak, NULL, ro, o_flgs, 0, NULL); \
NET_EPOCH_EXIT(et); \
}
#define SCTP_IP6_OUTPUT(result, o_pak, ro, ifp, stcb, vrf_id) \
{ \
struct epoch_tracker et; \
struct sctp_tcb *local_stcb = stcb; \
m_clrprotoflags(o_pak); \
NET_EPOCH_ENTER(et); \
if (local_stcb && local_stcb->sctp_ep) \
result = ip6_output(o_pak, \
((struct inpcb *)(local_stcb->sctp_ep))->in6p_outputopts, \
(ro), 0, 0, ifp, NULL); \
else \
result = ip6_output(o_pak, NULL, (ro), 0, 0, ifp, NULL); \
NET_EPOCH_EXIT(et); \
}
struct mbuf *

View File

@ -12561,6 +12561,7 @@ sctp_lower_sosend(struct socket *so,
struct thread *p
)
{
struct epoch_tracker et;
ssize_t sndlen = 0, max_len, local_add_more;
int error, len;
struct mbuf *top = NULL;
@ -13062,7 +13063,9 @@ sctp_lower_sosend(struct socket *so,
atomic_add_int(&stcb->asoc.refcnt, -1);
free_cnt_applied = 0;
/* release this lock, otherwise we hang on ourselves */
NET_EPOCH_ENTER(et);
sctp_abort_an_association(stcb->sctp_ep, stcb, mm, SCTP_SO_LOCKED);
NET_EPOCH_EXIT(et);
/* now relock the stcb so everything is sane */
hold_tcblock = 0;
stcb = NULL;
@ -13366,7 +13369,9 @@ skip_preblock:
/* a collision took us forward? */
queue_only = 0;
} else {
NET_EPOCH_ENTER(et);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
NET_EPOCH_EXIT(et);
SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
queue_only = 1;
}
@ -13424,6 +13429,7 @@ skip_preblock:
* the input via the net is happening
* and I don't need to start output :-D
*/
NET_EPOCH_ENTER(et);
if (hold_tcblock == 0) {
if (SCTP_TCB_TRYLOCK(stcb)) {
hold_tcblock = 1;
@ -13436,6 +13442,7 @@ skip_preblock:
stcb,
SCTP_OUTPUT_FROM_USR_SEND, SCTP_SO_LOCKED);
}
NET_EPOCH_EXIT(et);
}
if (hold_tcblock == 1) {
SCTP_TCB_UNLOCK(stcb);
@ -13609,8 +13616,10 @@ dataless_eof:
"%s:%d at %s", __FILE__, __LINE__, __func__);
op_err = sctp_generate_cause(SCTP_BASE_SYSCTL(sctp_diag_info_code),
msg);
NET_EPOCH_ENTER(et);
sctp_abort_an_association(stcb->sctp_ep, stcb,
op_err, SCTP_SO_LOCKED);
NET_EPOCH_EXIT(et);
/*
* now relock the stcb so everything
* is sane
@ -13684,6 +13693,7 @@ skip_out_eof:
stcb->asoc.total_flight,
stcb->asoc.chunks_on_out_queue, stcb->asoc.total_flight_count);
}
NET_EPOCH_ENTER(et);
if ((queue_only == 0) && (nagle_applies == 0) && (stcb->asoc.peers_rwnd && un_sent)) {
/* we can attempt to send too. */
if (hold_tcblock == 0) {
@ -13719,6 +13729,7 @@ skip_out_eof:
(void)sctp_med_chunk_output(inp, stcb, &stcb->asoc, &num_out,
&reason, 1, 1, &now, &now_filled, frag_point, SCTP_SO_LOCKED);
}
NET_EPOCH_EXIT(et);
SCTPDBG(SCTP_DEBUG_OUTPUT1, "USR Send complete qo:%d prw:%d unsent:%d tf:%d cooq:%d toqs:%d err:%d\n",
queue_only, stcb->asoc.peers_rwnd, un_sent,
stcb->asoc.total_flight, stcb->asoc.chunks_on_out_queue,

View File

@ -429,6 +429,7 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
static void
sctp_abort(struct socket *so)
{
struct epoch_tracker et;
struct sctp_inpcb *inp;
uint32_t flags;
@ -437,6 +438,7 @@ sctp_abort(struct socket *so)
return;
}
NET_EPOCH_ENTER(et);
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@ -466,6 +468,7 @@ sctp_must_try_again:
goto sctp_must_try_again;
}
}
NET_EPOCH_EXIT(et);
return;
}
@ -526,6 +529,7 @@ sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
void
sctp_close(struct socket *so)
{
struct epoch_tracker et;
struct sctp_inpcb *inp;
uint32_t flags;
@ -536,6 +540,7 @@ sctp_close(struct socket *so)
/*
* Inform all the lower layer assoc that we are done.
*/
NET_EPOCH_ENTER(et);
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@ -578,6 +583,7 @@ sctp_must_try_again:
goto sctp_must_try_again;
}
}
NET_EPOCH_EXIT(et);
return;
}
@ -660,9 +666,12 @@ connected_type:
* definitions) but this is not advisable. This code is used
* by FreeBSD when sending a file with sendfile() though.
*/
struct epoch_tracker et;
int ret;
NET_EPOCH_ENTER(et);
ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
NET_EPOCH_EXIT(et);
inp->pkt = NULL;
inp->control = NULL;
return (ret);
@ -689,6 +698,7 @@ sctp_disconnect(struct socket *so)
SCTP_INP_RUNLOCK(inp);
return (0);
} else {
struct epoch_tracker et;
struct sctp_association *asoc;
struct sctp_tcb *stcb;
@ -706,6 +716,7 @@ sctp_disconnect(struct socket *so)
SCTP_INP_RUNLOCK(inp);
return (0);
}
NET_EPOCH_ENTER(et);
if (((so->so_options & SO_LINGER) &&
(so->so_linger == 0)) ||
(so->so_rcv.sb_cc > 0)) {
@ -725,6 +736,7 @@ sctp_disconnect(struct socket *so)
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
/* No unlock tcb assoc is gone */
NET_EPOCH_EXIT(et);
return (0);
}
if (TAILQ_EMPTY(&asoc->send_queue) &&
@ -799,12 +811,14 @@ sctp_disconnect(struct socket *so)
SCTP_INP_RUNLOCK(inp);
(void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
NET_EPOCH_EXIT(et);
return (0);
} else {
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
}
soisdisconnecting(so);
NET_EPOCH_EXIT(et);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_RUNLOCK(inp);
return (0);
@ -896,6 +910,7 @@ sctp_shutdown(struct socket *so)
* SHUT_WR or SHUT_RDWR. This means we put the shutdown flag
* against it.
*/
struct epoch_tracker et;
struct sctp_tcb *stcb;
struct sctp_association *asoc;
struct sctp_nets *netp;
@ -935,6 +950,7 @@ sctp_shutdown(struct socket *so)
SCTP_INP_RUNLOCK(inp);
return (0);
}
NET_EPOCH_ENTER(et);
if (stcb->asoc.alternate) {
netp = stcb->asoc.alternate;
} else {
@ -974,6 +990,7 @@ sctp_shutdown(struct socket *so)
SCTP_INP_RUNLOCK(inp);
sctp_abort_an_association(stcb->sctp_ep, stcb,
op_err, SCTP_SO_LOCKED);
NET_EPOCH_EXIT(et);
return (0);
}
}
@ -985,6 +1002,7 @@ sctp_shutdown(struct socket *so)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_RUNLOCK(inp);
NET_EPOCH_EXIT(et);
return (0);
}
}
@ -6906,11 +6924,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
int
sctp_ctloutput(struct socket *so, struct sockopt *sopt)
{
void *optval = NULL;
size_t optsize = 0;
void *p;
int error = 0;
struct epoch_tracker et;
struct sctp_inpcb *inp;
void *optval = NULL;
void *p;
size_t optsize = 0;
int error = 0;
if ((sopt->sopt_level == SOL_SOCKET) &&
(sopt->sopt_name == SO_SETFIB)) {
@ -6957,7 +6976,9 @@ sctp_ctloutput(struct socket *so, struct sockopt *sopt)
}
p = (void *)sopt->sopt_td;
if (sopt->sopt_dir == SOPT_SET) {
NET_EPOCH_ENTER(et);
error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
NET_EPOCH_EXIT(et);
} else if (sopt->sopt_dir == SOPT_GET) {
error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
} else {
@ -6978,6 +6999,7 @@ out:
static int
sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
{
struct epoch_tracker et;
int error = 0;
int create_lock_on = 0;
uint32_t vrf_id;
@ -7037,7 +7059,7 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
SCTP_INP_INCR_REF(inp);
SCTP_ASOC_CREATE_LOCK(inp);
create_lock_on = 1;
NET_EPOCH_ENTER(et);
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
(inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
@ -7122,10 +7144,10 @@ sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
out_now:
NET_EPOCH_EXIT(et);
if (create_lock_on) {
SCTP_ASOC_CREATE_UNLOCK(inp);
}
SCTP_INP_DECR_REF(inp);
return (error);
}

View File

@ -1371,11 +1371,13 @@ sctp_expand_mapping_array(struct sctp_association *asoc, uint32_t needed)
static void
sctp_iterator_work(struct sctp_iterator *it)
{
struct epoch_tracker et;
struct sctp_inpcb *tinp;
int iteration_count = 0;
int inp_skip = 0;
int first_in = 1;
struct sctp_inpcb *tinp;
NET_EPOCH_ENTER(et);
SCTP_INP_INFO_RLOCK();
SCTP_ITERATOR_LOCK();
sctp_it_ctl.cur_it = it;
@ -1393,6 +1395,7 @@ done_with_iterator:
(*it->function_atend) (it->pointer, it->val);
}
SCTP_FREE(it, SCTP_M_ITER);
NET_EPOCH_EXIT(et);
return;
}
select_a_new_ep:
@ -1601,6 +1604,7 @@ sctp_handle_addr_wq(void)
void
sctp_timeout_handler(void *t)
{
struct epoch_tracker et;
struct sctp_inpcb *inp;
struct sctp_tcb *stcb;
struct sctp_nets *net;
@ -1716,6 +1720,7 @@ sctp_timeout_handler(void *t)
/* record in stopped what t-o occurred */
tmr->stopped_from = type;
NET_EPOCH_ENTER(et);
/* mark as being serviced now */
if (SCTP_OS_TIMER_PENDING(&tmr->timer)) {
/*
@ -1910,7 +1915,6 @@ sctp_timeout_handler(void *t)
sctp_abort_an_association(inp, stcb, op_err, SCTP_SO_NOT_LOCKED);
/* no need to unlock on tcb its gone */
goto out_decr;
case SCTP_TIMER_TYPE_STRRESET:
if ((stcb == NULL) || (inp == NULL)) {
break;
@ -1943,7 +1947,6 @@ sctp_timeout_handler(void *t)
sctp_delete_prim_timer(inp, stcb, net);
SCTP_STAT_INCR(sctps_timodelprim);
break;
case SCTP_TIMER_TYPE_AUTOCLOSE:
if ((stcb == NULL) || (inp == NULL)) {
break;
@ -2034,6 +2037,7 @@ out_decr:
out_no_decr:
SCTPDBG(SCTP_DEBUG_TIMER1, "Timer now complete (type = %d)\n", type);
CURVNET_RESTORE();
NET_EPOCH_EXIT(et);
}
void
@ -5184,6 +5188,7 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
uint32_t rwnd_req)
{
/* User pulled some data, do we need a rwnd update? */
struct epoch_tracker et;
int r_unlocked = 0;
uint32_t dif, rwnd;
struct socket *so = NULL;
@ -5239,11 +5244,13 @@ sctp_user_rcvd(struct sctp_tcb *stcb, uint32_t *freed_so_far, int hold_rlock,
goto out;
}
SCTP_STAT_INCR(sctps_wu_sacks_sent);
NET_EPOCH_ENTER(et);
sctp_send_sack(stcb, SCTP_SO_LOCKED);
sctp_chunk_output(stcb->sctp_ep, stcb,
SCTP_OUTPUT_FROM_USR_RCVD, SCTP_SO_LOCKED);
/* make sure no timer is running */
NET_EPOCH_EXIT(et);
sctp_timer_stop(SCTP_TIMER_TYPE_RECV, stcb->sctp_ep, stcb, NULL,
SCTP_FROM_SCTPUTIL + SCTP_LOC_6);
SCTP_TCB_UNLOCK(stcb);

View File

@ -111,7 +111,7 @@ sctp6_input_with_port(struct mbuf **i_pak, int *offp, uint16_t port)
}
}
ip6 = mtod(m, struct ip6_hdr *);
sh = (struct sctphdr *)(mtod(m, caddr_t) + iphlen);
sh = (struct sctphdr *)(mtod(m, caddr_t)+iphlen);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(struct sctphdr));
offset -= sizeof(struct sctp_chunkhdr);
memset(&src, 0, sizeof(struct sockaddr_in6));
@ -481,6 +481,7 @@ SYSCTL_PROC(_net_inet6_sctp6, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
static void
sctp6_abort(struct socket *so)
{
struct epoch_tracker et;
struct sctp_inpcb *inp;
uint32_t flags;
@ -489,6 +490,7 @@ sctp6_abort(struct socket *so)
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP6_USRREQ, EINVAL);
return;
}
NET_EPOCH_ENTER(et);
sctp_must_try_again:
flags = inp->sctp_flags;
#ifdef SCTP_LOG_CLOSING
@ -517,6 +519,7 @@ sctp_must_try_again:
goto sctp_must_try_again;
}
}
NET_EPOCH_EXIT(et);
return;
}
@ -776,9 +779,12 @@ connected_type:
* optionaly switch back to this code (by changing back the
* defininitions but this is not advisable.
*/
struct epoch_tracker et;
int ret;
NET_EPOCH_ENTER(et);
ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
NET_EPOCH_EXIT(et);
inp->pkt = NULL;
inp->control = NULL;
return (ret);
@ -790,6 +796,7 @@ connected_type:
static int
sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
{
struct epoch_tracker et;
uint32_t vrf_id;
int error = 0;
struct sctp_inpcb *inp;
@ -924,8 +931,10 @@ sctp6_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
}
SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
NET_EPOCH_ENTER(et);
sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
SCTP_TCB_UNLOCK(stcb);
NET_EPOCH_EXIT(et);
return (error);
}