/*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2012 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
#include <kern/cpu_number.h> /* before tcp_seq.h, for tcp_random18() */
#include <net/route.h>
+#include <net/if_var.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
int timer;
{
register int rexmt;
- struct socket *so_tmp;
+ struct socket *so;
struct tcptemp *t_template;
int optlen = 0;
int idle_time = 0;
int isipv6 = (tp->t_inpcb->inp_vflag & INP_IPV4) == 0;
#endif /* INET6 */
- so_tmp = tp->t_inpcb->inp_socket;
+ so = tp->t_inpcb->inp_socket;
idle_time = tcp_now - tp->t_rcvtime;
switch (timer) {
* to a longer retransmit interval and retransmit one segment.
*/
case TCPT_REXMT:
- tcp_free_sackholes(tp);
/* Drop a connection in the retransmit timer
* 1. If we have retransmitted more than TCP_MAXRXTSHIFT times
* 2. If the time spent in this retransmission episode is more than
tcpstat.tcps_timeoutdrop++;
}
tp->t_rxtshift = TCP_MAXRXTSHIFT;
+ postevent(so, 0, EV_TIMEOUT);
+ soevent(so,
+ (SO_FILT_HINT_LOCKED|SO_FILT_HINT_TIMEOUT));
tp = tcp_drop(tp, tp->t_softerror ?
tp->t_softerror : ETIMEDOUT);
- postevent(so_tmp, 0, EV_TIMEOUT);
+
break;
}
tp->rxt_start = tcp_now;
}
tcpstat.tcps_rexmttimeo++;
+
if (tp->t_state == TCPS_SYN_SENT)
rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
else
TCP_ADD_REXMTSLOP(tp));
tp->t_timer[TCPT_REXMT] = OFFSET_FROM_START(tp, tp->t_rxtcur);
+ if (INP_WAIT_FOR_IF_FEEDBACK(tp->t_inpcb))
+ goto fc_output;
+
+ tcp_free_sackholes(tp);
/*
* Check for potential Path MTU Discovery Black Hole
*/
if (tcp_pmtud_black_hole_detect && (tp->t_state == TCPS_ESTABLISHED)) {
- if (((tp->t_flags & (TF_PMTUD|TF_MAXSEGSNT)) == (TF_PMTUD|TF_MAXSEGSNT)) && (tp->t_rxtshift == 2)) {
+ if (((tp->t_flags & (TF_PMTUD|TF_MAXSEGSNT)) == (TF_PMTUD|TF_MAXSEGSNT)) &&
+ (tp->t_rxtshift == 2)) {
/*
* Enter Path MTU Black-hole Detection mechanism:
* - Disable Path MTU Discovery (IP "DF" bit).
if ((tp->t_state == TCPS_SYN_SENT) &&
(tp->t_rxtshift == tcp_broken_peer_syn_rxmit_thres))
tp->t_flags &= ~(TF_REQ_SCALE|TF_REQ_TSTMP|TF_REQ_CC);
+
/*
* If losing, let the lower level know and try for
* a better route. Also, if we backed off this far,
tp->t_dupacks = 0;
EXIT_FASTRECOVERY(tp);
+ /* CWR notifications are to be sent on new data right after
+ * RTOs, Fast Retransmits and ECE notification receipts.
+ */
+ if ((tp->ecn_flags & TE_ECN_ON) == TE_ECN_ON) {
+ tp->ecn_flags |= TE_SENDCWR;
+ }
+fc_output:
DTRACE_TCP5(cc, void, NULL, struct inpcb *, tp->t_inpcb,
struct tcpcb *, tp, struct tcphdr *, NULL,
int32_t, TCP_CC_REXMT_TIMEOUT);
if ((tp->t_rxtshift == TCP_MAXRXTSHIFT &&
(idle_time >= tcp_maxpersistidle ||
idle_time >= TCP_REXMTVAL(tp) * tcp_totbackoff)) ||
- ((tp->t_persist_stop != 0) && (tp->t_persist_stop <= tcp_now))) {
+ ((tp->t_persist_stop != 0) &&
+ TSTMP_LEQ(tp->t_persist_stop, tcp_now))) {
tcpstat.tcps_persistdrop++;
- so_tmp = tp->t_inpcb->inp_socket;
+ postevent(so, 0, EV_TIMEOUT);
+ soevent(so,
+ (SO_FILT_HINT_LOCKED|SO_FILT_HINT_TIMEOUT));
tp = tcp_drop(tp, ETIMEDOUT);
- postevent(so_tmp, 0, EV_TIMEOUT);
break;
}
tcp_setpersist(tp);
unsigned int ifscope, nocell = 0;
if (tp->t_inpcb->inp_flags & INP_BOUND_IF)
- ifscope = tp->t_inpcb->inp_boundif;
+ ifscope = tp->t_inpcb->inp_boundifp->if_index;
else
ifscope = IFSCOPE_NONE;
if ((tp->t_flags & TF_STRETCHACK) != 0)
tcp_reset_stretch_ack(tp);
+ /* If we are measuring inter packet arrival jitter for
+ * throttling a connection, this delayed ack might be
+ * the reason for accumulating some jitter. So let's
+ * restart the measurement.
+ */
+ CLEAR_IAJ_STATE(tp);
+
tcpstat.tcps_delack++;
(void) tcp_output(tp);
}
#endif
dropit:
tcpstat.tcps_keepdrops++;
+ postevent(so, 0, EV_TIMEOUT);
+ soevent(so,
+ (SO_FILT_HINT_LOCKED|SO_FILT_HINT_TIMEOUT));
tp = tcp_drop(tp, ETIMEDOUT);
- postevent(so_tmp, 0, EV_TIMEOUT);
break;
}
return (tp);