- window update sacks sent incorrectly after

shutdown which caused extra abort from peer.
- RTT time calculation was not being done in
  express sack handling since it refered to an unused
  variable (rto_pending). Removed variable.
- socket buffer high water access macro-ized.
This commit is contained in:
Randall Stewart 2007-03-20 10:23:11 +00:00
parent d2e5427a0d
commit 62c1ff9c48
9 changed files with 33 additions and 36 deletions

View File

@ -74,7 +74,7 @@ sctp_set_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->size_on_reasm_queue == 0 && asoc->size_on_reasm_queue == 0 &&
asoc->size_on_all_streams == 0) { asoc->size_on_all_streams == 0) {
/* Full rwnd granted */ /* Full rwnd granted */
asoc->my_rwnd = max(stcb->sctp_socket->so_rcv.sb_hiwat, asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
SCTP_MINIMAL_RWND); SCTP_MINIMAL_RWND);
return; return;
} }
@ -134,7 +134,7 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->size_on_reasm_queue == 0 && asoc->size_on_reasm_queue == 0 &&
asoc->size_on_all_streams == 0) { asoc->size_on_all_streams == 0) {
/* Full rwnd granted */ /* Full rwnd granted */
calc = max(stcb->sctp_socket->so_rcv.sb_hiwat, calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
SCTP_MINIMAL_RWND); SCTP_MINIMAL_RWND);
return (calc); return (calc);
} }
@ -3024,7 +3024,6 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
asoc, asoc,
tp1->whoTo, tp1->whoTo,
&tp1->sent_rcv_time); &tp1->sent_rcv_time);
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0; tp1->do_rtt = 0;
} }
} }
@ -3500,7 +3499,6 @@ sctp_strike_gap_ack_chunks(struct sctp_tcb *stcb, struct sctp_association *asoc,
* this guy had a RTO calculation pending on * this guy had a RTO calculation pending on
* it, cancel it * it, cancel it
*/ */
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0; tp1->do_rtt = 0;
} }
/* fix counts and things */ /* fix counts and things */
@ -4171,12 +4169,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->send_size; tp1->send_size;
/* update RTO too? */ /* update RTO too? */
if ((tp1->do_rtt) && (tp1->whoTo->rto_pending)) { if (tp1->do_rtt) {
tp1->whoTo->RTO = tp1->whoTo->RTO =
sctp_calculate_rto(stcb, sctp_calculate_rto(stcb,
asoc, tp1->whoTo, asoc, tp1->whoTo,
&tp1->sent_rcv_time); &tp1->sent_rcv_time);
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0; tp1->do_rtt = 0;
} }
} }
@ -4738,7 +4735,6 @@ sctp_handle_sack(struct sctp_sack_chunk *ch, struct sctp_tcb *stcb,
sctp_calculate_rto(stcb, sctp_calculate_rto(stcb,
asoc, tp1->whoTo, asoc, tp1->whoTo,
&tp1->sent_rcv_time); &tp1->sent_rcv_time);
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0; tp1->do_rtt = 0;
} }
} }

View File

@ -2566,7 +2566,6 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* this guy had a RTO calculation * this guy had a RTO calculation
* pending on it, cancel it * pending on it, cancel it
*/ */
tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0; tp1->do_rtt = 0;
} }
SCTP_STAT_INCR(sctps_pdrpmark); SCTP_STAT_INCR(sctps_pdrpmark);

View File

@ -259,6 +259,9 @@ typedef struct callout sctp_os_timer_t;
(sb).sb_mb = NULL; \ (sb).sb_mb = NULL; \
(sb).sb_mbcnt = 0; (sb).sb_mbcnt = 0;
#define SCTP_SB_LIMIT_RCV(so) so->so_rcv.sb_hiwat
#define SCTP_SB_LIMIT_SND(so) so->so_snd.sb_hiwat
/* /*
* SCTP AUTH * SCTP AUTH
*/ */

View File

@ -3953,7 +3953,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/* place in my tag */ /* place in my tag */
initm->msg.init.initiate_tag = htonl(stcb->asoc.my_vtag); initm->msg.init.initiate_tag = htonl(stcb->asoc.my_vtag);
/* set up some of the credits. */ /* set up some of the credits. */
initm->msg.init.a_rwnd = htonl(max(inp->sctp_socket->so_rcv.sb_hiwat, initm->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket),
SCTP_MINIMAL_RWND)); SCTP_MINIMAL_RWND));
initm->msg.init.num_outbound_streams = htons(stcb->asoc.pre_open_streams); initm->msg.init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
@ -4862,7 +4862,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
stc.my_vtag = initackm_out->msg.init.initiate_tag; stc.my_vtag = initackm_out->msg.init.initiate_tag;
/* set up some of the credits. */ /* set up some of the credits. */
initackm_out->msg.init.a_rwnd = htonl(max(inp->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND)); initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket), SCTP_MINIMAL_RWND));
/* set what I want */ /* set what I want */
his_limit = ntohs(init_chk->init.num_inbound_streams); his_limit = ntohs(init_chk->init.num_inbound_streams);
/* choose what I want */ /* choose what I want */
@ -7314,15 +7314,10 @@ again_one_more_time:
*num_out += (ctl_cnt + bundle_at); *num_out += (ctl_cnt + bundle_at);
} }
if (bundle_at) { if (bundle_at) {
/* if (!net->rto_pending) { */
/* setup for a RTO measurement */ /* setup for a RTO measurement */
/* net->rto_pending = 1; */
tsns_sent = data_list[0]->rec.data.TSN_seq; tsns_sent = data_list[0]->rec.data.TSN_seq;
data_list[0]->do_rtt = 1; data_list[0]->do_rtt = 1;
/* } else { */
/* data_list[0]->do_rtt = 0; */
/* } */
SCTP_STAT_INCR_BY(sctps_senddata, bundle_at); SCTP_STAT_INCR_BY(sctps_senddata, bundle_at);
sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net); sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net);
if (sctp_early_fr) { if (sctp_early_fr) {
@ -9625,7 +9620,7 @@ jump_out:
chk->rec.chunk_id.can_take_data = 1; chk->rec.chunk_id.can_take_data = 1;
drp->ch.chunk_type = SCTP_PACKET_DROPPED; drp->ch.chunk_type = SCTP_PACKET_DROPPED;
drp->ch.chunk_length = htons(chk->send_size); drp->ch.chunk_length = htons(chk->send_size);
spc = stcb->sctp_socket->so_rcv.sb_hiwat; spc = SCTP_SB_LIMIT_RCV(stcb->sctp_socket);
if (spc < 0) { if (spc < 0) {
spc = 0; spc = 0;
} }
@ -10416,7 +10411,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*error = 0; *error = 0;
/* Unless E_EOR mode is on, we must make a send FIT in one call. */ /* Unless E_EOR mode is on, we must make a send FIT in one call. */
if (((user_marks_eor == 0) && non_blocking) && if (((user_marks_eor == 0) && non_blocking) &&
(uio->uio_resid > stcb->sctp_socket->so_snd.sb_hiwat)) { (uio->uio_resid > SCTP_SB_LIMIT_SND(stcb->sctp_socket))) {
/* It will NEVER fit */ /* It will NEVER fit */
*error = EMSGSIZE; *error = EMSGSIZE;
goto out_now; goto out_now;
@ -10828,7 +10823,7 @@ sctp_lower_sosend(struct socket *so,
asoc = &stcb->asoc; asoc = &stcb->asoc;
/* would we block? */ /* would we block? */
if (non_blocking) { if (non_blocking) {
if ((so->so_snd.sb_hiwat < if ((SCTP_SB_LIMIT_SND(so) <
(sndlen + stcb->asoc.total_output_queue_size)) || (sndlen + stcb->asoc.total_output_queue_size)) ||
(stcb->asoc.chunks_on_out_queue > (stcb->asoc.chunks_on_out_queue >
sctp_max_chunks_on_queue)) { sctp_max_chunks_on_queue)) {
@ -10997,8 +10992,8 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked; goto out_unlocked;
} }
/* Calculate the maximum we can send */ /* Calculate the maximum we can send */
if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) { if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size) {
max_len = so->so_snd.sb_hiwat - stcb->asoc.total_output_queue_size; max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
} else { } else {
max_len = 0; max_len = 0;
} }
@ -11021,7 +11016,7 @@ sctp_lower_sosend(struct socket *so,
if (max_len < sctp_add_more_threshold) { if (max_len < sctp_add_more_threshold) {
/* No room right no ! */ /* No room right no ! */
SOCKBUF_LOCK(&so->so_snd); SOCKBUF_LOCK(&so->so_snd);
while (so->so_snd.sb_hiwat < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) { while (SCTP_SB_LIMIT_SND(so) < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) {
#ifdef SCTP_BLK_LOGGING #ifdef SCTP_BLK_LOGGING
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA, sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA,
so, asoc, uio->uio_resid); so, asoc, uio->uio_resid);
@ -11049,8 +11044,8 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked; goto out_unlocked;
} }
} }
if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) { if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size) {
max_len = so->so_snd.sb_hiwat - stcb->asoc.total_output_queue_size; max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
} else { } else {
max_len = 0; max_len = 0;
} }
@ -11143,8 +11138,8 @@ 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 (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
max_len = so->so_snd.sb_hiwat - stcb->asoc.total_output_queue_size; max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
else else
max_len = 0; max_len = 0;
@ -11213,8 +11208,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);
if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) if (SCTP_SB_LIMIT_SND(so) > stcb->asoc.total_output_queue_size)
max_len = so->so_snd.sb_hiwat - stcb->asoc.total_output_queue_size; max_len = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
else else
max_len = 0; max_len = 0;
if (max_len > 0) { if (max_len > 0) {
@ -11338,7 +11333,7 @@ sctp_lower_sosend(struct socket *so,
* will get to sleep safely with the wakeup flag in * will get to sleep safely with the wakeup flag in
* place. * place.
*/ */
if (so->so_snd.sb_hiwat < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) { if (SCTP_SB_LIMIT_SND(so) < (stcb->asoc.total_output_queue_size + sctp_add_more_threshold)) {
#ifdef SCTP_BLK_LOGGING #ifdef SCTP_BLK_LOGGING
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK, sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
so, asoc, uio->uio_resid); so, asoc, uio->uio_resid);

View File

@ -1636,7 +1636,7 @@ sctp_inpcb_alloc(struct socket *so)
inp->sctp_socket = so; inp->sctp_socket = so;
inp->ip_inp.inp.inp_socket = so; inp->ip_inp.inp.inp_socket = so;
inp->partial_delivery_point = so->so_rcv.sb_hiwat >> SCTP_PARTIAL_DELIVERY_SHIFT; inp->partial_delivery_point = SCTP_SB_LIMIT_RCV(so) >> SCTP_PARTIAL_DELIVERY_SHIFT;
inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
#ifdef IPSEC #ifdef IPSEC

View File

@ -237,8 +237,6 @@ struct sctp_nets {
uint8_t will_exit_fast_recovery; uint8_t will_exit_fast_recovery;
/* Flags that probably can be combined into dest_state */ /* Flags that probably can be combined into dest_state */
uint8_t rto_variance_dir; /* increase = 1, decreasing = 0 */ uint8_t rto_variance_dir; /* increase = 1, decreasing = 0 */
uint8_t rto_pending; /* is segment marked for RTO update ** if we
* split? */
uint8_t fast_retran_ip; /* fast retransmit in progress */ uint8_t fast_retran_ip; /* fast retransmit in progress */
uint8_t hb_responded; uint8_t hb_responded;
uint8_t saw_newack; /* CMT's SFR algorithm flag */ uint8_t saw_newack; /* CMT's SFR algorithm flag */

View File

@ -524,7 +524,6 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
*/ */
orig_rwnd = stcb->asoc.peers_rwnd; orig_rwnd = stcb->asoc.peers_rwnd;
orig_flight = net->flight_size; orig_flight = net->flight_size;
net->rto_pending = 0;
net->fast_retran_ip = 0; net->fast_retran_ip = 0;
/* Now on to each chunk */ /* Now on to each chunk */
num_mk = cnt_mk = 0; num_mk = cnt_mk = 0;

View File

@ -2422,6 +2422,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
uint32_t *value; uint32_t *value;
SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize); SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
if (*value > SCTP_SB_LIMIT_RCV(so)) {
error = EINVAL;
break;
}
inp->partial_delivery_point = *value; inp->partial_delivery_point = *value;
} }
break; break;

View File

@ -1024,8 +1024,8 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
asoc->ipv6_addr_legal = 0; asoc->ipv6_addr_legal = 0;
} }
asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND); asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(m->sctp_socket), SCTP_MINIMAL_RWND);
asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat; asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(m->sctp_socket);
asoc->smallest_mtu = m->sctp_frag_point; asoc->smallest_mtu = m->sctp_frag_point;
asoc->minrto = m->sctp_ep.sctp_minrto; asoc->minrto = m->sctp_ep.sctp_minrto;
@ -4354,7 +4354,10 @@ sctp_user_rcvd(struct sctp_tcb *stcb, int *freed_so_far, int hold_rlock,
atomic_add_int(&stcb->asoc.refcnt, 1); atomic_add_int(&stcb->asoc.refcnt, 1);
if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { if (stcb->asoc.state & (SCTP_STATE_ABOUT_TO_BE_FREED |
SCTP_STATE_SHUTDOWN_RECEIVED |
SCTP_STATE_SHUTDOWN_ACK_SENT)
) {
/* Pre-check If we are freeing no update */ /* Pre-check If we are freeing no update */
goto no_lock; goto no_lock;
} }
@ -4504,7 +4507,7 @@ sctp_sorecvmsg(struct socket *so,
if (inp == NULL) { if (inp == NULL) {
return (EFAULT); return (EFAULT);
} }
rwnd_req = (so->so_rcv.sb_hiwat >> SCTP_RWND_HIWAT_SHIFT); rwnd_req = (SCTP_SB_LIMIT_RCV(so) >> SCTP_RWND_HIWAT_SHIFT);
/* Must be at least a MTU's worth */ /* Must be at least a MTU's worth */
if (rwnd_req < SCTP_MIN_RWND) if (rwnd_req < SCTP_MIN_RWND)
rwnd_req = SCTP_MIN_RWND; rwnd_req = SCTP_MIN_RWND;