mirror of
https://git.FreeBSD.org/src.git
synced 2025-02-04 17:15:50 +00:00
This is work done by Michael Tuexen and myself at the IETF. This
adds the new I-Data (Interleaved Data) message. This allows a user to be able to have complete freedom from Head Of Line blocking that was previously there due to the in-ability to send multiple large messages without the TSN's being in sequence. The code as been tested with Michaels various packet drill scripts as well as inter-networking between the IETF's location in Argentina and Germany.
This commit is contained in:
parent
5ce34567e6
commit
44249214d3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=297662
@ -196,6 +196,9 @@ struct sctp_paramhdr {
|
||||
#define SCTP_SS_VALUE 0x00001204
|
||||
#define SCTP_CC_OPTION 0x00001205 /* Options for CC
|
||||
* modules */
|
||||
/* For I-DATA */
|
||||
#define SCTP_INTERLEAVING_SUPPORTED 0x00001206
|
||||
|
||||
/* read only */
|
||||
#define SCTP_GET_SNDBUF_USE 0x00001101
|
||||
#define SCTP_GET_STAT_LOG 0x00001103
|
||||
@ -452,6 +455,7 @@ struct sctp_error_auth_invalid_hmac {
|
||||
/* EY nr_sack chunk id*/
|
||||
#define SCTP_NR_SELECTIVE_ACK 0x10
|
||||
/************0x40 series ***********/
|
||||
#define SCTP_IDATA 0x40
|
||||
/************0x80 series ***********/
|
||||
/* RFC5061 */
|
||||
#define SCTP_ASCONF_ACK 0x80
|
||||
@ -467,7 +471,7 @@ struct sctp_error_auth_invalid_hmac {
|
||||
#define SCTP_FORWARD_CUM_TSN 0xc0
|
||||
/* RFC5061 */
|
||||
#define SCTP_ASCONF 0xc1
|
||||
|
||||
#define SCTP_IFORWARD_CUM_TSN 0xc2
|
||||
|
||||
/* ABORT and SHUTDOWN COMPLETE FLAG */
|
||||
#define SCTP_HAD_NO_TCB 0x01
|
||||
|
@ -386,8 +386,8 @@ __FBSDID("$FreeBSD$");
|
||||
/* align to 32-bit sizes */
|
||||
#define SCTP_SIZE32(x) ((((x) + 3) >> 2) << 2)
|
||||
|
||||
#define IS_SCTP_CONTROL(a) ((a)->chunk_type != SCTP_DATA)
|
||||
#define IS_SCTP_DATA(a) ((a)->chunk_type == SCTP_DATA)
|
||||
#define IS_SCTP_CONTROL(a) (((a)->chunk_type != SCTP_DATA) && ((a)->chunk_type != SCTP_IDATA))
|
||||
#define IS_SCTP_DATA(a) (((a)->chunk_type == SCTP_DATA) || ((a)->chunk_type == SCTP_IDATA))
|
||||
|
||||
|
||||
/* SCTP parameter types */
|
||||
@ -886,12 +886,19 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
/* modular comparison */
|
||||
/* See RFC 1982 for details. */
|
||||
#define SCTP_SSN_GT(a, b) (((a < b) && ((uint16_t)(b - a) > (1U<<15))) || \
|
||||
((a > b) && ((uint16_t)(a - b) < (1U<<15))))
|
||||
#define SCTP_SSN_GE(a, b) (SCTP_SSN_GT(a, b) || (a == b))
|
||||
#define SCTP_TSN_GT(a, b) (((a < b) && ((uint32_t)(b - a) > (1U<<31))) || \
|
||||
((a > b) && ((uint32_t)(a - b) < (1U<<31))))
|
||||
#define SCTP_TSN_GE(a, b) (SCTP_TSN_GT(a, b) || (a == b))
|
||||
#define SCTP_UINT16_GT(a, b) (((a < b) && ((uint16_t)(b - a) > (1U<<15))) || \
|
||||
((a > b) && ((uint16_t)(a - b) < (1U<<15))))
|
||||
#define SCTP_UINT16_GE(a, b) (SCTP_UINT16_GT(a, b) || (a == b))
|
||||
#define SCTP_UINT32_GT(a, b) (((a < b) && ((uint32_t)(b - a) > (1U<<31))) || \
|
||||
((a > b) && ((uint32_t)(a - b) < (1U<<31))))
|
||||
#define SCTP_UINT32_GE(a, b) (SCTP_UINT32_GT(a, b) || (a == b))
|
||||
|
||||
#define SCTP_SSN_GT(a, b) SCTP_UINT16_GT(a, b)
|
||||
#define SCTP_SSN_GE(a, b) SCTP_UINT16_GE(a, b)
|
||||
#define SCTP_TSN_GT(a, b) SCTP_UINT32_GT(a, b)
|
||||
#define SCTP_TSN_GE(a, b) SCTP_UINT32_GE(a, b)
|
||||
#define SCTP_MSGID_GT(o, a, b) ((o == 1) ? SCTP_UINT16_GT((uint16_t)a, (uint16_t)b) : SCTP_UINT32_GT(a, b))
|
||||
#define SCTP_MSGID_GE(o, a, b) ((o == 1) ? SCTP_UINT16_GE((uint16_t)a, (uint16_t)b) : SCTP_UINT32_GE(a, b))
|
||||
|
||||
/* Mapping array manipulation routines */
|
||||
#define SCTP_IS_TSN_PRESENT(arry, gap) ((arry[(gap >> 3)] >> (gap & 0x07)) & 0x01)
|
||||
|
@ -45,131 +45,131 @@ SDT_PROVIDER_DEFINE(sctp);
|
||||
/********************************************************/
|
||||
/* Initial */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, init,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* ACK-INCREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, ack,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* ACK-INCREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, rttvar,
|
||||
"uint64_t", /* The Vtag << 32 | localport << 16 | remoteport */
|
||||
"uint64_t", /* obw | nbw */
|
||||
"uint64_t", /* bwrtt | newrtt */
|
||||
"uint64_t", /* flight */
|
||||
"uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
"uint64_t", /* The Vtag << 32 | localport << 16 |
|
||||
* remoteport */
|
||||
"uint64_t", /* obw | nbw */
|
||||
"uint64_t", /* bwrtt | newrtt */
|
||||
"uint64_t", /* flight */
|
||||
"uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, rttstep,
|
||||
"uint64_t", /* The Vtag << 32 | localport << 16 | remoteport */
|
||||
"uint64_t", /* obw | nbw */
|
||||
"uint64_t", /* bwrtt | newrtt */
|
||||
"uint64_t", /* flight */
|
||||
"uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
"uint64_t", /* The Vtag << 32 | localport << 16 |
|
||||
* remoteport */
|
||||
"uint64_t", /* obw | nbw */
|
||||
"uint64_t", /* bwrtt | newrtt */
|
||||
"uint64_t", /* flight */
|
||||
"uint64_t"); /* (cwnd << 32) | point << 16 | retval(0/1) */
|
||||
|
||||
/* FastRetransmit-DECREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, fr,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* TimeOut-DECREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, to,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* BurstLimit-DECREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, bl,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* ECN-DECREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, ecn,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/* PacketDrop-DECREASE */
|
||||
SDT_PROBE_DEFINE5(sctp, cwnd, net, pd,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The old value of the cwnd */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/********************************************************/
|
||||
/* Rwnd probe - tracks changes in the receiver window for an assoc */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE4(sctp, rwnd, assoc, val,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/********************************************************/
|
||||
/* flight probe - tracks changes in the flight size on a net or assoc */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE5(sctp, flightsize, net, val,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets * changing */
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"uintptr_t", /* The pointer to the struct sctp_nets *
|
||||
* changing */
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
/********************************************************/
|
||||
/* The total flight version */
|
||||
/********************************************************/
|
||||
SDT_PROBE_DEFINE4(sctp, flightsize, assoc, val,
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /*
|
||||
* The port number of the local side << 16 | port number
|
||||
* of remote in network byte order.
|
||||
*/
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
"uint32_t", /* The Vtag for this end */
|
||||
"uint32_t", /* The port number of the local side << 16 |
|
||||
* port number of remote in network byte
|
||||
* order. */
|
||||
"int", /* The up/down amount */
|
||||
"int"); /* The new value of the cwnd */
|
||||
|
||||
#endif
|
||||
|
@ -152,6 +152,23 @@ struct sctp_data_chunk {
|
||||
struct sctp_data dp;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_idata {
|
||||
uint32_t tsn;
|
||||
uint16_t stream_id;
|
||||
uint16_t reserved; /* Where does the SSN go? */
|
||||
uint32_t msg_id;
|
||||
union {
|
||||
uint32_t protocol_id;
|
||||
uint32_t fsn; /* Fragment Sequence Number */
|
||||
};
|
||||
/* user data follows */
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_idata_chunk {
|
||||
struct sctp_chunkhdr ch;
|
||||
struct sctp_idata dp;
|
||||
} SCTP_PACKED;
|
||||
|
||||
/*
|
||||
* Structures for the control chunks
|
||||
*/
|
||||
@ -378,6 +395,12 @@ struct sctp_strseq {
|
||||
uint16_t sequence;
|
||||
} SCTP_PACKED;
|
||||
|
||||
struct sctp_strseq_mid {
|
||||
uint16_t stream;
|
||||
uint16_t reserved;
|
||||
uint32_t msg_id;
|
||||
};
|
||||
|
||||
struct sctp_forward_tsn_msg {
|
||||
struct sctphdr sh;
|
||||
struct sctp_forward_tsn_chunk msg;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -43,35 +43,31 @@ sctp_build_readq_entry(struct sctp_tcb *stcb,
|
||||
struct sctp_nets *net,
|
||||
uint32_t tsn, uint32_t ppid,
|
||||
uint32_t context, uint16_t stream_no,
|
||||
uint16_t stream_seq, uint8_t flags,
|
||||
uint32_t stream_seq, uint8_t flags,
|
||||
struct mbuf *dm);
|
||||
|
||||
|
||||
#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm) do { \
|
||||
#define sctp_build_readq_entry_mac(_ctl, in_it, context, net, tsn, ppid, stream_no, stream_seq, flags, dm, tfsn, msgid) do { \
|
||||
if (_ctl) { \
|
||||
atomic_add_int(&((net)->ref_count), 1); \
|
||||
memset(_ctl, 0, sizeof(struct sctp_queued_to_read)); \
|
||||
(_ctl)->sinfo_stream = stream_no; \
|
||||
(_ctl)->sinfo_ssn = stream_seq; \
|
||||
TAILQ_INIT(&_ctl->reasm); \
|
||||
(_ctl)->top_fsn = tfsn; \
|
||||
(_ctl)->msg_id = msgid; \
|
||||
(_ctl)->sinfo_flags = (flags << 8); \
|
||||
(_ctl)->sinfo_ppid = ppid; \
|
||||
(_ctl)->sinfo_context = context; \
|
||||
(_ctl)->sinfo_timetolive = 0; \
|
||||
(_ctl)->fsn_included = 0xffffffff; \
|
||||
(_ctl)->top_fsn = 0xffffffff; \
|
||||
(_ctl)->sinfo_tsn = tsn; \
|
||||
(_ctl)->sinfo_cumtsn = tsn; \
|
||||
(_ctl)->sinfo_assoc_id = sctp_get_associd((in_it)); \
|
||||
(_ctl)->length = 0; \
|
||||
(_ctl)->held_length = 0; \
|
||||
(_ctl)->whoFrom = net; \
|
||||
(_ctl)->data = dm; \
|
||||
(_ctl)->tail_mbuf = NULL; \
|
||||
(_ctl)->aux_data = NULL; \
|
||||
(_ctl)->stcb = (in_it); \
|
||||
(_ctl)->port_from = (in_it)->rport; \
|
||||
(_ctl)->spec_flags = 0; \
|
||||
(_ctl)->do_not_ref_stcb = 0; \
|
||||
(_ctl)->end_added = 0; \
|
||||
(_ctl)->pdapi_aborted = 0; \
|
||||
(_ctl)->some_taken = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
@ -386,17 +386,9 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
|
||||
if (asoc->strmin != NULL) {
|
||||
/* Free the old ones */
|
||||
struct sctp_queued_to_read *ctl, *nctl;
|
||||
|
||||
for (i = 0; i < asoc->streamincnt; i++) {
|
||||
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
|
||||
TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
|
||||
sctp_free_remote_addr(ctl->whoFrom);
|
||||
ctl->whoFrom = NULL;
|
||||
sctp_m_freem(ctl->data);
|
||||
ctl->data = NULL;
|
||||
sctp_free_a_readq(stcb, ctl);
|
||||
}
|
||||
sctp_clean_up_stream(stcb, &asoc->strmin[i].inqueue);
|
||||
sctp_clean_up_stream(stcb, &asoc->strmin[i].uno_inqueue);
|
||||
}
|
||||
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
|
||||
}
|
||||
@ -414,8 +406,10 @@ sctp_process_init(struct sctp_init_chunk *cp, struct sctp_tcb *stcb)
|
||||
}
|
||||
for (i = 0; i < asoc->streamincnt; i++) {
|
||||
asoc->strmin[i].stream_no = i;
|
||||
asoc->strmin[i].last_sequence_delivered = 0xffff;
|
||||
asoc->strmin[i].last_sequence_delivered = 0xffffffff;
|
||||
TAILQ_INIT(&asoc->strmin[i].inqueue);
|
||||
TAILQ_INIT(&asoc->strmin[i].uno_inqueue);
|
||||
asoc->strmin[i].pd_api_started = 0;
|
||||
asoc->strmin[i].delivery_started = 0;
|
||||
}
|
||||
/*
|
||||
@ -894,6 +888,29 @@ sctp_handle_shutdown(struct sctp_shutdown_chunk *cp,
|
||||
* With a normal shutdown we assume the end of last record.
|
||||
*/
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
if (asoc->control_pdapi->on_strm_q) {
|
||||
struct sctp_stream_in *strm;
|
||||
|
||||
strm = &asoc->strmin[asoc->control_pdapi->sinfo_stream];
|
||||
if (asoc->control_pdapi->on_strm_q == SCTP_ON_UNORDERED) {
|
||||
/* Unordered */
|
||||
TAILQ_REMOVE(&strm->uno_inqueue, asoc->control_pdapi, next_instrm);
|
||||
asoc->control_pdapi->on_strm_q = 0;
|
||||
} else if (asoc->control_pdapi->on_strm_q == SCTP_ON_ORDERED) {
|
||||
/* Ordered */
|
||||
TAILQ_REMOVE(&strm->inqueue, asoc->control_pdapi, next_instrm);
|
||||
asoc->control_pdapi->on_strm_q = 0;
|
||||
} else {
|
||||
panic("Unknown state on ctrl:%p on_strm_q:%d",
|
||||
asoc->control_pdapi,
|
||||
asoc->control_pdapi->on_strm_q);
|
||||
}
|
||||
}
|
||||
printf("%s:%d End added to ctl:%p (%d)\n",
|
||||
__FUNCTION__,
|
||||
__LINE__,
|
||||
asoc->control_pdapi,
|
||||
asoc->control_pdapi->on_strm_q);
|
||||
asoc->control_pdapi->end_added = 1;
|
||||
asoc->control_pdapi->pdapi_aborted = 1;
|
||||
asoc->control_pdapi = NULL;
|
||||
@ -1009,6 +1026,11 @@ sctp_handle_shutdown_ack(struct sctp_shutdown_ack_chunk *cp SCTP_UNUSED,
|
||||
* With a normal shutdown we assume the end of last record.
|
||||
*/
|
||||
SCTP_INP_READ_LOCK(stcb->sctp_ep);
|
||||
printf("%s:%d End added to ctl:%p (%d)\n",
|
||||
__FUNCTION__,
|
||||
__LINE__,
|
||||
asoc->control_pdapi,
|
||||
asoc->control_pdapi->on_strm_q);
|
||||
asoc->control_pdapi->end_added = 1;
|
||||
asoc->control_pdapi->pdapi_aborted = 1;
|
||||
asoc->control_pdapi = NULL;
|
||||
@ -1083,6 +1105,7 @@ sctp_process_unrecog_chunk(struct sctp_tcb *stcb, struct sctp_paramhdr *phdr,
|
||||
case SCTP_ASCONF:
|
||||
sctp_asconf_cleanup(stcb, net);
|
||||
break;
|
||||
case SCTP_IFORWARD_CUM_TSN:
|
||||
case SCTP_FORWARD_CUM_TSN:
|
||||
stcb->asoc.prsctp_supported = 0;
|
||||
break;
|
||||
@ -3450,6 +3473,7 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
|
||||
/* resend last asconf ack */
|
||||
sctp_send_asconf_ack(stcb);
|
||||
break;
|
||||
case SCTP_IFORWARD_CUM_TSN:
|
||||
case SCTP_FORWARD_CUM_TSN:
|
||||
send_forward_tsn(stcb, &stcb->asoc);
|
||||
break;
|
||||
@ -3475,8 +3499,8 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *
|
||||
uint16_t temp;
|
||||
|
||||
/*
|
||||
* We set things to 0xffff since this is the last delivered sequence
|
||||
* and we will be sending in 0 after the reset.
|
||||
* We set things to 0xffffffff since this is the last delivered
|
||||
* sequence and we will be sending in 0 after the reset.
|
||||
*/
|
||||
|
||||
if (number_entries) {
|
||||
@ -3485,12 +3509,12 @@ sctp_reset_in_stream(struct sctp_tcb *stcb, uint32_t number_entries, uint16_t *
|
||||
if (temp >= stcb->asoc.streamincnt) {
|
||||
continue;
|
||||
}
|
||||
stcb->asoc.strmin[temp].last_sequence_delivered = 0xffff;
|
||||
stcb->asoc.strmin[temp].last_sequence_delivered = 0xffffffff;
|
||||
}
|
||||
} else {
|
||||
list = NULL;
|
||||
for (i = 0; i < stcb->asoc.streamincnt; i++) {
|
||||
stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
|
||||
stcb->asoc.strmin[i].last_sequence_delivered = 0xffffffff;
|
||||
}
|
||||
}
|
||||
sctp_ulp_notify(SCTP_NOTIFY_STR_RESET_RECV, stcb, number_entries, (void *)list, SCTP_SO_NOT_LOCKED);
|
||||
@ -4031,20 +4055,28 @@ sctp_handle_str_reset_add_strm(struct sctp_tcb *stcb, struct sctp_tmit_chunk *ch
|
||||
/* copy off the old data */
|
||||
for (i = 0; i < stcb->asoc.streamincnt; i++) {
|
||||
TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
|
||||
TAILQ_INIT(&stcb->asoc.strmin[i].uno_inqueue);
|
||||
stcb->asoc.strmin[i].stream_no = i;
|
||||
stcb->asoc.strmin[i].last_sequence_delivered = oldstrm[i].last_sequence_delivered;
|
||||
stcb->asoc.strmin[i].delivery_started = oldstrm[i].delivery_started;
|
||||
stcb->asoc.strmin[i].pd_api_started = oldstrm[i].pd_api_started;
|
||||
/* now anything on those queues? */
|
||||
TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next, nctl) {
|
||||
TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next);
|
||||
TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next);
|
||||
TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].inqueue, next_instrm, nctl) {
|
||||
TAILQ_REMOVE(&oldstrm[i].inqueue, ctl, next_instrm);
|
||||
TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].inqueue, ctl, next_instrm);
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(ctl, &oldstrm[i].uno_inqueue, next_instrm, nctl) {
|
||||
TAILQ_REMOVE(&oldstrm[i].uno_inqueue, ctl, next_instrm);
|
||||
TAILQ_INSERT_TAIL(&stcb->asoc.strmin[i].uno_inqueue, ctl, next_instrm);
|
||||
}
|
||||
}
|
||||
/* Init the new streams */
|
||||
for (i = stcb->asoc.streamincnt; i < num_stream; i++) {
|
||||
TAILQ_INIT(&stcb->asoc.strmin[i].inqueue);
|
||||
TAILQ_INIT(&stcb->asoc.strmin[i].uno_inqueue);
|
||||
stcb->asoc.strmin[i].stream_no = i;
|
||||
stcb->asoc.strmin[i].last_sequence_delivered = 0xffff;
|
||||
stcb->asoc.strmin[i].last_sequence_delivered = 0xffffffff;
|
||||
stcb->asoc.strmin[i].pd_api_started = 0;
|
||||
stcb->asoc.strmin[i].delivery_started = 0;
|
||||
}
|
||||
SCTP_FREE(oldstrm, SCTP_M_STRMI);
|
||||
@ -5441,6 +5473,7 @@ process_control_chunks:
|
||||
}
|
||||
break;
|
||||
case SCTP_FORWARD_CUM_TSN:
|
||||
case SCTP_IFORWARD_CUM_TSN:
|
||||
SCTPDBG(SCTP_DEBUG_INPUT3, "SCTP_FWD-TSN\n");
|
||||
if (chk_length < sizeof(struct sctp_forward_tsn_chunk)) {
|
||||
/* Its not ours */
|
||||
|
@ -480,9 +480,9 @@ sctp_get_mbuf_for_msg(unsigned int space_needed,
|
||||
#define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \
|
||||
{ \
|
||||
int32_t oldval; \
|
||||
oldval = atomic_fetchadd_int(addr, -val); \
|
||||
oldval = atomic_fetchadd_int(addr, -val); \
|
||||
if (oldval < val) { \
|
||||
panic("Counter goes negative"); \
|
||||
panic("Counter goes negative addr:%p val:%d oldval:%d", addr, val, oldval); \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
|
@ -3326,10 +3326,11 @@ sctp_source_address_selection(struct sctp_inpcb *inp,
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Rules: - Find the route if needed, cache if I can. - Look at
|
||||
* interface address in route, Is it in the bound list. If so we
|
||||
* have the best source. - If not we must rotate amongst the
|
||||
* addresses.
|
||||
* Rules:
|
||||
* - Find the route if needed, cache if I can.
|
||||
* - Look at interface address in route, Is it in the bound list. If so we
|
||||
* have the best source.
|
||||
* - If not we must rotate amongst the addresses.
|
||||
*
|
||||
* Cavets and issues
|
||||
*
|
||||
@ -4796,6 +4797,9 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+chunk_len);
|
||||
if (stcb->asoc.prsctp_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
if (stcb->asoc.idata_supported) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_IFORWARD_CUM_TSN;
|
||||
}
|
||||
}
|
||||
if (stcb->asoc.auth_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
|
||||
@ -4807,6 +4811,9 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
|
||||
if (stcb->asoc.reconfig_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
|
||||
}
|
||||
if (stcb->asoc.idata_supported) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_IDATA;
|
||||
}
|
||||
if (stcb->asoc.nrsack_supported == 1) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
|
||||
}
|
||||
@ -5951,6 +5958,10 @@ do_a_abort:
|
||||
if (((asoc != NULL) && (asoc->prsctp_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->prsctp_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
|
||||
if (((asoc != NULL) && (asoc->idata_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->idata_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_IFORWARD_CUM_TSN;
|
||||
}
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->auth_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->auth_supported == 1))) {
|
||||
@ -5965,6 +5976,10 @@ do_a_abort:
|
||||
((asoc == NULL) && (inp->reconfig_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->idata_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->idata_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_IDATA;
|
||||
}
|
||||
if (((asoc != NULL) && (asoc->nrsack_supported == 1)) ||
|
||||
((asoc == NULL) && (inp->nrsack_supported == 1))) {
|
||||
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
|
||||
@ -6232,11 +6247,15 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
|
||||
* we use a larger frag point.
|
||||
*/
|
||||
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
|
||||
ovh = SCTP_MED_OVERHEAD;
|
||||
ovh = SCTP_MIN_OVERHEAD;
|
||||
} else {
|
||||
ovh = SCTP_MED_V4_OVERHEAD;
|
||||
ovh = SCTP_MIN_V4_OVERHEAD;
|
||||
}
|
||||
if (stcb->asoc.idata_supported) {
|
||||
ovh += sizeof(struct sctp_idata_chunk);
|
||||
} else {
|
||||
ovh += sizeof(struct sctp_data_chunk);
|
||||
}
|
||||
|
||||
if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu)
|
||||
siz = asoc->smallest_mtu - ovh;
|
||||
else
|
||||
@ -6361,6 +6380,8 @@ sctp_msg_append(struct sctp_tcb *stcb,
|
||||
sp->timetolive = srcv->sinfo_timetolive;
|
||||
sp->ppid = srcv->sinfo_ppid;
|
||||
sp->context = srcv->sinfo_context;
|
||||
sp->fsn = 0;
|
||||
sp->msg_id = atomic_fetchadd_int(&stcb->asoc.assoc_msg_id, 1);
|
||||
if (sp->sinfo_flags & SCTP_ADDR_OVER) {
|
||||
sp->net = net;
|
||||
atomic_add_int(&sp->net->ref_count, 1);
|
||||
@ -7163,8 +7184,9 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
struct sctp_association *asoc;
|
||||
struct sctp_stream_queue_pending *sp;
|
||||
struct sctp_tmit_chunk *chk;
|
||||
struct sctp_data_chunk *dchkh;
|
||||
uint32_t to_move, length;
|
||||
struct sctp_data_chunk *dchkh = NULL;
|
||||
struct sctp_idata_chunk *ndchkh = NULL;
|
||||
uint32_t to_move, length, leading;
|
||||
uint8_t rcv_flags = 0;
|
||||
uint8_t some_taken;
|
||||
uint8_t send_lock_up = 0;
|
||||
@ -7173,6 +7195,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
||||
asoc = &stcb->asoc;
|
||||
one_more_time:
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
*locked = 0;
|
||||
sp = TAILQ_FIRST(&strq->outqueue);
|
||||
if (sp == NULL) {
|
||||
*locked = 0;
|
||||
@ -7184,7 +7207,9 @@ one_more_time:
|
||||
if (sp) {
|
||||
goto one_more_time;
|
||||
}
|
||||
if (strq->last_msg_incomplete) {
|
||||
if ((sctp_is_feature_on(stcb->sctp_ep, SCTP_PCB_FLAGS_EXPLICIT_EOR) == 0) &&
|
||||
(stcb->asoc.idata_supported == 0) &&
|
||||
(strq->last_msg_incomplete)) {
|
||||
SCTP_PRINTF("Huh? Stream:%d lm_in_c=%d but queue is NULL\n",
|
||||
strq->stream_no,
|
||||
strq->last_msg_incomplete);
|
||||
@ -7248,7 +7273,8 @@ one_more_time:
|
||||
* sender just finished this but still holds a
|
||||
* reference
|
||||
*/
|
||||
*locked = 1;
|
||||
if (stcb->asoc.idata_supported == 0)
|
||||
*locked = 1;
|
||||
*giveup = 1;
|
||||
to_move = 0;
|
||||
goto out_of;
|
||||
@ -7257,7 +7283,8 @@ one_more_time:
|
||||
/* is there some to get */
|
||||
if (sp->length == 0) {
|
||||
/* no */
|
||||
*locked = 1;
|
||||
if (stcb->asoc.idata_supported == 0)
|
||||
*locked = 1;
|
||||
*giveup = 1;
|
||||
to_move = 0;
|
||||
goto out_of;
|
||||
@ -7280,7 +7307,8 @@ one_more_time:
|
||||
}
|
||||
sp->length = 0;
|
||||
sp->some_taken = 1;
|
||||
*locked = 1;
|
||||
if (stcb->asoc.idata_supported == 0)
|
||||
*locked = 1;
|
||||
*giveup = 1;
|
||||
to_move = 0;
|
||||
goto out_of;
|
||||
@ -7342,7 +7370,8 @@ re_look:
|
||||
}
|
||||
} else {
|
||||
/* Nothing to take. */
|
||||
if (sp->some_taken) {
|
||||
if ((sp->some_taken) &&
|
||||
(stcb->asoc.idata_supported == 0)) {
|
||||
*locked = 1;
|
||||
}
|
||||
*giveup = 1;
|
||||
@ -7461,7 +7490,12 @@ dont_do_it:
|
||||
} else {
|
||||
atomic_subtract_int(&sp->length, to_move);
|
||||
}
|
||||
if (M_LEADINGSPACE(chk->data) < (int)sizeof(struct sctp_data_chunk)) {
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
leading = (int)sizeof(struct sctp_data_chunk);
|
||||
} else {
|
||||
leading = (int)sizeof(struct sctp_idata_chunk);
|
||||
}
|
||||
if (M_LEADINGSPACE(chk->data) < leading) {
|
||||
/* Not enough room for a chunk header, get some */
|
||||
struct mbuf *m;
|
||||
|
||||
@ -7502,7 +7536,11 @@ dont_do_it:
|
||||
M_ALIGN(chk->data, 4);
|
||||
}
|
||||
}
|
||||
SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_NOWAIT);
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_data_chunk), M_NOWAIT);
|
||||
} else {
|
||||
SCTP_BUF_PREPEND(chk->data, sizeof(struct sctp_idata_chunk), M_NOWAIT);
|
||||
}
|
||||
if (chk->data == NULL) {
|
||||
/* HELP, TSNH since we assured it would not above? */
|
||||
#ifdef INVARIANTS
|
||||
@ -7515,8 +7553,13 @@ dont_do_it:
|
||||
to_move = 0;
|
||||
goto out_of;
|
||||
}
|
||||
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
|
||||
chk->book_size = chk->send_size = (uint16_t) (to_move + sizeof(struct sctp_data_chunk));
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
|
||||
chk->book_size = chk->send_size = (uint16_t) (to_move + sizeof(struct sctp_data_chunk));
|
||||
} else {
|
||||
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_idata_chunk));
|
||||
chk->book_size = chk->send_size = (uint16_t) (to_move + sizeof(struct sctp_idata_chunk));
|
||||
}
|
||||
chk->book_size_scale = 0;
|
||||
chk->sent = SCTP_DATAGRAM_UNSENT;
|
||||
|
||||
@ -7555,7 +7598,11 @@ dont_do_it:
|
||||
(uint32_t) ((chk->rec.data.stream_number << 16) | chk->rec.data.stream_seq),
|
||||
chk->rec.data.TSN_seq);
|
||||
}
|
||||
dchkh = mtod(chk->data, struct sctp_data_chunk *);
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
dchkh = mtod(chk->data, struct sctp_data_chunk *);
|
||||
} else {
|
||||
ndchkh = mtod(chk->data, struct sctp_idata_chunk *);
|
||||
}
|
||||
/*
|
||||
* Put the rest of the things in place now. Size was done earlier in
|
||||
* previous loop prior to padding.
|
||||
@ -7577,14 +7624,29 @@ dont_do_it:
|
||||
asoc->out_tsnlog[asoc->tsn_out_at].in_out = 2;
|
||||
asoc->tsn_out_at++;
|
||||
#endif
|
||||
|
||||
dchkh->ch.chunk_type = SCTP_DATA;
|
||||
dchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
|
||||
dchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
|
||||
dchkh->dp.stream_id = htons(strq->stream_no);
|
||||
dchkh->dp.stream_sequence = htons(chk->rec.data.stream_seq);
|
||||
dchkh->dp.protocol_id = chk->rec.data.payloadtype;
|
||||
dchkh->ch.chunk_length = htons(chk->send_size);
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
dchkh->ch.chunk_type = SCTP_DATA;
|
||||
dchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
|
||||
dchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
|
||||
dchkh->dp.stream_id = htons((strq->stream_no & 0x0000ffff));
|
||||
dchkh->dp.stream_sequence = htons(chk->rec.data.stream_seq);
|
||||
dchkh->dp.protocol_id = chk->rec.data.payloadtype;
|
||||
dchkh->ch.chunk_length = htons(chk->send_size);
|
||||
} else {
|
||||
ndchkh->ch.chunk_type = SCTP_IDATA;
|
||||
ndchkh->ch.chunk_flags = chk->rec.data.rcv_flags;
|
||||
ndchkh->dp.tsn = htonl(chk->rec.data.TSN_seq);
|
||||
ndchkh->dp.stream_id = htons(strq->stream_no);
|
||||
/* WHAT DO WE DO HERE??? */
|
||||
ndchkh->dp.reserved = htons(0);
|
||||
ndchkh->dp.msg_id = htonl(sp->msg_id);
|
||||
if (sp->fsn == 0)
|
||||
ndchkh->dp.protocol_id = chk->rec.data.payloadtype;
|
||||
else
|
||||
ndchkh->dp.fsn = htonl(sp->fsn);
|
||||
sp->fsn++;
|
||||
ndchkh->ch.chunk_length = htons(chk->send_size);
|
||||
}
|
||||
/* Now advance the chk->send_size by the actual pad needed. */
|
||||
if (chk->send_size < SCTP_SIZE32(chk->book_size)) {
|
||||
/* need a pad */
|
||||
@ -7640,7 +7702,8 @@ dont_do_it:
|
||||
stcb->asoc.locked_on_sending = NULL;
|
||||
} else {
|
||||
/* more to go, we are locked */
|
||||
*locked = 1;
|
||||
if (stcb->asoc.idata_supported == 0)
|
||||
*locked = 1;
|
||||
}
|
||||
asoc->chunks_on_out_queue++;
|
||||
strq->chunks_on_queues++;
|
||||
@ -7686,7 +7749,11 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
|
||||
break;
|
||||
}
|
||||
/* Need an allowance for the data chunk header too */
|
||||
goal_mtu -= sizeof(struct sctp_data_chunk);
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
goal_mtu -= sizeof(struct sctp_data_chunk);
|
||||
} else {
|
||||
goal_mtu -= sizeof(struct sctp_idata_chunk);
|
||||
}
|
||||
|
||||
/* must make even word boundary */
|
||||
goal_mtu &= 0xfffffffc;
|
||||
@ -7797,12 +7864,15 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
|
||||
{
|
||||
/**
|
||||
* Ok this is the generic chunk service queue. we must do the
|
||||
* following: - Service the stream queue that is next, moving any
|
||||
* message (note I must get a complete message i.e. FIRST/MIDDLE and
|
||||
* LAST to the out queue in one pass) and assigning TSN's - Check to
|
||||
* see if the cwnd/rwnd allows any output, if so we go ahead and
|
||||
* fomulate and send the low level chunks. Making sure to combine
|
||||
* any control in the control chunk queue also.
|
||||
* following:
|
||||
* - Service the stream queue that is next, moving any
|
||||
* message (note I must get a complete message i.e. FIRST/MIDDLE and
|
||||
* LAST to the out queue in one pass) and assigning TSN's. This
|
||||
* only applys though if the peer does not support NDATA. For NDATA
|
||||
* chunks its ok to not send the entire message ;-)
|
||||
* - Check to see if the cwnd/rwnd allows any output, if so we go ahead and
|
||||
* fomulate and send the low level chunks. Making sure to combine
|
||||
* any control in the control chunk queue also.
|
||||
*/
|
||||
struct sctp_nets *net, *start_at, *sack_goes_to = NULL, *old_start_at = NULL;
|
||||
struct mbuf *outchain, *endoutchain;
|
||||
@ -10225,7 +10295,13 @@ send_forward_tsn(struct sctp_tcb *stcb,
|
||||
struct sctp_tmit_chunk *chk;
|
||||
struct sctp_forward_tsn_chunk *fwdtsn;
|
||||
uint32_t advance_peer_ack_point;
|
||||
int old;
|
||||
|
||||
if (asoc->idata_supported) {
|
||||
old = 0;
|
||||
} else {
|
||||
old = 1;
|
||||
}
|
||||
SCTP_TCB_LOCK_ASSERT(stcb);
|
||||
TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
|
||||
if (chk->rec.chunk_id.id == SCTP_FORWARD_CUM_TSN) {
|
||||
@ -10247,6 +10323,11 @@ send_forward_tsn(struct sctp_tcb *stcb,
|
||||
}
|
||||
asoc->fwd_tsn_cnt++;
|
||||
chk->copy_by_ref = 0;
|
||||
/*
|
||||
* We don't do the old thing here since this is used not for on-wire
|
||||
* but to tell if we are sending a fwd-tsn by the stack during
|
||||
* output. And if its a IFORWARD or a FORWARD it is a fwd-tsn.
|
||||
*/
|
||||
chk->rec.chunk_id.id = SCTP_FORWARD_CUM_TSN;
|
||||
chk->rec.chunk_id.can_take_data = 0;
|
||||
chk->flags = 0;
|
||||
@ -10271,6 +10352,7 @@ sctp_fill_in_rest:
|
||||
{
|
||||
struct sctp_tmit_chunk *at, *tp1, *last;
|
||||
struct sctp_strseq *strseq;
|
||||
struct sctp_strseq_mid *strseq_m;
|
||||
unsigned int cnt_of_space, i, ovh;
|
||||
unsigned int space_needed;
|
||||
unsigned int cnt_of_skipped = 0;
|
||||
@ -10287,9 +10369,13 @@ sctp_fill_in_rest:
|
||||
}
|
||||
cnt_of_skipped++;
|
||||
}
|
||||
space_needed = (sizeof(struct sctp_forward_tsn_chunk) +
|
||||
(cnt_of_skipped * sizeof(struct sctp_strseq)));
|
||||
|
||||
if (old) {
|
||||
space_needed = (sizeof(struct sctp_forward_tsn_chunk) +
|
||||
(cnt_of_skipped * sizeof(struct sctp_strseq)));
|
||||
} else {
|
||||
space_needed = (sizeof(struct sctp_forward_tsn_chunk) +
|
||||
(cnt_of_skipped * sizeof(struct sctp_strseq_mid)));
|
||||
}
|
||||
cnt_of_space = (unsigned int)M_TRAILINGSPACE(chk->data);
|
||||
|
||||
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
|
||||
@ -10318,8 +10404,13 @@ sctp_fill_in_rest:
|
||||
0xff, 0xff, cnt_of_space,
|
||||
space_needed);
|
||||
}
|
||||
cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk);
|
||||
cnt_of_skipped /= sizeof(struct sctp_strseq);
|
||||
if (old) {
|
||||
cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk);
|
||||
cnt_of_skipped /= sizeof(struct sctp_strseq);
|
||||
} else {
|
||||
cnt_of_skipped = cnt_of_space - sizeof(struct sctp_forward_tsn_chunk);
|
||||
cnt_of_skipped /= sizeof(struct sctp_strseq_mid);
|
||||
}
|
||||
/*-
|
||||
* Go through and find the TSN that will be the one
|
||||
* we report.
|
||||
@ -10346,15 +10437,24 @@ sctp_fill_in_rest:
|
||||
*/
|
||||
if (last)
|
||||
advance_peer_ack_point = last->rec.data.TSN_seq;
|
||||
space_needed = sizeof(struct sctp_forward_tsn_chunk) +
|
||||
cnt_of_skipped * sizeof(struct sctp_strseq);
|
||||
if (old) {
|
||||
space_needed = sizeof(struct sctp_forward_tsn_chunk) +
|
||||
cnt_of_skipped * sizeof(struct sctp_strseq);
|
||||
} else {
|
||||
space_needed = sizeof(struct sctp_forward_tsn_chunk) +
|
||||
cnt_of_skipped * sizeof(struct sctp_strseq_mid);
|
||||
}
|
||||
}
|
||||
chk->send_size = space_needed;
|
||||
/* Setup the chunk */
|
||||
fwdtsn = mtod(chk->data, struct sctp_forward_tsn_chunk *);
|
||||
fwdtsn->ch.chunk_length = htons(chk->send_size);
|
||||
fwdtsn->ch.chunk_flags = 0;
|
||||
fwdtsn->ch.chunk_type = SCTP_FORWARD_CUM_TSN;
|
||||
if (old) {
|
||||
fwdtsn->ch.chunk_type = SCTP_FORWARD_CUM_TSN;
|
||||
} else {
|
||||
fwdtsn->ch.chunk_type = SCTP_IFORWARD_CUM_TSN;
|
||||
}
|
||||
fwdtsn->new_cumulative_tsn = htonl(advance_peer_ack_point);
|
||||
SCTP_BUF_LEN(chk->data) = chk->send_size;
|
||||
fwdtsn++;
|
||||
@ -10362,7 +10462,11 @@ sctp_fill_in_rest:
|
||||
* Move pointer to after the fwdtsn and transfer to the
|
||||
* strseq pointer.
|
||||
*/
|
||||
strseq = (struct sctp_strseq *)fwdtsn;
|
||||
if (old) {
|
||||
strseq = (struct sctp_strseq *)fwdtsn;
|
||||
} else {
|
||||
strseq_m = (struct sctp_strseq_mid *)fwdtsn;
|
||||
}
|
||||
/*-
|
||||
* Now populate the strseq list. This is done blindly
|
||||
* without pulling out duplicate stream info. This is
|
||||
@ -10389,9 +10493,15 @@ sctp_fill_in_rest:
|
||||
if (at->rec.data.TSN_seq == advance_peer_ack_point) {
|
||||
at->rec.data.fwd_tsn_cnt = 0;
|
||||
}
|
||||
strseq->stream = ntohs(at->rec.data.stream_number);
|
||||
strseq->sequence = ntohs(at->rec.data.stream_seq);
|
||||
strseq++;
|
||||
if (old) {
|
||||
strseq->stream = ntohs(at->rec.data.stream_number);
|
||||
strseq->sequence = ntohs(at->rec.data.stream_seq);
|
||||
strseq++;
|
||||
} else {
|
||||
strseq_m->stream = ntohs(at->rec.data.stream_number);
|
||||
strseq_m->msg_id = ntohl(at->rec.data.stream_seq);
|
||||
strseq_m++;
|
||||
}
|
||||
at = tp1;
|
||||
}
|
||||
}
|
||||
@ -12312,6 +12422,8 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
|
||||
sp->timetolive = srcv->sinfo_timetolive;
|
||||
sp->ppid = srcv->sinfo_ppid;
|
||||
sp->context = srcv->sinfo_context;
|
||||
sp->fsn = 0;
|
||||
sp->msg_id = atomic_fetchadd_int(&stcb->asoc.assoc_msg_id, 1);
|
||||
(void)SCTP_GETTIME_TIMEVAL(&sp->ts);
|
||||
|
||||
sp->stream = srcv->sinfo_stream;
|
||||
@ -13065,8 +13177,10 @@ skip_preblock:
|
||||
* interrupt.
|
||||
*/
|
||||
strm->last_msg_incomplete = 1;
|
||||
asoc->stream_locked = 1;
|
||||
asoc->stream_locked_on = srcv->sinfo_stream;
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
asoc->stream_locked = 1;
|
||||
asoc->stream_locked_on = srcv->sinfo_stream;
|
||||
}
|
||||
sp->sender_all_done = 0;
|
||||
}
|
||||
sctp_snd_sb_alloc(stcb, sp->length);
|
||||
@ -13325,8 +13439,10 @@ skip_preblock:
|
||||
if (sp) {
|
||||
if (sp->msg_is_complete == 0) {
|
||||
strm->last_msg_incomplete = 1;
|
||||
asoc->stream_locked = 1;
|
||||
asoc->stream_locked_on = srcv->sinfo_stream;
|
||||
if (stcb->asoc.idata_supported == 0) {
|
||||
asoc->stream_locked = 1;
|
||||
asoc->stream_locked_on = srcv->sinfo_stream;
|
||||
}
|
||||
} else {
|
||||
sp->sender_all_done = 1;
|
||||
strm->last_msg_incomplete = 0;
|
||||
|
@ -2476,6 +2476,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
inp->reconfig_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_reconfig_enable);
|
||||
inp->nrsack_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_nrsack_enable);
|
||||
inp->pktdrop_supported = (uint8_t) SCTP_BASE_SYSCTL(sctp_pktdrop_enable);
|
||||
inp->idata_supported = 0;
|
||||
|
||||
inp->fibnum = so->so_fibnum;
|
||||
/* init the small hash table we use to track asocid <-> tcb */
|
||||
inp->sctp_asocidhash = SCTP_HASH_INIT(SCTP_STACK_VTAG_HASH_SIZE, &inp->hashasocidmark);
|
||||
@ -3660,8 +3662,7 @@ sctp_inpcb_free(struct sctp_inpcb *inp, int immediate, int from)
|
||||
* no need to free the net count, since at this point all
|
||||
* assoc's are gone.
|
||||
*/
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq);
|
||||
SCTP_DECR_READQ_COUNT();
|
||||
sctp_free_a_readq(NULL, sq);
|
||||
}
|
||||
/* Now the sctp_pcb things */
|
||||
/*
|
||||
@ -4649,6 +4650,45 @@ sctp_add_vtag_to_timewait(uint32_t tag, uint32_t time, uint16_t lport, uint16_t
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sctp_clean_up_stream(struct sctp_tcb *stcb, struct sctp_readhead *rh)
|
||||
{
|
||||
struct sctp_tmit_chunk *chk, *nchk;
|
||||
struct sctp_queued_to_read *ctl, *nctl;
|
||||
|
||||
TAILQ_FOREACH_SAFE(ctl, rh, next_instrm, nctl) {
|
||||
TAILQ_REMOVE(rh, ctl, next_instrm);
|
||||
ctl->on_strm_q = 0;
|
||||
if (ctl->on_read_q == 0) {
|
||||
sctp_free_remote_addr(ctl->whoFrom);
|
||||
if (ctl->data) {
|
||||
sctp_m_freem(ctl->data);
|
||||
ctl->data = NULL;
|
||||
}
|
||||
}
|
||||
/* Reassembly free? */
|
||||
TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
|
||||
TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->holds_key_ref)
|
||||
sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
|
||||
SCTP_DECR_CHK_COUNT();
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
}
|
||||
/*
|
||||
* We don't free the address here since all the net's were
|
||||
* freed above.
|
||||
*/
|
||||
if (ctl->on_read_q == 0) {
|
||||
sctp_free_a_readq(stcb, ctl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-
|
||||
@ -4986,8 +5026,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
sq->whoFrom = NULL;
|
||||
sq->stcb = NULL;
|
||||
/* Free the ctl entry */
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), sq);
|
||||
SCTP_DECR_READQ_COUNT();
|
||||
sctp_free_a_readq(stcb, sq);
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(chk, &asoc->free_chunks, sctp_next, nchk) {
|
||||
@ -5100,20 +5139,6 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
SCTP_DECR_CHK_COUNT();
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
|
||||
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
if (chk->holds_key_ref)
|
||||
sctp_auth_key_release(stcb, chk->auth_keyid, SCTP_SO_LOCKED);
|
||||
sctp_free_remote_addr(chk->whoTo);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_chunk), chk);
|
||||
SCTP_DECR_CHK_COUNT();
|
||||
/* sa_ignore FREED_MEMORY */
|
||||
}
|
||||
|
||||
if (asoc->mapping_array) {
|
||||
SCTP_FREE(asoc->mapping_array, SCTP_M_MAP);
|
||||
asoc->mapping_array = NULL;
|
||||
@ -5129,23 +5154,9 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
|
||||
}
|
||||
asoc->strm_realoutsize = asoc->streamoutcnt = 0;
|
||||
if (asoc->strmin) {
|
||||
struct sctp_queued_to_read *ctl, *nctl;
|
||||
|
||||
for (i = 0; i < asoc->streamincnt; i++) {
|
||||
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[i].inqueue, next, nctl) {
|
||||
TAILQ_REMOVE(&asoc->strmin[i].inqueue, ctl, next);
|
||||
sctp_free_remote_addr(ctl->whoFrom);
|
||||
if (ctl->data) {
|
||||
sctp_m_freem(ctl->data);
|
||||
ctl->data = NULL;
|
||||
}
|
||||
/*
|
||||
* We don't free the address here since all
|
||||
* the net's were freed above.
|
||||
*/
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
|
||||
SCTP_DECR_READQ_COUNT();
|
||||
}
|
||||
sctp_clean_up_stream(stcb, &asoc->strmin[i].inqueue);
|
||||
sctp_clean_up_stream(stcb, &asoc->strmin[i].uno_inqueue);
|
||||
}
|
||||
SCTP_FREE(asoc->strmin, SCTP_M_STRMI);
|
||||
asoc->strmin = NULL;
|
||||
@ -6094,6 +6105,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
uint8_t peer_supports_reconfig;
|
||||
uint8_t peer_supports_nrsack;
|
||||
uint8_t peer_supports_pktdrop;
|
||||
uint8_t peer_supports_idata;
|
||||
|
||||
#ifdef INET
|
||||
struct sockaddr_in sin;
|
||||
@ -6122,6 +6134,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
} else {
|
||||
sa = src;
|
||||
}
|
||||
peer_supports_idata = 0;
|
||||
peer_supports_ecn = 0;
|
||||
peer_supports_prsctp = 0;
|
||||
peer_supports_auth = 0;
|
||||
@ -6502,6 +6515,9 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
|
||||
case SCTP_AUTHENTICATION:
|
||||
peer_supports_auth = 1;
|
||||
break;
|
||||
case SCTP_IDATA:
|
||||
peer_supports_idata = 1;
|
||||
break;
|
||||
default:
|
||||
/* one I have not learned yet */
|
||||
break;
|
||||
@ -6660,6 +6676,10 @@ next_param:
|
||||
(peer_supports_reconfig == 0)) {
|
||||
stcb->asoc.reconfig_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.idata_supported == 1) &&
|
||||
(peer_supports_idata == 0)) {
|
||||
stcb->asoc.idata_supported = 0;
|
||||
}
|
||||
if ((stcb->asoc.nrsack_supported == 1) &&
|
||||
(peer_supports_nrsack == 0)) {
|
||||
stcb->asoc.nrsack_supported = 0;
|
||||
@ -6851,26 +6871,9 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
|
||||
SCTP_STAT_INCR(sctps_protocol_drains_done);
|
||||
cumulative_tsn_p1 = asoc->cumulative_tsn + 1;
|
||||
cnt = 0;
|
||||
/* First look in the re-assembly queue */
|
||||
TAILQ_FOREACH_SAFE(chk, &asoc->reasmqueue, sctp_next, nchk) {
|
||||
if (SCTP_TSN_GT(chk->rec.data.TSN_seq, cumulative_tsn_p1)) {
|
||||
/* Yep it is above cum-ack */
|
||||
cnt++;
|
||||
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn);
|
||||
asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
|
||||
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
|
||||
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
TAILQ_REMOVE(&asoc->reasmqueue, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
}
|
||||
/* Ok that was fun, now we will drain all the inbound streams? */
|
||||
for (strmat = 0; strmat < asoc->streamincnt; strmat++) {
|
||||
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next, nctl) {
|
||||
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].inqueue, next_instrm, nctl) {
|
||||
if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
|
||||
/* Yep it is above cum-ack */
|
||||
cnt++;
|
||||
@ -6878,14 +6881,58 @@ sctp_drain_mbufs(struct sctp_tcb *stcb)
|
||||
asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
|
||||
sctp_ucount_decr(asoc->cnt_on_all_streams);
|
||||
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, ctl, next);
|
||||
TAILQ_REMOVE(&asoc->strmin[strmat].inqueue, ctl, next_instrm);
|
||||
if (ctl->data) {
|
||||
sctp_m_freem(ctl->data);
|
||||
ctl->data = NULL;
|
||||
}
|
||||
sctp_free_remote_addr(ctl->whoFrom);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), ctl);
|
||||
SCTP_DECR_READQ_COUNT();
|
||||
/* Now its reasm? */
|
||||
TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
|
||||
cnt++;
|
||||
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn);
|
||||
asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
|
||||
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
|
||||
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
sctp_free_a_readq(stcb, ctl);
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH_SAFE(ctl, &asoc->strmin[strmat].uno_inqueue, next_instrm, nctl) {
|
||||
if (SCTP_TSN_GT(ctl->sinfo_tsn, cumulative_tsn_p1)) {
|
||||
/* Yep it is above cum-ack */
|
||||
cnt++;
|
||||
SCTP_CALC_TSN_TO_GAP(gap, ctl->sinfo_tsn, asoc->mapping_array_base_tsn);
|
||||
asoc->size_on_all_streams = sctp_sbspace_sub(asoc->size_on_all_streams, ctl->length);
|
||||
sctp_ucount_decr(asoc->cnt_on_all_streams);
|
||||
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
TAILQ_REMOVE(&asoc->strmin[strmat].uno_inqueue, ctl, next_instrm);
|
||||
if (ctl->data) {
|
||||
sctp_m_freem(ctl->data);
|
||||
ctl->data = NULL;
|
||||
}
|
||||
sctp_free_remote_addr(ctl->whoFrom);
|
||||
/* Now its reasm? */
|
||||
TAILQ_FOREACH_SAFE(chk, &ctl->reasm, sctp_next, nchk) {
|
||||
cnt++;
|
||||
SCTP_CALC_TSN_TO_GAP(gap, chk->rec.data.TSN_seq, asoc->mapping_array_base_tsn);
|
||||
asoc->size_on_reasm_queue = sctp_sbspace_sub(asoc->size_on_reasm_queue, chk->send_size);
|
||||
sctp_ucount_decr(asoc->cnt_on_reasm_queue);
|
||||
SCTP_UNSET_TSN_PRESENT(asoc->mapping_array, gap);
|
||||
TAILQ_REMOVE(&ctl->reasm, chk, sctp_next);
|
||||
if (chk->data) {
|
||||
sctp_m_freem(chk->data);
|
||||
chk->data = NULL;
|
||||
}
|
||||
sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
|
||||
}
|
||||
sctp_free_a_readq(stcb, ctl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -410,6 +410,7 @@ struct sctp_inpcb {
|
||||
uint8_t ecn_supported;
|
||||
uint8_t prsctp_supported;
|
||||
uint8_t auth_supported;
|
||||
uint8_t idata_supported;
|
||||
uint8_t asconf_supported;
|
||||
uint8_t reconfig_supported;
|
||||
uint8_t nrsack_supported;
|
||||
@ -629,6 +630,8 @@ int sctp_destination_is_reachable(struct sctp_tcb *, struct sockaddr *);
|
||||
|
||||
int sctp_swap_inpcb_for_listen(struct sctp_inpcb *inp);
|
||||
|
||||
void sctp_clean_up_stream(struct sctp_tcb *stcb, struct sctp_readhead *rh);
|
||||
|
||||
/*-
|
||||
* Null in last arg inpcb indicate run on ALL ep's. Specific inp in last arg
|
||||
* indicates run on ONLY assoc's of the specified endpoint.
|
||||
|
@ -389,7 +389,7 @@ struct sctp_nets {
|
||||
|
||||
struct sctp_data_chunkrec {
|
||||
uint32_t TSN_seq; /* the TSN of this transmit */
|
||||
uint16_t stream_seq; /* the stream sequence number of this transmit */
|
||||
uint32_t stream_seq; /* the stream sequence number of this transmit */
|
||||
uint16_t stream_number; /* the stream number of this guy */
|
||||
uint32_t payloadtype;
|
||||
uint32_t context; /* from send */
|
||||
@ -400,6 +400,7 @@ struct sctp_data_chunkrec {
|
||||
*/
|
||||
uint32_t fast_retran_tsn; /* sending_seq at the time of FR */
|
||||
struct timeval timetodrop; /* time we drop it from queue */
|
||||
uint32_t fsn_num; /* Fragment Sequence Number */
|
||||
uint8_t doing_fast_retransmit;
|
||||
uint8_t rcv_flags; /* flags pulled from data chunk on inbound for
|
||||
* outbound holds sending flags for PR-SCTP. */
|
||||
@ -458,7 +459,7 @@ struct sctp_tmit_chunk {
|
||||
*/
|
||||
struct sctp_queued_to_read { /* sinfo structure Pluse more */
|
||||
uint16_t sinfo_stream; /* off the wire */
|
||||
uint16_t sinfo_ssn; /* off the wire */
|
||||
uint32_t sinfo_ssn; /* off the wire */
|
||||
uint16_t sinfo_flags; /* SCTP_UNORDERED from wire use SCTP_EOF for
|
||||
* EOR */
|
||||
uint32_t sinfo_ppid; /* off the wire */
|
||||
@ -468,8 +469,11 @@ struct sctp_queued_to_read { /* sinfo structure Pluse more */
|
||||
uint32_t sinfo_cumtsn; /* Use this in reassembly as last TSN */
|
||||
sctp_assoc_t sinfo_assoc_id; /* our assoc id */
|
||||
/* Non sinfo stuff */
|
||||
uint32_t msg_id; /* Fragment Index */
|
||||
uint32_t length; /* length of data */
|
||||
uint32_t held_length; /* length held in sb */
|
||||
uint32_t top_fsn; /* Highest FSN in queue */
|
||||
uint32_t fsn_included; /* Highest FSN in *data portion */
|
||||
struct sctp_nets *whoFrom; /* where it came from */
|
||||
struct mbuf *data; /* front of the mbuf chain of data with
|
||||
* PKT_HDR */
|
||||
@ -478,14 +482,24 @@ struct sctp_queued_to_read { /* sinfo structure Pluse more */
|
||||
* take it from us */
|
||||
struct sctp_tcb *stcb; /* assoc, used for window update */
|
||||
TAILQ_ENTRY(sctp_queued_to_read) next;
|
||||
TAILQ_ENTRY(sctp_queued_to_read) next_instrm;
|
||||
struct sctpchunk_listhead reasm;
|
||||
uint16_t port_from;
|
||||
uint16_t spec_flags; /* Flags to hold the notification field */
|
||||
uint8_t do_not_ref_stcb;
|
||||
uint8_t end_added;
|
||||
uint8_t pdapi_aborted;
|
||||
uint8_t pdapi_started;
|
||||
uint8_t some_taken;
|
||||
uint8_t last_frag_seen;
|
||||
uint8_t first_frag_seen;
|
||||
uint8_t on_read_q;
|
||||
uint8_t on_strm_q;
|
||||
};
|
||||
|
||||
#define SCTP_ON_ORDERED 1
|
||||
#define SCTP_ON_UNORDERED 2
|
||||
|
||||
/* This data structure will be on the outbound
|
||||
* stream queues. Data will be pulled off from
|
||||
* the front of the mbuf data and chunk-ified
|
||||
@ -511,6 +525,8 @@ struct sctp_stream_queue_pending {
|
||||
struct sctp_nets *net;
|
||||
TAILQ_ENTRY(sctp_stream_queue_pending) next;
|
||||
TAILQ_ENTRY(sctp_stream_queue_pending) ss_next;
|
||||
uint32_t fsn;
|
||||
uint32_t msg_id;
|
||||
uint32_t length;
|
||||
uint32_t timetolive;
|
||||
uint32_t ppid;
|
||||
@ -534,9 +550,11 @@ struct sctp_stream_queue_pending {
|
||||
TAILQ_HEAD(sctpwheelunrel_listhead, sctp_stream_in);
|
||||
struct sctp_stream_in {
|
||||
struct sctp_readhead inqueue;
|
||||
struct sctp_readhead uno_inqueue;
|
||||
uint32_t last_sequence_delivered; /* used for re-order */
|
||||
uint16_t stream_no;
|
||||
uint16_t last_sequence_delivered; /* used for re-order */
|
||||
uint8_t delivery_started;
|
||||
uint8_t pd_api_started;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(sctpwheel_listhead, sctp_stream_out);
|
||||
@ -605,8 +623,8 @@ struct sctp_stream_out {
|
||||
uint32_t abandoned_unsent[1];
|
||||
uint32_t abandoned_sent[1];
|
||||
#endif
|
||||
uint32_t next_sequence_send; /* next one I expect to send out */
|
||||
uint16_t stream_no;
|
||||
uint16_t next_sequence_send; /* next one I expect to send out */
|
||||
uint8_t last_msg_incomplete;
|
||||
uint8_t state;
|
||||
};
|
||||
@ -635,12 +653,13 @@ struct sctp_scoping {
|
||||
struct sctp_tsn_log {
|
||||
void *stcb;
|
||||
uint32_t tsn;
|
||||
uint32_t seq;
|
||||
uint16_t strm;
|
||||
uint16_t seq;
|
||||
uint16_t sz;
|
||||
uint16_t flgs;
|
||||
uint16_t in_pos;
|
||||
uint16_t in_out;
|
||||
uint16_t resv;
|
||||
};
|
||||
|
||||
#define SCTP_FS_SPEC_LOG_SIZE 200
|
||||
@ -811,9 +830,6 @@ struct sctp_association {
|
||||
struct sctpchunk_listhead sent_queue;
|
||||
struct sctpchunk_listhead send_queue;
|
||||
|
||||
/* re-assembly queue for fragmented chunks on the inbound path */
|
||||
struct sctpchunk_listhead reasmqueue;
|
||||
|
||||
/* Scheduling queues */
|
||||
union scheduling_data ss_data;
|
||||
|
||||
@ -881,7 +897,7 @@ struct sctp_association {
|
||||
uint32_t stream_scheduling_module;
|
||||
|
||||
uint32_t vrf_id;
|
||||
|
||||
uint32_t assoc_msg_id;
|
||||
uint32_t cookie_preserve_req;
|
||||
/* ASCONF next seq I am sending out, inits at init-tsn */
|
||||
uint32_t asconf_seq_out;
|
||||
@ -1177,12 +1193,12 @@ struct sctp_association {
|
||||
uint8_t reconfig_supported;
|
||||
uint8_t nrsack_supported;
|
||||
uint8_t pktdrop_supported;
|
||||
uint8_t idata_supported;
|
||||
|
||||
/* Did the peer make the stream config (add out) request */
|
||||
uint8_t peer_req_out;
|
||||
|
||||
uint8_t local_strreset_support;
|
||||
|
||||
uint8_t peer_supports_nat;
|
||||
|
||||
struct sctp_scoping scope;
|
||||
|
@ -432,7 +432,7 @@ struct sctp_sysctl {
|
||||
#define SCTPCTL_STRICT_DATA_ORDER_DESC "Enforce strict data ordering, abort if control inside data"
|
||||
#define SCTPCTL_STRICT_DATA_ORDER_MIN 0
|
||||
#define SCTPCTL_STRICT_DATA_ORDER_MAX 1
|
||||
#define SCTPCTL_STRICT_DATA_ORDER_DEFAULT 0
|
||||
#define SCTPCTL_STRICT_DATA_ORDER_DEFAULT 1
|
||||
|
||||
/* min_residual: min residual in a data fragment leftover */
|
||||
#define SCTPCTL_MIN_RESIDUAL_DESC "Minimum residual data chunk in second part of split"
|
||||
|
@ -318,12 +318,13 @@ struct sctp_assoc_change {
|
||||
#define SCTP_CANT_STR_ASSOC 0x0005
|
||||
|
||||
/* sac_info values */
|
||||
#define SCTP_ASSOC_SUPPORTS_PR 0x01
|
||||
#define SCTP_ASSOC_SUPPORTS_AUTH 0x02
|
||||
#define SCTP_ASSOC_SUPPORTS_ASCONF 0x03
|
||||
#define SCTP_ASSOC_SUPPORTS_MULTIBUF 0x04
|
||||
#define SCTP_ASSOC_SUPPORTS_RE_CONFIG 0x05
|
||||
#define SCTP_ASSOC_SUPPORTS_MAX 0x05
|
||||
#define SCTP_ASSOC_SUPPORTS_PR 0x01
|
||||
#define SCTP_ASSOC_SUPPORTS_AUTH 0x02
|
||||
#define SCTP_ASSOC_SUPPORTS_ASCONF 0x03
|
||||
#define SCTP_ASSOC_SUPPORTS_MULTIBUF 0x04
|
||||
#define SCTP_ASSOC_SUPPORTS_RE_CONFIG 0x05
|
||||
#define SCTP_ASSOC_SUPPORTS_INTERLEAVING 0x06
|
||||
#define SCTP_ASSOC_SUPPORTS_MAX 0x06
|
||||
/*
|
||||
* Address event
|
||||
*/
|
||||
|
@ -1730,6 +1730,37 @@ flags_out:
|
||||
*optsize = sizeof(uint32_t);
|
||||
break;
|
||||
}
|
||||
case SCTP_INTERLEAVING_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
|
||||
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
av->assoc_value = stcb->asoc.idata_supported;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(av->assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_RLOCK(inp);
|
||||
if (inp->idata_supported) {
|
||||
av->assoc_value = 1;
|
||||
} else {
|
||||
av->assoc_value = 0;
|
||||
}
|
||||
SCTP_INP_RUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
if (error == 0) {
|
||||
*optsize = sizeof(struct sctp_assoc_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_CMT_ON_OFF:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
@ -3904,6 +3935,47 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_INTERLEAVING_SUPPORTED:
|
||||
{
|
||||
struct sctp_assoc_value *av;
|
||||
|
||||
SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
|
||||
SCTP_FIND_STCB(inp, stcb, av->assoc_id);
|
||||
|
||||
if (stcb) {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
} else {
|
||||
if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
|
||||
(inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
|
||||
(av->assoc_id == SCTP_FUTURE_ASSOC)) {
|
||||
SCTP_INP_WLOCK(inp);
|
||||
if (av->assoc_value == 0) {
|
||||
inp->idata_supported = 0;
|
||||
} else {
|
||||
if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
|
||||
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) {
|
||||
inp->idata_supported = 1;
|
||||
} else {
|
||||
/*
|
||||
* Must have Frag
|
||||
* interleave and
|
||||
* stream interleave
|
||||
* on
|
||||
*/
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
SCTP_INP_WUNLOCK(inp);
|
||||
} else {
|
||||
SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
|
||||
error = EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SCTP_CMT_ON_OFF:
|
||||
if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
|
||||
struct sctp_assoc_value *av;
|
||||
|
@ -97,11 +97,19 @@ extern struct pr_usrreqs sctp_usrreqs;
|
||||
* an mbuf cache as well so it is not really worth doing, at least
|
||||
* right now :-D
|
||||
*/
|
||||
|
||||
#ifdef INVARIANTS
|
||||
#define sctp_free_a_readq(_stcb, _readq) { \
|
||||
if ((_readq)->on_strm_q) \
|
||||
panic("On strm q stcb:%p readq:%p", (_stcb), (_readq)); \
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), (_readq)); \
|
||||
SCTP_DECR_READQ_COUNT(); \
|
||||
}
|
||||
#else
|
||||
#define sctp_free_a_readq(_stcb, _readq) { \
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), (_readq)); \
|
||||
SCTP_DECR_READQ_COUNT(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define sctp_alloc_a_readq(_stcb, _readq) { \
|
||||
(_readq) = SCTP_ZONE_GET(SCTP_BASE_INFO(ipi_zone_readq), struct sctp_queued_to_read); \
|
||||
@ -196,7 +204,7 @@ extern struct pr_usrreqs sctp_usrreqs;
|
||||
}
|
||||
|
||||
#define sctp_sbfree(ctl, stcb, sb, m) { \
|
||||
SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_cc, SCTP_BUF_LEN((m))); \
|
||||
SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_cc, SCTP_BUF_LEN((m))); \
|
||||
SCTP_SAVE_ATOMIC_DECREMENT(&(sb)->sb_mbcnt, MSIZE); \
|
||||
if (((ctl)->do_not_ref_stcb == 0) && stcb) {\
|
||||
SCTP_SAVE_ATOMIC_DECREMENT(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \
|
||||
@ -211,7 +219,7 @@ extern struct pr_usrreqs sctp_usrreqs;
|
||||
atomic_add_int(&(sb)->sb_cc,SCTP_BUF_LEN((m))); \
|
||||
atomic_add_int(&(sb)->sb_mbcnt, MSIZE); \
|
||||
if (stcb) { \
|
||||
atomic_add_int(&(stcb)->asoc.sb_cc,SCTP_BUF_LEN((m))); \
|
||||
atomic_add_int(&(stcb)->asoc.sb_cc, SCTP_BUF_LEN((m))); \
|
||||
atomic_add_int(&(stcb)->asoc.my_rwnd_control_len, MSIZE); \
|
||||
} \
|
||||
if (SCTP_BUF_TYPE(m) != MT_DATA && SCTP_BUF_TYPE(m) != MT_HEADER && \
|
||||
|
@ -970,11 +970,13 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
asoc->sctp_cmt_on_off = inp->sctp_cmt_on_off;
|
||||
asoc->ecn_supported = inp->ecn_supported;
|
||||
asoc->prsctp_supported = inp->prsctp_supported;
|
||||
asoc->idata_supported = inp->idata_supported;
|
||||
asoc->auth_supported = inp->auth_supported;
|
||||
asoc->asconf_supported = inp->asconf_supported;
|
||||
asoc->reconfig_supported = inp->reconfig_supported;
|
||||
asoc->nrsack_supported = inp->nrsack_supported;
|
||||
asoc->pktdrop_supported = inp->pktdrop_supported;
|
||||
asoc->idata_supported = inp->idata_supported;
|
||||
asoc->sctp_cmt_pf = (uint8_t) 0;
|
||||
asoc->sctp_frag_point = inp->sctp_frag_point;
|
||||
asoc->sctp_features = inp->sctp_features;
|
||||
@ -1163,7 +1165,6 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
TAILQ_INIT(&asoc->asconf_send_queue);
|
||||
TAILQ_INIT(&asoc->send_queue);
|
||||
TAILQ_INIT(&asoc->sent_queue);
|
||||
TAILQ_INIT(&asoc->reasmqueue);
|
||||
TAILQ_INIT(&asoc->resetHead);
|
||||
asoc->max_inbound_streams = inp->sctp_ep.max_open_streams_intome;
|
||||
TAILQ_INIT(&asoc->asconf_queue);
|
||||
@ -2736,6 +2737,9 @@ sctp_notify_assoc_change(uint16_t state, struct sctp_tcb *stcb,
|
||||
if (stcb->asoc.asconf_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_ASCONF;
|
||||
}
|
||||
if (stcb->asoc.idata_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_INTERLEAVING;
|
||||
}
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_MULTIBUF;
|
||||
if (stcb->asoc.reconfig_supported == 1) {
|
||||
sac->sac_info[i++] = SCTP_ASSOC_SUPPORTS_RE_CONFIG;
|
||||
@ -4449,6 +4453,43 @@ sctp_pull_off_control_to_new_inp(struct sctp_inpcb *old_inp,
|
||||
SCTP_INP_READ_UNLOCK(new_inp);
|
||||
}
|
||||
|
||||
void
|
||||
sctp_wakeup_the_read_socket(struct sctp_inpcb *inp)
|
||||
{
|
||||
if (inp && inp->sctp_socket) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
|
||||
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
|
||||
} else {
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
struct socket *so;
|
||||
|
||||
so = SCTP_INP_SO(inp);
|
||||
if (!so_locked) {
|
||||
if (stcb) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
SCTP_SOCKET_LOCK(so, 1);
|
||||
if (stcb) {
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
}
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sctp_sorwakeup(inp, inp->sctp_socket);
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
if (!so_locked) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
struct sctp_tcb *stcb,
|
||||
@ -4484,7 +4525,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
sctp_m_freem(control->data);
|
||||
control->data = NULL;
|
||||
}
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
|
||||
sctp_free_a_readq(stcb, control);
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return;
|
||||
@ -4530,7 +4571,7 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
} else {
|
||||
/* Everything got collapsed out?? */
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
SCTP_ZONE_FREE(SCTP_BASE_INFO(ipi_zone_readq), control);
|
||||
sctp_free_a_readq(stcb, control);
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
return;
|
||||
@ -4539,39 +4580,11 @@ sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
control->end_added = 1;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(&inp->read_queue, control, next);
|
||||
control->on_read_q = 1;
|
||||
if (inp_read_lock_held == 0)
|
||||
SCTP_INP_READ_UNLOCK(inp);
|
||||
if (inp && inp->sctp_socket) {
|
||||
if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ZERO_COPY_ACTIVE)) {
|
||||
SCTP_ZERO_COPY_EVENT(inp, inp->sctp_socket);
|
||||
} else {
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
struct socket *so;
|
||||
|
||||
so = SCTP_INP_SO(inp);
|
||||
if (!so_locked) {
|
||||
if (stcb) {
|
||||
atomic_add_int(&stcb->asoc.refcnt, 1);
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
}
|
||||
SCTP_SOCKET_LOCK(so, 1);
|
||||
if (stcb) {
|
||||
SCTP_TCB_LOCK(stcb);
|
||||
atomic_subtract_int(&stcb->asoc.refcnt, 1);
|
||||
}
|
||||
if (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sctp_sorwakeup(inp, inp->sctp_socket);
|
||||
#if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
|
||||
if (!so_locked) {
|
||||
SCTP_SOCKET_UNLOCK(so, 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
sctp_wakeup_the_read_socket(inp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5552,6 +5565,10 @@ restart_nosblocks:
|
||||
sctp_m_free(control->aux_data);
|
||||
control->aux_data = NULL;
|
||||
}
|
||||
if (control->on_strm_q) {
|
||||
panic("About to free ctl:%p so:%p and its in %d",
|
||||
control, so, control->on_strm_q);
|
||||
}
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
sctp_free_a_readq(stcb, control);
|
||||
if (hold_rlock) {
|
||||
@ -5822,15 +5839,8 @@ get_more_data:
|
||||
/* error we are out of here */
|
||||
goto release;
|
||||
}
|
||||
if ((SCTP_BUF_NEXT(m) == NULL) &&
|
||||
(cp_len >= SCTP_BUF_LEN(m)) &&
|
||||
((control->end_added == 0) ||
|
||||
(control->end_added &&
|
||||
(TAILQ_NEXT(control, next) == NULL)))
|
||||
) {
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
hold_rlock = 1;
|
||||
}
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
hold_rlock = 1;
|
||||
if (cp_len == SCTP_BUF_LEN(m)) {
|
||||
if ((SCTP_BUF_NEXT(m) == NULL) &&
|
||||
(control->end_added)) {
|
||||
@ -5948,19 +5958,9 @@ get_more_data:
|
||||
#endif
|
||||
}
|
||||
done_with_control:
|
||||
if (TAILQ_NEXT(control, next) == NULL) {
|
||||
/*
|
||||
* If we don't have a next we need a
|
||||
* lock, if there is a next
|
||||
* interrupt is filling ahead of us
|
||||
* and we don't need a lock to
|
||||
* remove this guy (which is the
|
||||
* head of the queue).
|
||||
*/
|
||||
if (hold_rlock == 0) {
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
hold_rlock = 1;
|
||||
}
|
||||
if (hold_rlock == 0) {
|
||||
SCTP_INP_READ_LOCK(inp);
|
||||
hold_rlock = 1;
|
||||
}
|
||||
TAILQ_REMOVE(&inp->read_queue, control, next);
|
||||
/* Add back any hiddend data */
|
||||
@ -5976,6 +5976,10 @@ get_more_data:
|
||||
no_rcv_needed = control->do_not_ref_stcb;
|
||||
sctp_free_remote_addr(control->whoFrom);
|
||||
control->data = NULL;
|
||||
if (control->on_strm_q) {
|
||||
panic("About to free ctl:%p so:%p and its in %d",
|
||||
control, so, control->on_strm_q);
|
||||
}
|
||||
sctp_free_a_readq(stcb, control);
|
||||
control = NULL;
|
||||
if ((freed_so_far >= rwnd_req) &&
|
||||
@ -6096,7 +6100,7 @@ wait_some_more:
|
||||
* corrupt?
|
||||
*/
|
||||
#ifdef INVARIANTS
|
||||
panic("Impossible data==NULL length !=0");
|
||||
panic("Impossible data==NULL length !=0 control:%p stcb:%p length:%d", control, stcb, control->length);
|
||||
#endif
|
||||
out_flags |= MSG_EOR;
|
||||
out_flags |= MSG_TRUNC;
|
||||
|
@ -107,6 +107,9 @@ int
|
||||
void
|
||||
sctp_mtu_size_reset(struct sctp_inpcb *, struct sctp_association *, uint32_t);
|
||||
|
||||
void
|
||||
sctp_wakeup_the_read_socket(struct sctp_inpcb *inp);
|
||||
|
||||
void
|
||||
sctp_add_to_readq(struct sctp_inpcb *inp,
|
||||
struct sctp_tcb *stcb,
|
||||
|
Loading…
x
Reference in New Issue
Block a user