#include <netinet/in_systm.h>
#include <netinet/ip.h>
-#if INET6
#include <netinet/ip6.h>
-#endif
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_fsm.h>
.switch_to = tcp_newreno_switch_cc
};
-int tcp_newreno_init(struct tcpcb *tp) {
+int
+tcp_newreno_init(struct tcpcb *tp)
+{
#pragma unused(tp)
OSIncrementAtomic((volatile SInt32 *)&tcp_cc_newreno.num_sockets);
return 0;
}
-int tcp_newreno_cleanup(struct tcpcb *tp) {
+int
+tcp_newreno_cleanup(struct tcpcb *tp)
+{
#pragma unused(tp)
OSDecrementAtomic((volatile SInt32 *)&tcp_cc_newreno.num_sockets);
return 0;
* this is a local network or not.
*/
void
-tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp) {
+tcp_newreno_cwnd_init_or_reset(struct tcpcb *tp)
+{
tcp_cc_cwnd_init_or_reset(tp);
}
* This will get called from header prediction code.
*/
void
-tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_congestion_avd(struct tcpcb *tp, struct tcphdr *th)
+{
uint32_t acked = 0;
acked = BYTES_ACKED(th, tp);
/*
/* Function to process an ack.
*/
void
-tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_ack_rcvd(struct tcpcb *tp, struct tcphdr *th)
+{
/*
* RFC 3465 - Appropriate Byte Counting.
*
* greater than or equal to the congestion window.
*/
- register u_int cw = tp->snd_cwnd;
- register u_int incr = tp->t_maxseg;
- int acked = 0;
+ uint32_t cw = tp->snd_cwnd;
+ uint32_t incr = tp->t_maxseg;
+ uint32_t acked = 0;
acked = BYTES_ACKED(th, tp);
- if (tcp_do_rfc3465) {
-
- if (cw >= tp->snd_ssthresh) {
- tp->t_bytes_acked += acked;
- if (tp->t_bytes_acked >= cw) {
- /* Time to increase the window. */
- tp->t_bytes_acked -= cw;
- } else {
- /* No need to increase yet. */
- incr = 0;
- }
+ if (cw >= tp->snd_ssthresh) {
+ tp->t_bytes_acked += acked;
+ if (tp->t_bytes_acked >= cw) {
+ /* Time to increase the window. */
+ tp->t_bytes_acked -= cw;
} else {
- /*
- * If the user explicitly enables RFC3465
- * use 2*SMSS for the "L" param. Otherwise
- * use the more conservative 1*SMSS.
- *
- * (See RFC 3465 2.3 Choosing the Limit)
- */
- uint32_t abc_lim;
- abc_lim = (tcp_do_rfc3465_lim2 &&
- tp->snd_nxt == tp->snd_max) ? incr * 2
- : incr;
-
- incr = lmin(acked, abc_lim);
+ /* No need to increase yet. */
+ incr = 0;
}
} else {
/*
- * If the window gives us less than ssthresh packets
- * in flight, open exponentially (segsz per packet).
- * Otherwise open linearly: segsz per window
- * (segsz^2 / cwnd per packet).
+ * If the user explicitly enables RFC3465
+ * use 2*SMSS for the "L" param. Otherwise
+ * use the more conservative 1*SMSS.
+ *
+ * (See RFC 3465 2.3 Choosing the Limit)
*/
+ uint32_t abc_lim;
+ abc_lim = (tp->snd_nxt == tp->snd_max) ? incr * 2 : incr;
- if (cw >= tp->snd_ssthresh)
- incr = max((incr * incr / cw), 1);
+ incr = ulmin(acked, abc_lim);
}
- tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale);
+ tp->snd_cwnd = min(cw + incr, TCP_MAXWIN << tp->snd_scale);
}
void
-tcp_newreno_pre_fr(struct tcpcb *tp) {
-
+tcp_newreno_pre_fr(struct tcpcb *tp)
+{
uint32_t win;
- win = min(tp->snd_wnd, tp->snd_cwnd) /
- 2 / tp->t_maxseg;
- if ( win < 2 )
+ win = min(tp->snd_wnd, tp->snd_cwnd) /
+ 2 / tp->t_maxseg;
+ if (win < 2) {
win = 2;
- tp->snd_ssthresh = win * tp->t_maxseg;
+ }
+ tp->snd_ssthresh = win * tp->t_maxseg;
tcp_cc_resize_sndbuf(tp);
-
}
void
-tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th) {
+tcp_newreno_post_fr(struct tcpcb *tp, struct tcphdr *th)
+{
int32_t ss;
- ss = tp->snd_max - th->th_ack;
+ if (th) {
+ ss = tp->snd_max - th->th_ack;
+ } else {
+ ss = tp->snd_max - tp->snd_una;
+ }
/*
* Complete ack. Inflate the congestion window to
* would be inclined to send a burst, better to do
* it via the slow start mechanism.
*
- * If the flight size is zero, then make congestion
- * window to be worth at least 2 segments to avoid
+ * If the flight size is zero, then make congestion
+ * window to be worth at least 2 segments to avoid
* delayed acknowledgement (draft-ietf-tcpm-rfc3782-bis-05).
*/
- if (ss < (int32_t)tp->snd_ssthresh)
+ if (ss < (int32_t)tp->snd_ssthresh) {
tp->snd_cwnd = max(ss, tp->t_maxseg) + tp->t_maxseg;
- else
+ } else {
tp->snd_cwnd = tp->snd_ssthresh;
+ }
tp->t_bytes_acked = 0;
}
-/* Function to change the congestion window when the retransmit
+/* Function to change the congestion window when the retransmit
* timer fires.
*/
void
-tcp_newreno_after_timeout(struct tcpcb *tp) {
+tcp_newreno_after_timeout(struct tcpcb *tp)
+{
/*
* Close the congestion window down to one segment
* (we'll open it by one segment for each ack we get).
* growth is 2 mss. We don't allow the threshhold
* to go below this.)
*/
- if (tp->t_state >= TCPS_ESTABLISHED) {
+ if (tp->t_state >= TCPS_ESTABLISHED) {
u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg;
- if (win < 2)
+ if (win < 2) {
win = 2;
+ }
tp->snd_ssthresh = win * tp->t_maxseg;
tp->snd_cwnd = tp->t_maxseg;
/*
* Indicate whether this ack should be delayed.
* We can delay the ack if:
- * - delayed acks are enabled and set to 1, same as when value is set to 2.
+ * - delayed acks are enabled and set to 1, same as when value is set to 2.
* We kept this for binary compatibility.
* - delayed acks are enabled and set to 2, will "ack every other packet"
* - if our last ack wasn't a 0-sized window.
- * - if the peer hasn't sent us a TH_PUSH data packet (this solves 3649245).
- * If TH_PUSH is set, take this as a clue that we need to ACK
- * with no delay. This helps higher level protocols who won't send
- * us more data even if the window is open because their
+ * - if the peer hasn't sent us a TH_PUSH data packet (this solves 3649245).
+ * If TH_PUSH is set, take this as a clue that we need to ACK
+ * with no delay. This helps higher level protocols who won't send
+ * us more data even if the window is open because their
* last "segment" hasn't been ACKed
- * - delayed acks are enabled and set to 3, will do "streaming detection"
+ * - delayed acks are enabled and set to 3, will do "streaming detection"
* (see the comment in tcp_input.c) and
* - if we receive more than "maxseg_unacked" full packets in the last 100ms
- * - if the connection is not in slow-start or idle or loss/recovery states
+ * - if the connection is not in slow-start or idle or loss/recovery states
* - if those criteria aren't met, it will ack every other packet.
*/
int
-tcp_newreno_delay_ack(struct tcpcb *tp, struct tcphdr *th) {
- return (tcp_cc_delay_ack(tp, th));
+tcp_newreno_delay_ack(struct tcpcb *tp, struct tcphdr *th)
+{
+ return tcp_cc_delay_ack(tp, th);
}
/* Switch to newreno from a different CC. If the connection is in
* congestion avoidance state, it can continue to use the current
* congestion window because it is going to be conservative. But
* if the connection is in slow-start, we will halve the congestion
- * window and let newreno work from there.
+ * window and let newreno work from there.
*/
void
-tcp_newreno_switch_cc(struct tcpcb *tp, uint16_t old_index) {
+tcp_newreno_switch_cc(struct tcpcb *tp, uint16_t old_index)
+{
#pragma unused(old_index)
uint32_t cwnd = min(tp->snd_wnd, tp->snd_cwnd);
if (tp->snd_cwnd >= tp->snd_ssthresh) {
cwnd = cwnd / tp->t_maxseg;
- } else {
+ } else {
cwnd = cwnd / 2 / tp->t_maxseg;
}
- tp->snd_cwnd = max(TCP_CC_CWND_INIT_BYTES, cwnd * tp->t_maxseg);
+ tp->snd_cwnd = max(tcp_initial_cwnd(tp), cwnd * tp->t_maxseg);
/* Start counting bytes for RFC 3465 again */
tp->t_bytes_acked = 0;