From owner-svn-src-head@freebsd.org Sat Jul 15 19:54:04 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id BDFB6B7AE35; Sat, 15 Jul 2017 19:54:04 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 7FEFE82E70; Sat, 15 Jul 2017 19:54:04 +0000 (UTC) (envelope-from tuexen@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v6FJs3ct030822; Sat, 15 Jul 2017 19:54:03 GMT (envelope-from tuexen@FreeBSD.org) Received: (from tuexen@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v6FJs36p030820; Sat, 15 Jul 2017 19:54:03 GMT (envelope-from tuexen@FreeBSD.org) Message-Id: <201707151954.v6FJs36p030820@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: tuexen set sender to tuexen@FreeBSD.org using -f From: Michael Tuexen Date: Sat, 15 Jul 2017 19:54:03 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r321034 - head/sys/netinet X-SVN-Group: head X-SVN-Commit-Author: tuexen X-SVN-Commit-Paths: head/sys/netinet X-SVN-Commit-Revision: 321034 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 15 Jul 2017 19:54:04 -0000 Author: tuexen Date: Sat Jul 15 19:54:03 2017 New Revision: 321034 URL: https://svnweb.freebsd.org/changeset/base/321034 Log: 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 Modified: head/sys/netinet/sctp_output.c head/sys/netinet/sctp_output.h Modified: head/sys/netinet/sctp_output.c ============================================================================== --- head/sys/netinet/sctp_output.c Sat Jul 15 19:52:59 2017 (r321033) +++ head/sys/netinet/sctp_output.c Sat Jul 15 19:54:03 2017 (r321034) @@ -6250,11 +6250,7 @@ sctp_get_frag_point(struct sctp_tcb *stcb, } else { ovh = SCTP_MIN_V4_OVERHEAD; } - if (stcb->asoc.idata_supported) { - ovh += sizeof(struct sctp_idata_chunk); - } else { - ovh += sizeof(struct sctp_data_chunk); - } + ovh += SCTP_DATA_CHUNK_OVERHEAD(stcb); if (stcb->asoc.sctp_frag_point > asoc->smallest_mtu) siz = asoc->smallest_mtu - ovh; else @@ -6759,7 +6755,7 @@ sctp_sendall_iterator(struct sctp_inpcb *inp, struct s } } 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)) && (stcb->asoc.total_flight > 0) && @@ -7459,11 +7455,7 @@ dont_do_it: } else { atomic_subtract_int(&sp->length, to_move); } - if (stcb->asoc.idata_supported == 0) { - leading = sizeof(struct sctp_data_chunk); - } else { - leading = sizeof(struct sctp_idata_chunk); - } + leading = SCTP_DATA_CHUNK_OVERHEAD(stcb); if (M_LEADINGSPACE(chk->data) < leading) { /* Not enough room for a chunk header, get some */ struct mbuf *m; @@ -7505,11 +7497,7 @@ dont_do_it: M_ALIGN(chk->data, 4); } } - 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); - } + SCTP_BUF_PREPEND(chk->data, SCTP_DATA_CHUNK_OVERHEAD(stcb), M_NOWAIT); if (chk->data == NULL) { /* HELP, TSNH since we assured it would not above? */ #ifdef INVARIANTS @@ -7522,13 +7510,8 @@ dont_do_it: to_move = 0; goto out_of; } - 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)); - } + sctp_snd_sb_alloc(stcb, SCTP_DATA_CHUNK_OVERHEAD(stcb)); + chk->book_size = chk->send_size = (uint16_t)(to_move + SCTP_DATA_CHUNK_OVERHEAD(stcb)); chk->book_size_scale = 0; chk->sent = SCTP_DATAGRAM_UNSENT; @@ -7728,11 +7711,7 @@ sctp_fill_outqueue(struct sctp_tcb *stcb, break; } /* Need an allowance for the data chunk header too */ - if (stcb->asoc.idata_supported == 0) { - space_left -= sizeof(struct sctp_data_chunk); - } else { - space_left -= sizeof(struct sctp_idata_chunk); - } + space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb); /* must make even word boundary */ 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); total_moved += moved; space_left -= moved; - if (stcb->asoc.idata_supported == 0) { - if (space_left >= sizeof(struct sctp_data_chunk)) { - space_left -= sizeof(struct sctp_data_chunk); - } else { - space_left = 0; - } + if (space_left >= SCTP_DATA_CHUNK_OVERHEAD(stcb)) { + space_left -= SCTP_DATA_CHUNK_OVERHEAD(stcb); } else { - if (space_left >= sizeof(struct sctp_idata_chunk)) { - space_left -= sizeof(struct sctp_idata_chunk); - } else { - space_left = 0; - } + space_left = 0; } space_left &= 0xfffffffc; } @@ -10209,8 +10180,7 @@ do_it_again: * and we have data in flight we stop, except if we * are handling a fragmented user message. */ - un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) + - (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk))); + un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight; if ((un_sent < (int)(stcb->asoc.smallest_mtu - SCTP_MIN_OVERHEAD)) && (stcb->asoc.total_flight > 0)) { /* && 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->some_taken = 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; if (sp->length == 0) { *error = 0; @@ -12865,12 +12835,19 @@ sctp_lower_sosend(struct socket *so, } /* would we block? */ if (non_blocking) { + uint32_t amount; + if (hold_tcblock == 0) { SCTP_TCB_LOCK(stcb); hold_tcblock = 1; } - inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * sizeof(struct sctp_data_chunk)); - if ((SCTP_SB_LIMIT_SND(so) < (sndlen + inqueue_bytes + stcb->asoc.sb_send_resv)) || + inqueue_bytes = stcb->asoc.total_output_queue_size - (stcb->asoc.chunks_on_out_queue * SCTP_DATA_CHUNK_OVERHEAD(stcb)); + 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))) { SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, EWOULDBLOCK); if (sndlen > SCTP_SB_LIMIT_SND(so)) @@ -13036,7 +13013,7 @@ sctp_lower_sosend(struct socket *so, goto out_unlocked; } /* 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 (non_blocking) { /* 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))) { /* No room right now ! */ 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)) || ((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", @@ -13129,7 +13106,7 @@ sctp_lower_sosend(struct socket *so, SOCKBUF_UNLOCK(&so->so_snd); 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) { max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; @@ -13222,8 +13199,9 @@ skip_preblock: /* How much room do we have? */ struct mbuf *new_tail, *mm; - if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size) - max_len = 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) + max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; else max_len = 0; @@ -13299,8 +13277,8 @@ skip_preblock: hold_tcblock = 1; } 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)); - 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) max_len = SCTP_SB_LIMIT_SND(so) - inqueue_bytes; else max_len = 0; @@ -13341,8 +13319,7 @@ skip_preblock: } asoc->ifp_had_enobuf = 0; } - un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) + - (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk))); + un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight; if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && (stcb->asoc.total_flight > 0) && (stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && @@ -13416,7 +13393,8 @@ skip_preblock: * size we KNOW we will get to sleep safely with the * 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)))) { if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_BLK_LOGGING_ENABLE) { sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, @@ -13613,8 +13591,7 @@ skip_out_eof: } asoc->ifp_had_enobuf = 0; } - un_sent = ((stcb->asoc.total_output_queue_size - stcb->asoc.total_flight) + - (stcb->asoc.stream_queue_cnt * sizeof(struct sctp_data_chunk))); + un_sent = stcb->asoc.total_output_queue_size - stcb->asoc.total_flight; if ((sctp_is_feature_off(inp, SCTP_PCB_FLAGS_NODELAY)) && (stcb->asoc.total_flight > 0) && (stcb->asoc.stream_queue_cnt < SCTP_MAX_DATA_BUNDLING) && Modified: head/sys/netinet/sctp_output.h ============================================================================== --- head/sys/netinet/sctp_output.h Sat Jul 15 19:52:59 2017 (r321033) +++ head/sys/netinet/sctp_output.h Sat Jul 15 19:54:03 2017 (r321034) @@ -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); + +#define SCTP_DATA_CHUNK_OVERHEAD(stcb) ((stcb)->asoc.idata_supported ? \ + sizeof(struct sctp_idata_chunk) : \ + sizeof(struct sctp_data_chunk)) + int sctp_output(struct sctp_inpcb *, struct mbuf *, struct sockaddr *, struct mbuf *, struct thread *, int);