sctp: get rid of stcb send lock

Just use the stcb lock instead to simplify locking.

Reported by:	syzbot+d00b202063150f85b110@syzkaller.appspotmail.com
Reported by:	syzbot+87f268a0a6d2d6383306@syzkaller.appspotmail.com
MFC after:	3 days
This commit is contained in:
Michael Tuexen 2022-03-29 01:50:17 +02:00
parent c1970a7eba
commit 5ac91821f5
10 changed files with 336 additions and 409 deletions

View File

@ -179,6 +179,8 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked)
struct sctp_stream_queue_pending *sp;
struct sctp_association *asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
/*
* This function returns if any stream has true unsent data on it.
* Note that as it looks through it will clean up any places that
@ -186,7 +188,6 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked)
*/
asoc = &stcb->asoc;
unsent_data = 0;
SCTP_TCB_SEND_LOCK(stcb);
if (!stcb->asoc.ss_functions.sctp_ss_is_empty(stcb, asoc)) {
/* Check to see if some data queued */
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
@ -234,7 +235,6 @@ sctp_is_there_unsent_data(struct sctp_tcb *stcb, int so_locked)
}
}
}
SCTP_TCB_SEND_UNLOCK(stcb);
return (unsent_data);
}
@ -246,6 +246,8 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
struct sctp_nets *lnet;
unsigned int i;
SCTP_TCB_LOCK_ASSERT(stcb);
init = &cp->init;
asoc = &stcb->asoc;
/* save off parameters */
@ -263,7 +265,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
}
}
}
SCTP_TCB_SEND_LOCK(stcb);
if (asoc->pre_open_streams > ntohs(init->num_inbound_streams)) {
unsigned int newcnt;
struct sctp_stream_out *outs;
@ -323,7 +324,6 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
/* cut back the count */
asoc->pre_open_streams = newcnt;
}
SCTP_TCB_SEND_UNLOCK(stcb);
asoc->streamoutcnt = asoc->pre_open_streams;
if (asoc->strmout) {
for (i = 0; i < asoc->streamoutcnt; i++) {
@ -1808,8 +1808,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
SCTP_TCB_LOCK(stcb);
atomic_subtract_int(&stcb->asoc.refcnt, 1);
/* send up all the data */
SCTP_TCB_SEND_LOCK(stcb);
sctp_report_all_outbound(stcb, 0, SCTP_SO_LOCKED);
for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
stcb->asoc.strmout[i].chunks_on_queues = 0;
@ -1896,7 +1894,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
LIST_INSERT_HEAD(head, stcb, sctp_asocs);
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_INP_WUNLOCK(stcb->sctp_ep);
SCTP_INP_INFO_WUNLOCK();
asoc->total_flight = 0;

View File

@ -337,28 +337,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_ASOC_CREATE_LOCK_CONTENDED(_inp) \
((_inp)->inp_create_mtx.mtx_lock & MTX_CONTESTED)
#define SCTP_TCB_SEND_LOCK_INIT(_tcb) do { \
mtx_init(&(_tcb)->tcb_send_mtx, "sctp-send-tcb", "tcbs", \
MTX_DEF | MTX_DUPOK); \
} while (0)
#define SCTP_TCB_SEND_LOCK_DESTROY(_tcb) do { \
mtx_destroy(&(_tcb)->tcb_send_mtx); \
} while (0)
#define SCTP_TCB_SEND_LOCK(_tcb) do { \
mtx_lock(&(_tcb)->tcb_send_mtx); \
} while (0)
#define SCTP_TCB_SEND_UNLOCK(_tcb) do { \
mtx_unlock(&(_tcb)->tcb_send_mtx); \
} while (0)
#define SCTP_TCB_SEND_LOCK_ASSERT(_tcb) do { \
KASSERT(mtx_owned(&(_tcb)->tcb_send_mtx), \
("Don't own TCB send lock")); \
} while (0)
/*
* For the majority of things (once we have found the association) we will
* lock the actual association mutex. This will protect all the assoiciation

File diff suppressed because it is too large Load Diff

View File

@ -4326,7 +4326,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
asoc = &stcb->asoc;
SCTP_TCB_LOCK_INIT(stcb);
SCTP_TCB_SEND_LOCK_INIT(stcb);
stcb->rport = rport;
/* setup back pointer's */
stcb->sctp_ep = inp;
@ -4334,7 +4333,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
if ((err = sctp_init_asoc(inp, stcb, override_tag, initial_tsn, vrf_id, o_streams))) {
/* failed */
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
SCTP_DECR_ASOC_COUNT();
*error = err;
@ -4365,7 +4363,6 @@ sctp_aloc_assoc_locked(struct sctp_inpcb *inp, struct sockaddr *firstaddr,
SCTP_DECR_ASOC_COUNT();
SCTP_TCB_UNLOCK(stcb);
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
LIST_REMOVE(stcb, sctp_asocs);
LIST_REMOVE(stcb, sctp_tcbasocidhash);
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_asoc), stcb);
@ -4702,6 +4699,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
struct socket *so;
/* first, lets purge the entry from the hash table. */
SCTP_TCB_LOCK_ASSERT(stcb);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 6);
@ -4713,7 +4711,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* there is no asoc, really TSNH :-0 */
return (1);
}
SCTP_TCB_SEND_LOCK(stcb);
if (stcb->asoc.alternate) {
sctp_free_remote_addr(stcb->asoc.alternate);
stcb->asoc.alternate = NULL;
@ -4748,7 +4745,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* nope, reader or writer in the way */
sctp_timer_start(SCTP_TIMER_TYPE_ASOCKILL, inp, stcb, NULL);
/* no asoc destroyed */
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
#ifdef SCTP_LOG_CLOSING
sctp_log_closing(inp, stcb, 8);
@ -4826,7 +4822,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
sctp_sorwakeup(inp, so);
sctp_sowwakeup(inp, so);
}
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
#ifdef SCTP_LOG_CLOSING
@ -4851,12 +4846,10 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
if (from_inpcbfree == SCTP_NORMAL_PROC) {
atomic_add_int(&stcb->asoc.refcnt, 1);
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_INFO_WLOCK();
SCTP_INP_WLOCK(inp);
SCTP_TCB_LOCK(stcb);
SCTP_TCB_SEND_LOCK(stcb);
}
/* Double check the GONE flag */
if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
@ -4904,7 +4897,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
SCTP_INP_INFO_WUNLOCK();
SCTP_INP_WUNLOCK(inp);
}
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
return (0);
}
@ -5169,10 +5161,8 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
/* Insert new items here :> */
/* Get rid of LOCK */
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
SCTP_TCB_LOCK_DESTROY(stcb);
SCTP_TCB_SEND_LOCK_DESTROY(stcb);
if (from_inpcbfree == SCTP_NORMAL_PROC) {
SCTP_INP_INFO_WUNLOCK();
SCTP_INP_RLOCK(inp);

View File

@ -53,7 +53,7 @@ sctp_ss_default_init(struct sctp_tcb *stcb, struct sctp_association *asoc)
{
uint16_t i;
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
asoc->ss_data.locked_on_sending = NULL;
asoc->ss_data.last_out_stream = NULL;
@ -75,7 +75,7 @@ static void
sctp_ss_default_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
bool clear_values SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) {
struct sctp_stream_out *strq;
@ -92,6 +92,8 @@ sctp_ss_default_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
static void
sctp_ss_default_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (with_strq != NULL) {
if (stcb->asoc.ss_data.locked_on_sending == with_strq) {
stcb->asoc.ss_data.locked_on_sending = strq;
@ -109,7 +111,7 @@ sctp_ss_default_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq,
struct sctp_stream_queue_pending *sp SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
/* Add to wheel if not already on it and stream queue not empty */
if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) {
@ -123,6 +125,8 @@ sctp_ss_default_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
static bool
sctp_ss_default_is_empty(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc)
{
SCTP_TCB_LOCK_ASSERT(stcb);
return (TAILQ_EMPTY(&asoc->ss_data.out.wheel));
}
@ -131,7 +135,7 @@ sctp_ss_default_remove(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq,
struct sctp_stream_queue_pending *sp SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
/*
* Remove from wheel if stream queue is empty and actually is on the
@ -165,6 +169,8 @@ sctp_ss_default_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net,
{
struct sctp_stream_out *strq, *strqt;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->ss_data.locked_on_sending != NULL) {
KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled,
("locked_on_sending %p not scheduled",
@ -223,6 +229,8 @@ sctp_ss_default_scheduled(struct sctp_tcb *stcb,
KASSERT(strq != NULL, ("strq is NULL"));
KASSERT(strq->ss_params.scheduled, ("strq %p is not scheduled", (void *)strq));
SCTP_TCB_LOCK_ASSERT(stcb);
asoc->ss_data.last_out_stream = strq;
if (asoc->idata_supported == 0) {
sp = TAILQ_FIRST(&strq->outqueue);
@ -241,6 +249,8 @@ static void
sctp_ss_default_packet_done(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net SCTP_UNUSED,
struct sctp_association *asoc SCTP_UNUSED)
{
SCTP_TCB_LOCK_ASSERT(stcb);
/* Nothing to be done here */
return;
}
@ -249,6 +259,8 @@ static int
sctp_ss_default_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED,
struct sctp_stream_out *strq SCTP_UNUSED, uint16_t *value SCTP_UNUSED)
{
SCTP_TCB_LOCK_ASSERT(stcb);
/* Nothing to be done here */
return (-1);
}
@ -257,6 +269,8 @@ static int
sctp_ss_default_set_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED,
struct sctp_stream_out *strq SCTP_UNUSED, uint16_t value SCTP_UNUSED)
{
SCTP_TCB_LOCK_ASSERT(stcb);
/* Nothing to be done here */
return (-1);
}
@ -267,6 +281,8 @@ sctp_ss_default_is_user_msgs_incomplete(struct sctp_tcb *stcb SCTP_UNUSED, struc
struct sctp_stream_out *strq;
struct sctp_stream_queue_pending *sp;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->stream_queue_cnt != 1) {
return (false);
}
@ -292,7 +308,7 @@ sctp_ss_rr_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
{
struct sctp_stream_out *strqt;
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) {
if (TAILQ_EMPTY(&asoc->ss_data.out.wheel)) {
@ -322,6 +338,8 @@ static struct sctp_stream_out *
sctp_ss_rrp_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net SCTP_UNUSED,
struct sctp_association *asoc)
{
SCTP_TCB_LOCK_ASSERT(stcb);
return (asoc->ss_data.last_out_stream);
}
@ -331,6 +349,8 @@ sctp_ss_rrp_packet_done(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net
{
struct sctp_stream_out *strq, *strqt;
SCTP_TCB_LOCK_ASSERT(stcb);
strqt = asoc->ss_data.last_out_stream;
KASSERT(strqt == NULL || strqt->ss_params.scheduled,
("last_out_stream %p not scheduled", (void *)strqt));
@ -381,7 +401,7 @@ static void
sctp_ss_prio_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
bool clear_values)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) {
struct sctp_stream_out *strq;
@ -401,6 +421,8 @@ sctp_ss_prio_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
static void
sctp_ss_prio_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (with_strq != NULL) {
if (stcb->asoc.ss_data.locked_on_sending == with_strq) {
stcb->asoc.ss_data.locked_on_sending = strq;
@ -424,7 +446,7 @@ sctp_ss_prio_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
{
struct sctp_stream_out *strqt;
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
/* Add to wheel if not already on it and stream queue not empty */
if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) {
@ -450,7 +472,7 @@ static void
sctp_ss_prio_remove(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
/*
* Remove from wheel if stream queue is empty and actually is on the
@ -484,6 +506,8 @@ sctp_ss_prio_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net,
{
struct sctp_stream_out *strq, *strqt, *strqn;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->ss_data.locked_on_sending != NULL) {
KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled,
("locked_on_sending %p not scheduled",
@ -538,6 +562,8 @@ static int
sctp_ss_prio_get_value(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc SCTP_UNUSED,
struct sctp_stream_out *strq, uint16_t *value)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (strq == NULL) {
return (-1);
}
@ -549,6 +575,8 @@ static int
sctp_ss_prio_set_value(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq, uint16_t value)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (strq == NULL) {
return (-1);
}
@ -566,7 +594,7 @@ static void
sctp_ss_fb_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
bool clear_values)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
while (!TAILQ_EMPTY(&asoc->ss_data.out.wheel)) {
struct sctp_stream_out *strq;
@ -586,6 +614,8 @@ sctp_ss_fb_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
static void
sctp_ss_fb_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (with_strq != NULL) {
if (stcb->asoc.ss_data.locked_on_sending == with_strq) {
stcb->asoc.ss_data.locked_on_sending = strq;
@ -607,7 +637,7 @@ static void
sctp_ss_fb_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
if (!TAILQ_EMPTY(&strq->outqueue) && !strq->ss_params.scheduled) {
if (strq->ss_params.ss.fb.rounds < 0)
@ -622,7 +652,7 @@ static void
sctp_ss_fb_remove(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq, struct sctp_stream_queue_pending *sp SCTP_UNUSED)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
/*
* Remove from wheel if stream queue is empty and actually is on the
@ -656,6 +686,8 @@ sctp_ss_fb_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net,
{
struct sctp_stream_out *strq = NULL, *strqt;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->ss_data.locked_on_sending != NULL) {
KASSERT(asoc->ss_data.locked_on_sending->ss_params.scheduled,
("locked_on_sending %p not scheduled",
@ -699,6 +731,8 @@ sctp_ss_fb_scheduled(struct sctp_tcb *stcb, struct sctp_nets *net SCTP_UNUSED,
struct sctp_stream_out *strqt;
int subtract;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->idata_supported == 0) {
sp = TAILQ_FIRST(&strq->outqueue);
if ((sp != NULL) && (sp->some_taken == 1)) {
@ -740,7 +774,7 @@ sctp_ss_fcfs_init(struct sctp_tcb *stcb, struct sctp_association *asoc)
struct sctp_stream_queue_pending *sp;
uint16_t i;
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
TAILQ_INIT(&asoc->ss_data.out.list);
/*
@ -774,7 +808,7 @@ sctp_ss_fcfs_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
{
struct sctp_stream_queue_pending *sp;
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
while (!TAILQ_EMPTY(&asoc->ss_data.out.list)) {
sp = TAILQ_FIRST(&asoc->ss_data.out.list);
@ -789,6 +823,8 @@ sctp_ss_fcfs_clear(struct sctp_tcb *stcb, struct sctp_association *asoc,
static void
sctp_ss_fcfs_init_stream(struct sctp_tcb *stcb, struct sctp_stream_out *strq, struct sctp_stream_out *with_strq)
{
SCTP_TCB_LOCK_ASSERT(stcb);
if (with_strq != NULL) {
if (stcb->asoc.ss_data.locked_on_sending == with_strq) {
stcb->asoc.ss_data.locked_on_sending = strq;
@ -805,7 +841,7 @@ static void
sctp_ss_fcfs_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq SCTP_UNUSED, struct sctp_stream_queue_pending *sp)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
if (!sp->scheduled) {
TAILQ_INSERT_TAIL(&asoc->ss_data.out.list, sp, ss_next);
@ -817,6 +853,8 @@ sctp_ss_fcfs_add(struct sctp_tcb *stcb, struct sctp_association *asoc,
static bool
sctp_ss_fcfs_is_empty(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_association *asoc)
{
SCTP_TCB_LOCK_ASSERT(stcb);
return (TAILQ_EMPTY(&asoc->ss_data.out.list));
}
@ -824,7 +862,7 @@ static void
sctp_ss_fcfs_remove(struct sctp_tcb *stcb, struct sctp_association *asoc,
struct sctp_stream_out *strq SCTP_UNUSED, struct sctp_stream_queue_pending *sp)
{
SCTP_TCB_SEND_LOCK_ASSERT(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
if (sp->scheduled) {
TAILQ_REMOVE(&asoc->ss_data.out.list, sp, ss_next);
@ -840,6 +878,8 @@ sctp_ss_fcfs_select(struct sctp_tcb *stcb SCTP_UNUSED, struct sctp_nets *net,
struct sctp_stream_out *strq;
struct sctp_stream_queue_pending *sp;
SCTP_TCB_LOCK_ASSERT(stcb);
if (asoc->ss_data.locked_on_sending) {
return (asoc->ss_data.locked_on_sending);
}

View File

@ -855,8 +855,8 @@ sctp_sysctl_handle_trace_log_clear(SYSCTL_HANDLER_ARGS)
return (error); \
} \
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, mib_name, \
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, \
NULL, 0, sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC);
CTLFLAG_VNET|CTLTYPE_UINT|CTLFLAG_RW, NULL, 0, \
sctp_sysctl_handle_##mib_name, "UI", prefix##_DESC);
/*
* sysctl definitions
@ -867,14 +867,10 @@ SCTP_UINT_SYSCTL(recvspace, sctp_recvspace, SCTPCTL_RECVSPACE)
SCTP_UINT_SYSCTL(auto_asconf, sctp_auto_asconf, SCTPCTL_AUTOASCONF)
SCTP_UINT_SYSCTL(ecn_enable, sctp_ecn_enable, SCTPCTL_ECN_ENABLE)
SCTP_UINT_SYSCTL(pr_enable, sctp_pr_enable, SCTPCTL_PR_ENABLE)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_enable,
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_auth, "IU",
SCTPCTL_AUTH_ENABLE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_enable,
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_asconf, "IU",
SCTPCTL_ASCONF_ENABLE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, auth_enable, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_auth, "IU", SCTPCTL_AUTH_ENABLE_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, asconf_enable, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_asconf, "IU", SCTPCTL_ASCONF_ENABLE_DESC);
SCTP_UINT_SYSCTL(reconfig_enable, sctp_reconfig_enable, SCTPCTL_RECONFIG_ENABLE)
SCTP_UINT_SYSCTL(nrsack_enable, sctp_nrsack_enable, SCTPCTL_NRSACK_ENABLE)
SCTP_UINT_SYSCTL(pktdrop_enable, sctp_pktdrop_enable, SCTPCTL_PKTDROP_ENABLE)
@ -924,19 +920,13 @@ SCTP_UINT_SYSCTL(default_frag_interleave, sctp_default_frag_interleave, SCTPCTL_
SCTP_UINT_SYSCTL(mobility_base, sctp_mobility_base, SCTPCTL_MOBILITY_BASE)
SCTP_UINT_SYSCTL(mobility_fasthandoff, sctp_mobility_fasthandoff, SCTPCTL_MOBILITY_FASTHANDOFF)
#if defined(SCTP_LOCAL_TRACE_BUF)
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log,
CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_trace_log, "S,sctplog"a
, "SCTP logging (struct sctp_log)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace,
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_trace_log_clear, "IU",
"Clear SCTP Logging buffer");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, log, CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RD,
NULL, 0, sctp_sysctl_handle_trace_log, "S,sctplog", "SCTP logging (struct sctp_log)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, clear_trace, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_trace_log_clear, "IU", "Clear SCTP Logging buffer");
#endif
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port,
CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_udp_tunneling, "IU",
SCTPCTL_UDP_TUNNELING_PORT_DESC);
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, udp_tunneling_port, CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_udp_tunneling, "IU", SCTPCTL_UDP_TUNNELING_PORT_DESC);
SCTP_UINT_SYSCTL(enable_sack_immediately, sctp_enable_sack_immediately, SCTPCTL_SACK_IMMEDIATELY_ENABLE)
SCTP_UINT_SYSCTL(nat_friendly_init, sctp_inits_include_nat_friendly, SCTPCTL_NAT_FRIENDLY_INITS)
SCTP_UINT_SYSCTL(vtag_time_wait, sctp_vtag_time_wait, SCTPCTL_TIME_WAIT)
@ -953,11 +943,7 @@ SCTP_UINT_SYSCTL(diag_info_code, sctp_diag_info_code, SCTPCTL_DIAG_INFO_CODE)
#ifdef SCTP_DEBUG
SCTP_UINT_SYSCTL(debug, sctp_debug_on, SCTPCTL_DEBUG)
#endif
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats,
CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_stats, "S,sctpstat",
"SCTP statistics (struct sctp_stat)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist,
CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_NEEDGIANT,
NULL, 0, sctp_sysctl_handle_assoclist, "S,xassoc",
"List of active SCTP associations");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, stats, CTLFLAG_VNET | CTLTYPE_STRUCT | CTLFLAG_RW,
NULL, 0, sctp_sysctl_handle_stats, "S,sctpstat", "SCTP statistics (struct sctp_stat)");
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, assoclist, CTLFLAG_VNET | CTLTYPE_OPAQUE | CTLFLAG_RD,
NULL, 0, sctp_sysctl_handle_assoclist, "S,xassoc", "List of active SCTP associations");

View File

@ -1352,8 +1352,7 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
KASSERT(inp != NULL, ("inp is NULL"));
KASSERT(stcb != NULL, ("stcb is NULL"));
SCTP_TCB_SEND_LOCK(stcb);
SCTP_TCB_LOCK_ASSERT(stcb);
KASSERT(TAILQ_EMPTY(&stcb->asoc.send_queue), ("send_queue not empty"));
KASSERT(TAILQ_EMPTY(&stcb->asoc.sent_queue), ("sent_queue not empty"));
@ -1387,7 +1386,6 @@ sctp_audit_stream_queues_for_size(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
SCTP_PRINTF("Hmm, stream queue cnt at %d I counted %d in stream out wheel\n",
stcb->asoc.stream_queue_cnt, chks_in_queue);
}
SCTP_TCB_SEND_UNLOCK(stcb);
if (chks_in_queue) {
/* call the output queue function */
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_NOT_LOCKED);

View File

@ -1259,7 +1259,7 @@ int
sctp_lower_sosend(struct socket *so,
struct sockaddr *addr,
struct uio *uio,
struct mbuf *i_pak,
struct mbuf *top,
struct mbuf *control,
int flags,
struct sctp_sndrcvinfo *srcv

View File

@ -4068,12 +4068,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
}
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
if (stcb) {
SCTP_TCB_SEND_LOCK(stcb);
stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
stcb->asoc.stream_scheduling_module = av->assoc_value;
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
} else {
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
@ -4091,12 +4089,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
SCTP_INP_RLOCK(inp);
LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
SCTP_TCB_LOCK(stcb);
SCTP_TCB_SEND_LOCK(stcb);
stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
stcb->asoc.stream_scheduling_module = av->assoc_value;
stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
}
SCTP_INP_RUNLOCK(inp);

View File

@ -1288,7 +1288,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
SCTP_LTRACE_ERR_RET(NULL, stcb, NULL, SCTP_FROM_SCTPUTIL, ENOMEM);
return (ENOMEM);
}
SCTP_TCB_SEND_LOCK(stcb);
SCTP_TCB_LOCK(stcb);
for (i = 0; i < asoc->streamoutcnt; i++) {
/*
* inbound side must be set to 0xffff, also NOTE when we get
@ -1317,7 +1317,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
asoc->strmout[i].state = SCTP_STREAM_OPENING;
}
asoc->ss_functions.sctp_ss_init(stcb, asoc);
SCTP_TCB_SEND_UNLOCK(stcb);
SCTP_TCB_UNLOCK(stcb);
/* Now the mapping array */
asoc->mapping_array_size = SCTP_INITIAL_MAPPING_ARRAY;
@ -4331,6 +4331,8 @@ sctp_abort_notification(struct sctp_tcb *stcb, bool from_peer, bool timeout,
if (stcb == NULL) {
return;
}
SCTP_TCB_LOCK_ASSERT(stcb);
if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
(stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_CONNECTED))) {
@ -4341,11 +4343,9 @@ sctp_abort_notification(struct sctp_tcb *stcb, bool from_peer, bool timeout,
(stcb->asoc.state & SCTP_STATE_CLOSED_SOCKET)) {
return;
}
SCTP_TCB_SEND_LOCK(stcb);
SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_WAS_ABORTED);
/* Tell them we lost the asoc */
sctp_report_all_outbound(stcb, error, so_locked);
SCTP_TCB_SEND_UNLOCK(stcb);
if (from_peer) {
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_REM_ABORTED, stcb, error, abort, so_locked);
} else {
@ -5041,6 +5041,8 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
int notdone;
int do_wakeup_routine = 0;
SCTP_TCB_LOCK_ASSERT(stcb);
sid = tp1->rec.data.sid;
mid = tp1->rec.data.mid;
if (sent || !(tp1->rec.data.rcv_flags & SCTP_DATA_FIRST_FRAG)) {
@ -5151,7 +5153,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
* Still no eom found. That means there is stuff left on the
* stream out queue.. yuck.
*/
SCTP_TCB_SEND_LOCK(stcb);
strq = &stcb->asoc.strmout[sid];
sp = TAILQ_FIRST(&strq->outqueue);
if (sp != NULL) {
@ -5233,7 +5234,6 @@ sctp_release_pr_sctp_chunk(struct sctp_tcb *stcb, struct sctp_tmit_chunk *tp1,
sp->length = 0;
}
}
SCTP_TCB_SEND_UNLOCK(stcb);
}
if (do_wakeup_routine) {
sctp_sowwakeup(stcb->sctp_ep, stcb->sctp_socket);