Fix the handling of Explicit EOR mode.
While there, appropriately handle the overhead depending on the usage of DATA or I-DATA chunks. Take the overhead only into account, when required. Joint work with rrs@ MFC after: 1 week
This commit is contained in:
parent
34cfc1e7ed
commit
b36838d4aa
@ -6250,11 +6250,7 @@ sctp_get_frag_point(struct sctp_tcb *stcb,
|
|||||||
} else {
|
} else {
|
||||||
ovh = SCTP_MIN_V4_OVERHEAD;
|
ovh = SCTP_MIN_V4_OVERHEAD;
|
||||||
}
|
}
|
||||||
if (stcb->asoc.idata_supported) {
|
ovh += SCTP_DATA_CHUNK_OVERHEAD(stcb);
|
||||||
ovh += sizeof(struct sctp_idata_chunk);
|
|
||||||
} else {
|
|
||||||
ovh += sizeof(struct sctp_data_chunk);
|
|
||||||
}
|
|
||||||
if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu)
|
if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu)
|
||||||
siz = asoc->smallest_mtu - ovh;
|
siz = asoc->smallest_mtu - ovh;
|
||||||
else
|
else
|
||||||
@ -6759,7 +6755,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct sctp_tcb *stcb, void *ptr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
|
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
|
||||||
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
|
(stcb->asoc.stream_queue_cnt * SCTP_DATA_CHUNK_OVERHEAD(stcb)));
|
||||||
|
|
||||||
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
||||||
(stcb->asoc.total_flight > 0) &&
|
(stcb->asoc.total_flight > 0) &&
|
||||||
@ -7459,11 +7455,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
|||||||
} else {
|
} else {
|
||||||
atomic_subtract_int(&sp->length, to_move);
|
atomic_subtract_int(&sp->length, to_move);
|
||||||
}
|
}
|
||||||
if (stcb->asoc.idata_supported == 0) {
|
leading = SCTP_DATA_CHUNK_OVERHEAD(stcb);
|
||||||
leading = sizeof(struct sctp_data_chunk);
|
|
||||||
} else {
|
|
||||||
leading = sizeof(struct sctp_idata_chunk);
|
|
||||||
}
|
|
||||||
if (M_LEADINGSPACE(chk->data) < leading) {
|
if (M_LEADINGSPACE(chk->data) < leading) {
|
||||||
/* Not enough room for a chunk header, get some */
|
/* Not enough room for a chunk header, get some */
|
||||||
struct mbuf *m;
|
struct mbuf *m;
|
||||||
@ -7505,11 +7497,7 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
|||||||
M_ALIGN(chk->data, 4);
|
M_ALIGN(chk->data, 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stcb->asoc.idata_supported == 0) {
|
SCTP_BUF_PREPEND(chk->data, SCTP_DATA_CHUNK_OVERHEAD(stcb), M_NOWAIT);
|
||||||
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) {
|
if (chk->data == NULL) {
|
||||||
/* HELP, TSNH since we assured it would not above? */
|
/* HELP, TSNH since we assured it would not above? */
|
||||||
#ifdef INVARIANTS
|
#ifdef INVARIANTS
|
||||||
@ -7522,13 +7510,8 @@ sctp_move_to_outqueue(struct sctp_tcb *stcb,
|
|||||||
to_move = 0;
|
to_move = 0;
|
||||||
goto out_of;
|
goto out_of;
|
||||||
}
|
}
|
||||||
if (stcb->asoc.idata_supported == 0) {
|
sctp_snd_sb_alloc(stcb, SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
sctp_snd_sb_alloc(stcb, sizeof(struct sctp_data_chunk));
|
chk->book_size = chk->send_size = (uint16_t)(to_move + SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
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->book_size_scale = 0;
|
||||||
chk->sent = SCTP_DATAGRAM_UNSENT;
|
chk->sent = SCTP_DATAGRAM_UNSENT;
|
||||||
|
|
||||||
@ -7728,11 +7711,7 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Need an allowance for the data chunk header too */
|
/* Need an allowance for the data chunk header too */
|
||||||
if (stcb->asoc.idata_supported == 0) {
|
space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb);
|
||||||
space_left -= sizeof(struct sctp_data_chunk);
|
|
||||||
} else {
|
|
||||||
space_left -= sizeof(struct sctp_idata_chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* must make even word boundary */
|
/* must make even word boundary */
|
||||||
space_left &= 0xfffffffc;
|
space_left &= 0xfffffffc;
|
||||||
@ -7749,18 +7728,10 @@ sctp_fill_outqueue(struct sctp_tcb *stcb,
|
|||||||
strq = stcb->asoc.ss_functions.sctp_ss_select_stream(stcb, net, asoc);
|
strq = stcb->asoc.ss_functions.sctp_ss_select_stream(stcb, net, asoc);
|
||||||
total_moved += moved;
|
total_moved += moved;
|
||||||
space_left -= moved;
|
space_left -= moved;
|
||||||
if (stcb->asoc.idata_supported == 0) {
|
if (space_left >= SCTP_DATA_CHUNK_OVERHEAD(stcb)) {
|
||||||
if (space_left >= sizeof(struct sctp_data_chunk)) {
|
space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb);
|
||||||
space_left -= sizeof(struct sctp_data_chunk);
|
|
||||||
} else {
|
|
||||||
space_left = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (space_left >= sizeof(struct sctp_idata_chunk)) {
|
space_left = 0;
|
||||||
space_left -= sizeof(struct sctp_idata_chunk);
|
|
||||||
} else {
|
|
||||||
space_left = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
space_left &= 0xfffffffc;
|
space_left &= 0xfffffffc;
|
||||||
}
|
}
|
||||||
@ -10209,8 +10180,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
|
|||||||
* and we have data in flight we stop, except if we
|
* and we have data in flight we stop, except if we
|
||||||
* are handling a fragmented user message.
|
* are handling a fragmented user message.
|
||||||
*/
|
*/
|
||||||
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
|
un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
|
||||||
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
|
|
||||||
if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) &&
|
if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) &&
|
||||||
(stcb->asoc.total_flight > 0)) {
|
(stcb->asoc.total_flight > 0)) {
|
||||||
/* && sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {*/
|
/* && sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR))) {*/
|
||||||
@ -12448,7 +12418,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
|
|||||||
sp->sender_all_done = 0;
|
sp->sender_all_done = 0;
|
||||||
sp->some_taken = 0;
|
sp->some_taken = 0;
|
||||||
sp->put_last_out = 0;
|
sp->put_last_out = 0;
|
||||||
resv_in_first = sizeof(struct sctp_data_chunk);
|
resv_in_first = SCTP_DATA_CHUNK_OVERHEAD(stcb);
|
||||||
sp->data = sp->tail_mbuf = NULL;
|
sp->data = sp->tail_mbuf = NULL;
|
||||||
if (sp->length == 0) {
|
if (sp->length == 0) {
|
||||||
*error = 0;
|
*error = 0;
|
||||||
@ -12865,12 +12835,19 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
}
|
}
|
||||||
/* would we block? */
|
/* would we block? */
|
||||||
if (non_blocking) {
|
if (non_blocking) {
|
||||||
|
uint32_t amount;
|
||||||
|
|
||||||
if (hold_tcblock == 0) {
|
if (hold_tcblock == 0) {
|
||||||
SCTP_TCB_LOCK(stcb);
|
SCTP_TCB_LOCK(stcb);
|
||||||
hold_tcblock = 1;
|
hold_tcblock = 1;
|
||||||
}
|
}
|
||||||
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
if ((SCTP_SB_LIMIT_SND(so) < (sndlen + inqueue_bytes + stcb->asoc.sb_send_resv)) ||
|
if (user_marks_eor == 0) {
|
||||||
|
amount = sndlen;
|
||||||
|
} else {
|
||||||
|
amount = 1;
|
||||||
|
}
|
||||||
|
if ((SCTP_SB_LIMIT_SND(so) < (amount + inqueue_bytes + stcb->asoc.sb_send_resv)) ||
|
||||||
(stcb->asoc.chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
(stcb->asoc.chunks_on_out_queue >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
||||||
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK);
|
SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK);
|
||||||
if (sndlen > SCTP_SB_LIMIT_SND(so))
|
if (sndlen > SCTP_SB_LIMIT_SND(so))
|
||||||
@ -13036,7 +13013,7 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
}
|
}
|
||||||
/* Calculate the maximum we can send */
|
/* Calculate the maximum we can send */
|
||||||
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
|
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
|
||||||
if (non_blocking) {
|
if (non_blocking) {
|
||||||
/* we already checked for non-blocking above. */
|
/* we already checked for non-blocking above. */
|
||||||
@ -13093,7 +13070,7 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
((stcb->asoc.chunks_on_out_queue + stcb->asoc.stream_queue_cnt) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
||||||
/* No room right now ! */
|
/* No room right now ! */
|
||||||
SOCKBUF_LOCK(&so->so_snd);
|
SOCKBUF_LOCK(&so->so_snd);
|
||||||
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) ||
|
while ((SCTP_SB_LIMIT_SND(so) < (inqueue_bytes + local_add_more)) ||
|
||||||
((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
((stcb->asoc.stream_queue_cnt + stcb->asoc.chunks_on_out_queue) >= SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue))) {
|
||||||
SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%u <(inq:%d + %d) || (%d+%d > %d)\n",
|
SCTPDBG(SCTP_DEBUG_OUTPUT1, "pre_block limit:%u <(inq:%d + %d) || (%d+%d > %d)\n",
|
||||||
@ -13129,7 +13106,7 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
SOCKBUF_UNLOCK(&so->so_snd);
|
SOCKBUF_UNLOCK(&so->so_snd);
|
||||||
goto out_unlocked;
|
goto out_unlocked;
|
||||||
}
|
}
|
||||||
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
}
|
}
|
||||||
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
|
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes) {
|
||||||
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
|
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
|
||||||
@ -13222,8 +13199,9 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
/* How much room do we have? */
|
/* How much room do we have? */
|
||||||
struct mbuf *new_tail, *mm;
|
struct mbuf *new_tail, *mm;
|
||||||
|
|
||||||
if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
|
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes)
|
||||||
|
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
|
||||||
else
|
else
|
||||||
max_len = 0;
|
max_len = 0;
|
||||||
|
|
||||||
@ -13299,8 +13277,8 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
hold_tcblock = 1;
|
hold_tcblock = 1;
|
||||||
}
|
}
|
||||||
sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
|
sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
|
||||||
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk));
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
|
if (SCTP_SB_LIMIT_SND(so) > inqueue_bytes)
|
||||||
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
|
max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes;
|
||||||
else
|
else
|
||||||
max_len = 0;
|
max_len = 0;
|
||||||
@ -13341,8 +13319,7 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
}
|
}
|
||||||
asoc->ifp_had_enobuf = 0;
|
asoc->ifp_had_enobuf = 0;
|
||||||
}
|
}
|
||||||
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
|
un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
|
||||||
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
|
|
||||||
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
||||||
(stcb->asoc.total_flight > 0) &&
|
(stcb->asoc.total_flight > 0) &&
|
||||||
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
|
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
|
||||||
@ -13416,7 +13393,8 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
* size we KNOW we will get to sleep safely with the
|
* size we KNOW we will get to sleep safely with the
|
||||||
* wakeup flag in place.
|
* wakeup flag in place.
|
||||||
*/
|
*/
|
||||||
if (SCTP_SB_LIMIT_SND(so) <= (stcb->asoc.total_output_queue_size +
|
inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb));
|
||||||
|
if (SCTP_SB_LIMIT_SND(so) <= (inqueue_bytes +
|
||||||
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
|
min(SCTP_BASE_SYSCTL(sctp_add_more_threshold), SCTP_SB_LIMIT_SND(so)))) {
|
||||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
|
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) {
|
||||||
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
|
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
|
||||||
@ -13613,8 +13591,7 @@ sctp_lower_sosend(struct socket *so,
|
|||||||
}
|
}
|
||||||
asoc->ifp_had_enobuf = 0;
|
asoc->ifp_had_enobuf = 0;
|
||||||
}
|
}
|
||||||
un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) +
|
un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight;
|
||||||
(stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk)));
|
|
||||||
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) &&
|
||||||
(stcb->asoc.total_flight > 0) &&
|
(stcb->asoc.total_flight > 0) &&
|
||||||
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
|
(stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) &&
|
||||||
|
@ -135,6 +135,11 @@ void sctp_fix_ecn_echo(struct sctp_association *);
|
|||||||
|
|
||||||
void sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net);
|
void sctp_move_chunks_from_net(struct sctp_tcb *stcb, struct sctp_nets *net);
|
||||||
|
|
||||||
|
|
||||||
|
#define SCTP_DATA_CHUNK_OVERHEAD(stcb) ((stcb)->asoc.idata_supported ? \
|
||||||
|
sizeof(struct sctp_idata_chunk) : \
|
||||||
|
sizeof(struct sctp_data_chunk))
|
||||||
|
|
||||||
int
|
int
|
||||||
sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
|
sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *,
|
||||||
struct mbuf *, struct thread *, int);
|
struct mbuf *, struct thread *, int);
|
||||||
|
Loading…
Reference in New Issue
Block a user