summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrrs <rrs@FreeBSD.org>2011-02-02 11:13:23 +0000
committerrrs <rrs@FreeBSD.org>2011-02-02 11:13:23 +0000
commit21c4d27f12ba02243502767bea3b5204d7cc5b4b (patch)
tree0056ca24f8b0f300a7c3fbf157aaaace4954e2df
parent3d021845fb3da3ecb328f8817a723c879122b386 (diff)
downloadFreeBSD-src-21c4d27f12ba02243502767bea3b5204d7cc5b4b.zip
FreeBSD-src-21c4d27f12ba02243502767bea3b5204d7cc5b4b.tar.gz
1) Allow a chunk to track the cwnd it was at when sent.
2) Add separate max-bursts for retransmit and hb. These are set to sysctlable values but not settable via the socket api. This makes sure we don't blast out HB's or fast-retransmits. 3) Determine on the first data transmission on a net if its local-lan (by being under or over a RTT). This can later be used to think about different algorithms based on locallan vs big-i (experimental) 4) The cwnd should NOT be allowed to grow when an ECNEcho is seen (TCP has this same bug). We fix this in SCTP so an ECNe being seen prevents an advance of cwnd. 5) CWR's should not be sent multiple times to the same network, instead just updating the TSN being transmitted if needed. MFC after: 1 Month
-rw-r--r--sys/netinet/sctp_cc_functions.c1
-rw-r--r--sys/netinet/sctp_constants.h23
-rw-r--r--sys/netinet/sctp_indata.c20
-rw-r--r--sys/netinet/sctp_indata.h4
-rw-r--r--sys/netinet/sctp_input.c27
-rw-r--r--sys/netinet/sctp_output.c24
-rw-r--r--sys/netinet/sctp_pcb.c2
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_structs.h11
-rw-r--r--sys/netinet/sctp_sysctl.c6
-rw-r--r--sys/netinet/sctp_sysctl.h11
-rw-r--r--sys/netinet/sctp_timer.c3
-rw-r--r--sys/netinet/sctputil.c14
-rw-r--r--sys/netinet/sctputil.h2
14 files changed, 120 insertions, 29 deletions
diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c
index ddd2fd85..d9cf609 100644
--- a/sys/netinet/sctp_cc_functions.c
+++ b/sys/netinet/sctp_cc_functions.c
@@ -481,6 +481,7 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net)
}
}
+
static void
sctp_cwnd_update_after_ecn_echo(struct sctp_tcb *stcb, struct sctp_nets *net,
int in_window, int num_pkt_lost)
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index 719da64..02468da 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -345,6 +345,16 @@ __FBSDID("$FreeBSD$");
/* default max I can burst out after a fast retransmit, 0 disables it */
#define SCTP_DEF_MAX_BURST 0
+#define SCTP_DEF_HBMAX_BURST 4
+#define SCTP_DEF_FRMAX_BURST 4
+
+/* RTO calculation flag to say if it
+ * is safe to determine local lan or not.
+ */
+#define SCTP_DETERMINE_LL_NOTOK 0
+#define SCTP_DETERMINE_LL_OK 1
+
+
/* IP hdr (20/40) + 12+2+2 (enet) + sctp common 12 */
#define SCTP_FIRST_MBUF_RESV 68
/* Packet transmit states in the sent field */
@@ -947,6 +957,18 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_TIME_WAIT 60
+/* How many micro seconds is the cutoff from
+ * local lan type rtt's
+ */
+ /*
+ * We allow 500us for the rtt and another 500us for the cookie processing
+ * since we measure this on the first rtt.
+ */
+#define SCTP_LOCAL_LAN_RTT 1100
+#define SCTP_LAN_UNKNOWN 0
+#define SCTP_LAN_LOCAL 1
+#define SCTP_LAN_INTERNET 2
+
#define SCTP_SEND_BUFFER_SPLITTING 0x00000001
#define SCTP_RECV_BUFFER_SPLITTING 0x00000002
@@ -994,6 +1016,7 @@ __FBSDID("$FreeBSD$");
#if defined(_KERNEL)
+#define SCTP_GETTIME_TIMESPEC(x) (getnanouptime(x))
#define SCTP_GETTIME_TIMEVAL(x) (getmicrouptime(x))
#define SCTP_GETPTIME_TIMEVAL(x) (microuptime(x))
#endif
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index a6f8d25..186640d 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -2955,7 +2955,8 @@ sctp_process_segment_range(struct sctp_tcb *stcb, struct sctp_tmit_chunk **p_tp1
&stcb->asoc,
tp1->whoTo,
&tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_OK);
tp1->do_rtt = 0;
}
}
@@ -3751,7 +3752,7 @@ sctp_window_probe_recovery(struct sctp_tcb *stcb,
void
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
- uint32_t rwnd, int *abort_now)
+ uint32_t rwnd, int *abort_now, int ecne_seen)
{
struct sctp_nets *net;
struct sctp_association *asoc;
@@ -3902,7 +3903,8 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
sctp_calculate_rto(stcb,
asoc, tp1->whoTo,
&tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_OK);
tp1->do_rtt = 0;
}
}
@@ -3994,7 +3996,7 @@ sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
}
/* JRS - Use the congestion control given in the CC module */
- if (asoc->last_acked_seq != cumack)
+ if ((asoc->last_acked_seq != cumack) && (ecne_seen == 0))
asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, 1, 0, 0);
asoc->last_acked_seq = cumack;
@@ -4240,7 +4242,7 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
struct sctp_tcb *stcb, struct sctp_nets *net_from,
uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup,
int *abort_now, uint8_t flags,
- uint32_t cum_ack, uint32_t rwnd)
+ uint32_t cum_ack, uint32_t rwnd, int ecne_seen)
{
struct sctp_association *asoc;
struct sctp_tmit_chunk *tp1, *tp2;
@@ -4500,7 +4502,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
sctp_calculate_rto(stcb,
asoc, tp1->whoTo,
&tp1->sent_rcv_time,
- sctp_align_safe_nocopy);
+ sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_OK);
tp1->do_rtt = 0;
}
}
@@ -4754,7 +4757,8 @@ sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
asoc->saw_sack_with_nr_frags = 0;
/* JRS - Use the congestion control given in the CC module */
- asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
+ if (ecne_seen == 0)
+ asoc->cc_functions.sctp_cwnd_update_after_sack(stcb, asoc, accum_moved, reneged_all, will_exit_fast_recovery);
if (TAILQ_EMPTY(&asoc->sent_queue)) {
/* nothing left in-flight */
@@ -5077,7 +5081,7 @@ sctp_update_acked(struct sctp_tcb *stcb, struct sctp_shutdown_chunk *cp,
a_rwnd = stcb->asoc.peers_rwnd + stcb->asoc.total_flight;
/* Now call the express sack handling */
- sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag);
+ sctp_express_handle_sack(stcb, cum_ack, a_rwnd, abort_flag, 0);
}
static void
diff --git a/sys/netinet/sctp_indata.h b/sys/netinet/sctp_indata.h
index 7f62cca..2801e3d 100644
--- a/sys/netinet/sctp_indata.h
+++ b/sys/netinet/sctp_indata.h
@@ -93,14 +93,14 @@ sctp_calc_rwnd(struct sctp_tcb *stcb, struct sctp_association *asoc);
void
sctp_express_handle_sack(struct sctp_tcb *stcb, uint32_t cumack,
- uint32_t rwnd, int *abort_now);
+ uint32_t rwnd, int *abort_now, int ecne_seen);
void
sctp_handle_sack(struct mbuf *m, int offset_seg, int offset_dup,
struct sctp_tcb *stcb, struct sctp_nets *net_from,
uint16_t num_seg, uint16_t num_nr_seg, uint16_t num_dup,
int *abort_now, uint8_t flags,
- uint32_t cum_ack, uint32_t rwnd);
+ uint32_t cum_ack, uint32_t rwnd, int ecne_seen);
/* draft-ietf-tsvwg-usctp */
void
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 6fc8e5b..dd6410a 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -481,7 +481,8 @@ sctp_process_init_ack(struct mbuf *m, int iphlen, int offset,
asoc->primary_destination, SCTP_FROM_SCTP_INPUT + SCTP_LOC_4);
/* calculate the RTO */
- net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy);
+ net->RTO = sctp_calculate_rto(stcb, asoc, net, &asoc->time_entered, sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_NOTOK);
retval = sctp_send_cookie_echo(m, offset, stcb, net);
if (retval < 0) {
@@ -625,7 +626,8 @@ sctp_handle_heartbeat_ack(struct sctp_heartbeat_chunk *cp,
net, net->cwnd);
}
/* Now lets do a RTO with this */
- r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy);
+ r_net->RTO = sctp_calculate_rto(stcb, &stcb->asoc, r_net, &tv, sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_OK);
/* Mobility adaptation */
if (req_prim) {
if ((sctp_is_mobility_feature_on(stcb->sctp_ep,
@@ -1540,7 +1542,9 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
*/
net->hb_responded = 1;
net->RTO = sctp_calculate_rto(stcb, asoc, net,
- &cookie->time_entered, sctp_align_unsafe_makecopy);
+ &cookie->time_entered,
+ sctp_align_unsafe_makecopy,
+ SCTP_DETERMINE_LL_NOTOK);
if (stcb->asoc.sctp_autoclose_ticks &&
(sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))) {
@@ -2243,7 +2247,8 @@ sctp_process_cookie_new(struct mbuf *m, int iphlen, int offset,
(void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
if ((netp) && (*netp)) {
(*netp)->RTO = sctp_calculate_rto(stcb, asoc, *netp,
- &cookie->time_entered, sctp_align_unsafe_makecopy);
+ &cookie->time_entered, sctp_align_unsafe_makecopy,
+ SCTP_DETERMINE_LL_NOTOK);
}
/* respond with a COOKIE-ACK */
sctp_send_cookie_ack(stcb);
@@ -2831,7 +2836,8 @@ sctp_handle_cookie_ack(struct sctp_cookie_ack_chunk *cp,
SCTP_STAT_INCR_GAUGE32(sctps_currestab);
if (asoc->overall_error_count == 0) {
net->RTO = sctp_calculate_rto(stcb, asoc, net,
- &asoc->time_entered, sctp_align_safe_nocopy);
+ &asoc->time_entered, sctp_align_safe_nocopy,
+ SCTP_DETERMINE_LL_NOTOK);
}
(void)SCTP_GETTIME_TIMEVAL(&asoc->time_entered);
sctp_ulp_notify(SCTP_NOTIFY_ASSOC_UP, stcb, 0, NULL, SCTP_SO_NOT_LOCKED);
@@ -2939,6 +2945,7 @@ sctp_handle_ecn_echo(struct sctp_ecne_chunk *cp,
TAILQ_FOREACH(lchk, &stcb->asoc.sent_queue, sctp_next) {
if (lchk->rec.data.TSN_seq == tsn) {
net = lchk->whoTo;
+ net->ecn_prev_cwnd = lchk->rec.data.cwnd_at_send;
break;
}
if (SCTP_TSN_GT(lchk->rec.data.TSN_seq, tsn)) {
@@ -4196,6 +4203,7 @@ __attribute__((noinline))
uint32_t chk_length;
int ret;
int abort_no_unlock = 0;
+ int ecne_seen = 0;
/*
* How big should this be, and should it be alloc'd? Lets try the
@@ -4691,13 +4699,13 @@ process_control_chunks:
* with no missing segments to go
* this way too.
*/
- sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now);
+ sctp_express_handle_sack(stcb, cum_ack, a_rwnd, &abort_now, ecne_seen);
} else {
if (netp && *netp)
sctp_handle_sack(m, offset_seg, offset_dup,
stcb, *netp,
num_seg, 0, num_dup, &abort_now, flags,
- cum_ack, a_rwnd);
+ cum_ack, a_rwnd, ecne_seen);
}
if (abort_now) {
/* ABORT signal from sack processing */
@@ -4780,13 +4788,13 @@ process_control_chunks:
* too.
*/
sctp_express_handle_sack(stcb, cum_ack, a_rwnd,
- &abort_now);
+ &abort_now, ecne_seen);
} else {
if (netp && *netp)
sctp_handle_sack(m, offset_seg, offset_dup,
stcb, *netp,
num_seg, num_nr_seg, num_dup, &abort_now, flags,
- cum_ack, a_rwnd);
+ cum_ack, a_rwnd, ecne_seen);
}
if (abort_now) {
/* ABORT signal from sack processing */
@@ -5063,6 +5071,7 @@ process_control_chunks:
stcb->asoc.overall_error_count = 0;
sctp_handle_ecn_echo((struct sctp_ecne_chunk *)ch,
stcb);
+ ecne_seen = 1;
}
break;
case SCTP_ECN_CWR:
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index d1d9147..98bb8e2 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -6395,6 +6395,7 @@ sctp_clean_up_datalist(struct sctp_tcb *stcb,
}
/* record time */
data_list[i]->sent_rcv_time = net->last_sent_time;
+ data_list[i]->rec.data.cwnd_at_send = net->cwnd;
data_list[i]->rec.data.fast_retran_tsn = data_list[i]->rec.data.TSN_seq;
if (data_list[i]->whoTo == NULL) {
data_list[i]->whoTo = net;
@@ -9414,7 +9415,7 @@ sctp_chunk_output(struct sctp_inpcb *inp,
&now, &now_filled, frag_point, so_locked);
return;
}
- if ((asoc->max_burst > 0) && (tot_frs > asoc->max_burst)) {
+ if ((asoc->fr_max_burst > 0) && (tot_frs >= asoc->fr_max_burst)) {
/* Hit FR burst limit */
return;
}
@@ -10962,6 +10963,27 @@ sctp_send_cwr(struct sctp_tcb *stcb, struct sctp_nets *net, uint32_t high_tsn, u
asoc = &stcb->asoc;
SCTP_TCB_LOCK_ASSERT(stcb);
+
+ TAILQ_FOREACH(chk, &asoc->control_send_queue, sctp_next) {
+ if ((chk->rec.chunk_id.id == SCTP_ECN_CWR) && (net == chk->whoTo)) {
+ /*
+ * found a previous CWR queued to same destination
+ * update it if needed
+ */
+ uint32_t ctsn;
+
+ cwr = mtod(chk->data, struct sctp_cwr_chunk *);
+ ctsn = ntohl(cwr->tsn);
+ if (SCTP_TSN_GT(high_tsn, ctsn)) {
+ cwr->tsn = htonl(high_tsn);
+ }
+ if (override & SCTP_CWR_REDUCE_OVERRIDE) {
+ /* Make sure override is carried */
+ cwr->ch.chunk_flags |= SCTP_CWR_REDUCE_OVERRIDE;
+ }
+ return;
+ }
+ }
sctp_alloc_a_chunk(stcb, chk);
if (chk == NULL) {
return;
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index cdbc939..310b294 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2516,6 +2516,8 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
m->sctp_sws_sender = SCTP_SWS_SENDER_DEF;
m->sctp_sws_receiver = SCTP_SWS_RECEIVER_DEF;
m->max_burst = SCTP_BASE_SYSCTL(sctp_max_burst_default);
+ m->fr_max_burst = SCTP_BASE_SYSCTL(sctp_fr_max_burst_default);
+
m->sctp_default_cc_module = SCTP_BASE_SYSCTL(sctp_default_cc_module);
m->sctp_default_ss_module = SCTP_BASE_SYSCTL(sctp_default_ss_module);
/* number of streams to pre-open on a association */
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index e199eb7..cbb185a 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -318,6 +318,7 @@ struct sctp_pcb {
uint32_t adaptation_layer_indicator;
uint32_t store_at;
uint32_t max_burst;
+ uint32_t fr_max_burst;
char current_secret_number;
char last_secret_number;
};
diff --git a/sys/netinet/sctp_structs.h b/sys/netinet/sctp_structs.h
index c17729f..64491dd 100644
--- a/sys/netinet/sctp_structs.h
+++ b/sys/netinet/sctp_structs.h
@@ -237,6 +237,8 @@ struct sctp_nets {
uint32_t flight_size;
uint32_t cwnd; /* actual cwnd */
uint32_t prev_cwnd; /* cwnd before any processing */
+ uint32_t ecn_prev_cwnd; /* ECN prev cwnd at first ecn_echo seen in new
+ * window */
uint32_t partial_bytes_acked; /* in CA tracks when to incr a MTU */
uint32_t prev_rtt;
/* tracking variables to avoid the aloc/free in sack processing */
@@ -318,6 +320,7 @@ struct sctp_nets {
uint8_t window_probe; /* Doing a window probe? */
uint8_t RTO_measured; /* Have we done the first measure */
uint8_t last_hs_used; /* index into the last HS table entry we used */
+ uint8_t lan_type;
/* JRS - struct used in HTCP algorithm */
struct htcp htcp_ca;
};
@@ -329,8 +332,7 @@ struct sctp_data_chunkrec {
uint16_t stream_number; /* the stream number of this guy */
uint32_t payloadtype;
uint32_t context; /* from send */
-
- uint8_t fwd_tsn_cnt;
+ uint32_t cwnd_at_send;
/*
* part of the Highest sacked algorithm to be able to stroke counts
* on ones that are FR'd.
@@ -342,6 +344,7 @@ struct sctp_data_chunkrec {
* outbound holds sending flags for PR-SCTP. */
uint8_t state_flags;
uint8_t chunk_was_revoked;
+ uint8_t fwd_tsn_cnt;
};
TAILQ_HEAD(sctpchunk_listhead, sctp_tmit_chunk);
@@ -1052,8 +1055,10 @@ struct sctp_association {
*/
uint8_t send_sack;
- /* max burst after fast retransmit completes */
+ /* max burst of new packets into the network */
uint32_t max_burst;
+ /* max burst of fast retransmit packets */
+ uint32_t fr_max_burst;
uint8_t sat_network; /* RTT is in range of sat net or greater */
uint8_t sat_network_lockout; /* lockout code */
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index 4a75dfd..350b0f8 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -59,6 +59,7 @@ sctp_init_sysctls()
SCTP_BASE_SYSCTL(sctp_strict_init) = SCTPCTL_STRICT_INIT_DEFAULT;
SCTP_BASE_SYSCTL(sctp_peer_chunk_oh) = SCTPCTL_PEER_CHKOH_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_burst_default) = SCTPCTL_MAXBURST_DEFAULT;
+ SCTP_BASE_SYSCTL(sctp_fr_max_burst_default) = SCTPCTL_FRMAXBURST_DEFAULT;
SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = SCTPCTL_MAXCHUNKS_DEFAULT;
SCTP_BASE_SYSCTL(sctp_hashtblsize) = SCTPCTL_TCBHASHSIZE_DEFAULT;
SCTP_BASE_SYSCTL(sctp_pcbtblsize) = SCTPCTL_PCBHASHSIZE_DEFAULT;
@@ -576,6 +577,7 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
RANGECHK(SCTP_BASE_SYSCTL(sctp_strict_init), SCTPCTL_STRICT_INIT_MIN, SCTPCTL_STRICT_INIT_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_peer_chunk_oh), SCTPCTL_PEER_CHKOH_MIN, SCTPCTL_PEER_CHKOH_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_burst_default), SCTPCTL_MAXBURST_MIN, SCTPCTL_MAXBURST_MAX);
+ RANGECHK(SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), SCTPCTL_FRMAXBURST_MIN, SCTPCTL_FRMAXBURST_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), SCTPCTL_MAXCHUNKS_MIN, SCTPCTL_MAXCHUNKS_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_hashtblsize), SCTPCTL_TCBHASHSIZE_MIN, SCTPCTL_TCBHASHSIZE_MAX);
RANGECHK(SCTP_BASE_SYSCTL(sctp_pcbtblsize), SCTPCTL_PCBHASHSIZE_MIN, SCTPCTL_PCBHASHSIZE_MAX);
@@ -849,6 +851,10 @@ SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxburst, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_burst_default), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXBURST_DESC);
+SYSCTL_PROC(_net_inet_sctp, OID_AUTO, fr_maxburst, CTLTYPE_UINT | CTLFLAG_RW,
+ &SCTP_BASE_SYSCTL(sctp_fr_max_burst_default), 0, sysctl_sctp_check, "IU",
+ SCTPCTL_FRMAXBURST_DESC);
+
SYSCTL_PROC(_net_inet_sctp, OID_AUTO, maxchunks, CTLTYPE_UINT | CTLFLAG_RW,
&SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue), 0, sysctl_sctp_check, "IU",
SCTPCTL_MAXCHUNKS_DESC);
diff --git a/sys/netinet/sctp_sysctl.h b/sys/netinet/sctp_sysctl.h
index 3f33d3d..89b36be 100644
--- a/sys/netinet/sctp_sysctl.h
+++ b/sys/netinet/sctp_sysctl.h
@@ -43,7 +43,7 @@ struct sctp_sysctl {
uint32_t sctp_auto_asconf;
uint32_t sctp_multiple_asconfs;
uint32_t sctp_ecn_enable;
- uint32_t sctp_not_used;
+ uint32_t sctp_fr_max_burst_default;
uint32_t sctp_strict_sacks;
#if !defined(SCTP_WITH_NO_CSUM)
uint32_t sctp_no_csum_on_loopback;
@@ -182,6 +182,13 @@ struct sctp_sysctl {
#define SCTPCTL_MAXBURST_MAX 0xFFFFFFFF
#define SCTPCTL_MAXBURST_DEFAULT SCTP_DEF_MAX_BURST
+/* fr_maxburst: Default max burst for sctp endpoints when fast retransmitting */
+#define SCTPCTL_FRMAXBURST_DESC "Default fr max burst for sctp endpoints"
+#define SCTPCTL_FRMAXBURST_MIN 0
+#define SCTPCTL_FRMAXBURST_MAX 0xFFFFFFFF
+#define SCTPCTL_FRMAXBURST_DEFAULT SCTP_DEF_FRMAX_BURST
+
+
/* maxchunks: Default max chunks on queue per asoc */
#define SCTPCTL_MAXCHUNKS_DESC "Default max chunks on queue per asoc"
#define SCTPCTL_MAXCHUNKS_MIN 0
@@ -402,7 +409,7 @@ struct sctp_sysctl {
#define SCTPCTL_HB_MAX_BURST_DESC "Confirmation Heartbeat max burst"
#define SCTPCTL_HB_MAX_BURST_MIN 1
#define SCTPCTL_HB_MAX_BURST_MAX 0xFFFFFFFF
-#define SCTPCTL_HB_MAX_BURST_DEFAULT SCTP_DEF_MAX_BURST
+#define SCTPCTL_HB_MAX_BURST_DEFAULT SCTP_DEF_HBMAX_BURST
/* abort_at_limit: When one-2-one hits qlimit abort */
#define SCTPCTL_ABORT_AT_LIMIT_DESC "When one-2-one hits qlimit abort"
diff --git a/sys/netinet/sctp_timer.c b/sys/netinet/sctp_timer.c
index 1cb77f0..461e0c8 100644
--- a/sys/netinet/sctp_timer.c
+++ b/sys/netinet/sctp_timer.c
@@ -1630,7 +1630,8 @@ sctp_heartbeat_timer(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
else if (ret == 0) {
break;
}
- if (cnt_sent >= SCTP_BASE_SYSCTL(sctp_hb_maxburst))
+ if (SCTP_BASE_SYSCTL(sctp_hb_maxburst) &&
+ (cnt_sent >= SCTP_BASE_SYSCTL(sctp_hb_maxburst)))
break;
}
}
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index 823eea2..bef57d1 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -913,6 +913,7 @@ sctp_init_asoc(struct sctp_inpcb *m, struct sctp_tcb *stcb,
/* init all variables to a known value. */
SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_INUSE);
asoc->max_burst = m->sctp_ep.max_burst;
+ asoc->fr_max_burst = m->sctp_ep.fr_max_burst;
asoc->heart_beat_delay = TICKS_TO_MSEC(m->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
asoc->cookie_life = m->sctp_ep.def_cookie_life;
asoc->sctp_cmt_on_off = m->sctp_cmt_on_off;
@@ -2459,12 +2460,13 @@ sctp_mtu_size_reset(struct sctp_inpcb *inp,
* given an association and starting time of the current RTT period return
* RTO in number of msecs net should point to the current network
*/
+
uint32_t
sctp_calculate_rto(struct sctp_tcb *stcb,
struct sctp_association *asoc,
struct sctp_nets *net,
struct timeval *told,
- int safe)
+ int safe, int local_lan_determine)
{
/*-
* given an association and the starting time of the current RTT
@@ -2492,13 +2494,21 @@ sctp_calculate_rto(struct sctp_tcb *stcb,
/************************/
/* get the current time */
(void)SCTP_GETTIME_TIMEVAL(&now);
-
/*
* Record the real time of the last RTT for use in DC-CC.
*/
net->last_measured_rtt = now;
timevalsub(&net->last_measured_rtt, old);
+ /* Do we need to determine the lan type? */
+ if ((local_lan_determine == SCTP_DETERMINE_LL_OK) && (net->lan_type == SCTP_LAN_UNKNOWN)) {
+ if ((net->last_measured_rtt.tv_sec) ||
+ (net->last_measured_rtt.tv_usec > SCTP_LOCAL_LAN_RTT)) {
+ net->lan_type = SCTP_LAN_INTERNET;
+ } else {
+ net->lan_type = SCTP_LAN_LOCAL;
+ }
+ }
/* compute the RTT value */
if ((u_long)now.tv_sec > (u_long)old->tv_sec) {
calc_time = ((u_long)now.tv_sec - (u_long)old->tv_sec) * 1000;
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index d109ec2..d07c098 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -132,7 +132,7 @@ void
uint32_t
sctp_calculate_rto(struct sctp_tcb *, struct sctp_association *,
- struct sctp_nets *, struct timeval *, int);
+ struct sctp_nets *, struct timeval *, int, int);
uint32_t sctp_calculate_len(struct mbuf *);
OpenPOWER on IntegriCloud