summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2007-03-20 10:23:11 +0000
committerrrs <rrs@FreeBSD.org>2007-03-20 10:23:11 +0000
commiteecb0a8aa72ff92a9cc4881892c8fa117737ad7f (patch)
treec1ac41de5e74c6da148fd963903611df770236c1 /sys
parente588f34e9ccbae45abec18203973bfaeb542187d (diff)
downloadFreeBSD-src-eecb0a8aa72ff92a9cc4881892c8fa117737ad7f.zip
FreeBSD-src-eecb0a8aa72ff92a9cc4881892c8fa117737ad7f.tar.gz
- 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.
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/sctp_indata.c10
-rw-r--r--sys/netinet/sctp_input.c1
-rw-r--r--sys/netinet/sctp_os_bsd.h3
-rw-r--r--sys/netinet/sctp_output.c35
-rw-r--r--sys/netinet/sctp_pcb.c2
-rw-r--r--sys/netinet/sctp_structs.h2
-rw-r--r--sys/netinet/sctp_timer.c1
-rw-r--r--sys/netinet/sctp_usrreq.c4
-rw-r--r--sys/netinet/sctputil.c11
9 files changed, 33 insertions, 36 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 36bace9..5786782 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -74,7 +74,7 @@ sctp_set_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc)
asoc->size_on_reasm_queue == 0 &&
asoc->size_on_all_streams == 0) {
/* 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);
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_all_streams == 0) {
/* Full rwnd granted */
- calc = max(stcb->sctp_socket->so_rcv.sb_hiwat,
+ calc = max(SCTP_SB_LIMIT_RCV(stcb->sctp_socket),
SCTP_MINIMAL_RWND);
return (calc);
}
@@ -3024,7 +3024,6 @@ sctp_handle_segments(struct sctp_tcb *stcb, struct sctp_association *asoc,
asoc,
tp1->whoTo,
&tp1->sent_rcv_time);
- tp1->whoTo->rto_pending = 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
* it, cancel it
*/
- tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0;
}
/* fix counts and things */
@@ -4171,12 +4169,11 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
tp1->send_size;
/* update RTO too? */
- if ((tp1->do_rtt) && (tp1->whoTo->rto_pending)) {
+ if (tp1->do_rtt) {
tp1->whoTo->RTO =
sctp_calculate_rto(stcb,
asoc, tp1->whoTo,
&tp1->sent_rcv_time);
- tp1->whoTo->rto_pending = 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,
asoc, tp1->whoTo,
&tp1->sent_rcv_time);
- tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0;
}
}
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 86634a9..2317cea 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -2566,7 +2566,6 @@ process_chunk_drop(struct sctp_tcb *stcb, struct sctp_chunk_desc *desc,
* this guy had a RTO calculation
* pending on it, cancel it
*/
- tp1->whoTo->rto_pending = 0;
tp1->do_rtt = 0;
}
SCTP_STAT_INCR(sctps_pdrpmark);
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index 6900363..e1b7a1f 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -259,6 +259,9 @@ typedef struct callout sctp_os_timer_t;
(sb).sb_mb = NULL; \
(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
*/
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 4c20802..b23edb3 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -3953,7 +3953,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb)
/* place in my tag */
initm->msg.init.initiate_tag = htonl(stcb->asoc.my_vtag);
/* 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));
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;
/* 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 */
his_limit = ntohs(init_chk->init.num_inbound_streams);
/* choose what I want */
@@ -7314,15 +7314,10 @@ again_one_more_time:
*num_out += (ctl_cnt + bundle_at);
}
if (bundle_at) {
- /* if (!net->rto_pending) { */
/* setup for a RTO measurement */
- /* net->rto_pending = 1; */
tsns_sent = data_list[0]->rec.data.TSN_seq;
data_list[0]->do_rtt = 1;
- /* } else { */
- /* data_list[0]->do_rtt = 0; */
- /* } */
SCTP_STAT_INCR_BY(sctps_senddata, bundle_at);
sctp_clean_up_datalist(stcb, asoc, data_list, bundle_at, net);
if (sctp_early_fr) {
@@ -9625,7 +9620,7 @@ jump_out:
chk->rec.chunk_id.can_take_data = 1;
drp->ch.chunk_type = SCTP_PACKET_DROPPED;
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) {
spc = 0;
}
@@ -10416,7 +10411,7 @@ sctp_copy_it_in(struct sctp_tcb *stcb,
*error = 0;
/* Unless E_EOR mode is on, we must make a send FIT in one call. */
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 */
*error = EMSGSIZE;
goto out_now;
@@ -10828,7 +10823,7 @@ sctp_lower_sosend(struct socket *so,
asoc = &stcb->asoc;
/* would we block? */
if (non_blocking) {
- if ((so->so_snd.sb_hiwat <
+ if ((SCTP_SB_LIMIT_SND(so) <
(sndlen + stcb->asoc.total_output_queue_size)) ||
(stcb->asoc.chunks_on_out_queue >
sctp_max_chunks_on_queue)) {
@@ -10997,8 +10992,8 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
/* Calculate the maximum we can send */
- if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) {
- max_len = 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 = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
} else {
max_len = 0;
}
@@ -11021,7 +11016,7 @@ sctp_lower_sosend(struct socket *so,
if (max_len < sctp_add_more_threshold) {
/* No room right no ! */
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
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLKA,
so, asoc, uio->uio_resid);
@@ -11049,8 +11044,8 @@ sctp_lower_sosend(struct socket *so,
goto out_unlocked;
}
}
- if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size) {
- max_len = 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 = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
} else {
max_len = 0;
}
@@ -11143,8 +11138,8 @@ sctp_lower_sosend(struct socket *so,
/* How much room do we have? */
struct mbuf *new_tail, *mm;
- if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size)
- max_len = 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 = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
else
max_len = 0;
@@ -11213,8 +11208,8 @@ sctp_lower_sosend(struct socket *so,
hold_tcblock = 1;
}
sctp_prune_prsctp(stcb, asoc, srcv, sndlen);
- if (so->so_snd.sb_hiwat > stcb->asoc.total_output_queue_size)
- max_len = 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 = SCTP_SB_LIMIT_SND(so) - stcb->asoc.total_output_queue_size;
else
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
* 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
sctp_log_block(SCTP_BLOCK_LOG_INTO_BLK,
so, asoc, uio->uio_resid);
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 26e0d59..b2197e3 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -1636,7 +1636,7 @@ sctp_inpcb_alloc(struct socket *so)
inp->sctp_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;
#ifdef IPSEC
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index 6830b13..d57e3a0 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -237,8 +237,6 @@ struct sctp_nets {
uint8_t will_exit_fast_recovery;
/* Flags that probably can be combined into dest_state */
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 hb_responded;
uint8_t saw_newack; /* CMT's SFR algorithm flag */
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 1d6902e..a075e8e 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -524,7 +524,6 @@ sctp_mark_all_for_resend(struct sctp_tcb *stcb,
*/
orig_rwnd = stcb->asoc.peers_rwnd;
orig_flight = net->flight_size;
- net->rto_pending = 0;
net->fast_retran_ip = 0;
/* Now on to each chunk */
num_mk = cnt_mk = 0;
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index 82c952e..9899671 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -2422,6 +2422,10 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
uint32_t *value;
SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
+ if (*value > SCTP_SB_LIMIT_RCV(so)) {
+ error = EINVAL;
+ break;
+ }
inp->partial_delivery_point = *value;
}
break;
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index ea7a830..aa84b98 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -1024,8 +1024,8 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_association *asoc,
asoc->ipv6_addr_legal = 0;
}
- asoc->my_rwnd = max(m->sctp_socket->so_rcv.sb_hiwat, SCTP_MINIMAL_RWND);
- asoc->peers_rwnd = m->sctp_socket->so_rcv.sb_hiwat;
+ asoc->my_rwnd = max(SCTP_SB_LIMIT_RCV(m->sctp_socket), SCTP_MINIMAL_RWND);
+ asoc->peers_rwnd = SCTP_SB_LIMIT_RCV(m->sctp_socket);
asoc->smallest_mtu = m->sctp_frag_point;
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);
- 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 */
goto no_lock;
}
@@ -4504,7 +4507,7 @@ sctp_sorecvmsg(struct socket *so,
if (inp == NULL) {
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 */
if (rwnd_req < SCTP_MIN_RWND)
rwnd_req = SCTP_MIN_RWND;
OpenPOWER on IntegriCloud