PERFORCE change 164426 for review
Fang Wang
fangwang at FreeBSD.org
Mon Jun 15 13:42:59 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164426
Change 164426 by fangwang at fangwang_utobsd on 2009/06/15 13:42:34
Finish basic function. Hope it can work. There still are many details needs to modify according to RFC5482.
Affected files ...
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_input.c#4 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_output.c#6 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_subr.c#4 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.c#4 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.h#4 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.c#3 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.h#4 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_usrreq.c#2 edit
.. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_var.h#9 edit
Differences ...
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_input.c#4 (text+ko) ====
@@ -1187,6 +1187,16 @@
(thflags & TH_SYN) ? TO_SYN : 0);
/*
+ * If TCP user timeout option is received, because it's an
+ * optional option, we do nothing at this moment. And we will
+ * process when we need retransmission in synchronized states.
+ */
+ if (to.to_flags & TOF_UTO) {
+ tp->uto_flags |= TCPUTO_RCVD;
+ tp->rcv_uto = to.to_uto;
+ }
+
+ /*
* If echoed timestamp is later than the current time,
* fall back to non RFC1323 RTT calculation. Normalize
* timestamp if syncookies were used when this connection
@@ -1197,6 +1207,12 @@
if (TSTMP_GT(to.to_tsecr, ticks))
to.to_tsecr = 0;
}
+ if (tp->uto_flags & TCPUTO_SENDING)
+ if (th->th_ack > tp->uto_carrier) {
+ tp->uto_flags &= ~TCPUTO_SENDING;
+ tp->uto_flags |= TCPUTO_SENT;
+ }
+
/*
* Process options only when we get SYN/ACK back. The SYN case
@@ -1226,10 +1242,6 @@
if ((tp->t_flags & TF_SACK_PERMIT) &&
(to.to_flags & TOF_SACKPERM) == 0)
tp->t_flags &= ~TF_SACK_PERMIT;
- if (to.to_flags & TOF_UTO) {
- tp->t_flags |= TF_RCVD_UTO;
- tp->rcv_uto = to.to_uto;
- }
}
/*
@@ -2952,7 +2964,7 @@
continue;
to->to_flags |= TOF_UTO;
bcopy((char *)cp + 2,
- (char *)&to->to_uto, sizeof(uto_load));
+ (char *)&to->to_uto, sizeof(to->to_uto));
to->to_uto = ntohs(to->to_uto);
break;
default:
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_output.c#6 (text+ko) ====
@@ -696,9 +696,27 @@
if (tp->t_flags & TF_SIGNATURE)
to.to_flags |= TOF_SIGNATURE;
#endif /* TCP_SIGNATURE */
+ /*
+ * We put UTO option in tcp header in two case: the segment
+ * is a SYN or SYN | ACK segment, or the segment is a normal
+ * data segment.
+ */
+ if (flags & TH_SYN || (len && (tp->t_flags & ~TF_FORCEDATA) == 0))
+ if (tp->uto_flags & (TCPUTO_NEED | TCPUTO_SENDING)) {
+ to.to_uto = tp->snd_uto;
+ to.to_flags |= TOF_UTO;
+ }
/* Processing the options. */
hdrlen += optlen = tcp_addoptions(&to, opt);
+
+ /* Check whether we place UTO in TCP header successfully */
+ if (tp->uto_flags & (TCPUTO_NEED | TCPUTO_SENDING) &&
+ (to.to_flags & TOF_UTO) == 0) {
+ tp->uto_flags &= ~(TCPUTO_NEED | TCPUTO_SENDING);
+ tp->uto_flags |= TCPUTO_SENDING;
+ tp->uto_carrier = tp->snd_nxt + len;
+ }
}
#ifdef INET6
@@ -1327,8 +1345,11 @@
* we only have 10 bytes for SACK options (40 - (12 + 18)).
*
* There is a new tcp option UTO (user timeout, defined in RFC 5482), the
- * UTO option is a optional option. So we attach the UTO option only when
- * there are enough free space in the TCP header.
+ * UTO option is an optional option. So we attach the UTO option only when
+ * there are enough free space in the TCP header. Although UTO is optional,
+ * we still should try our best to transmit it, so we need some way to
+ * notify whether UTO was placed into TCP header. We do this through remove
+ * TOF_UTO bit from to_flags.
*/
int
tcp_addoptions(struct tcpopt *to, u_char *optp)
@@ -1453,6 +1474,7 @@
optlen += TCPOLEN_UTO;
bcopy((u_char *)&to->to_uto, optp, sizeof(to->to_uto));
optp += sizeof(to->to_uto);
+ to->to_flags &= ~TOF_UTO;
break;
}
default:
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_subr.c#4 (text+ko) ====
@@ -741,11 +741,12 @@
tp->t_rcvtime = ticks;
tp->t_bw_rtttime = ticks;
/*
- * Init TCP user timeout (RFC5482) variables. We don't use UTO by default,
- * but we make it available if a UTO request received or set it through
+ * Init TCP user timeout (RFC5482) variables. We don't enable UTO by default,
+ * but we make it available if a UTO request is received or set through
* setsockopt system call.
*/
- tp->uto_flag = UTO_ENABLE | UTO_CHANGEABLE
+ tp->uto_flags = TCPUTO_ENABLE | TCPUTO_CHANGEABLE;
+ tp->t_uto_adv = 64 * 4;
/*
* IPv4 TTL initialization is necessary for an IPv6 socket as well,
* because the socket may be bound to an IPv6 wildcard address,
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.c#4 (text+ko) ====
@@ -772,9 +772,13 @@
#endif
if (sc->sc_flags & SCF_SACK)
tp->t_flags |= TF_SACK_PERMIT;
- if (sc->sc_flags & SCF_UTO) {
- tp->t_flags |= TF_RCVD_UTO;
- tp->rcv_uto = sc->sc_uto;
+ if (sc->sc_flags & SCF_RCVD_UTO) {
+ tp->uto_flags |= TCPUTO_RCVD;
+ tp->rcv_uto = sc->sc_peer_uto;
+ }
+ if (sc->sc_flags & SCF_SENT_UTO) {
+ tp->uto_flags |= TCPUTO_SENT;
+ tp->snd_uto = sc->sc_uto;
}
}
@@ -1214,8 +1218,12 @@
if ((th->th_flags & (TH_ECE|TH_CWR)) && V_tcp_do_ecn)
sc->sc_flags |= SCF_ECN;
if (to->to_flags & TOF_UTO) {
- sc->sc_uto = to->to_uto;
- sc->sc_flags |= SCF_UTO;
+ sc->sc_peer_uto = to->to_uto;
+ sc->sc_flags |= SCF_RCVD_UTO;
+ }
+ if (tp->uto_flags & TCPUTO_NEED) {
+ sc->sc_uto = tp->snd_uto;
+ sc->sc_flags = SCF_UTO;
}
if (V_tcp_syncookies) {
@@ -1390,6 +1398,11 @@
}
optlen = tcp_addoptions(&to, (u_char *)(th + 1));
+ if ((to->to_flags & TOF_UTO) == 0 &&
+ (sc->sc_flags & SCF_UTO) == 1) {
+ sc->sc_flags &= ~SCF_UTO;
+ sc->sc_flags |= SCF_SENT_UTO;
+ }
/* Adjust headers by option size. */
th->th_off = (sizeof(struct tcphdr) + optlen) >> 2;
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.h#4 (text+ko) ====
@@ -69,7 +69,8 @@
u_int8_t sc_ip_tos; /* IPv4 TOS */
u_int8_t sc_requested_s_scale:4,
sc_requested_r_scale:4;
- u_int16_t sc_uto; /* user timeout */
+ u_int16_t sc_peer_uto; /* peer's user timeout */
+ u_int16_t sc_uto; /* our user timeout to send */
u_int16_t sc_flags;
#ifndef TCP_OFFLOAD_DISABLE
struct toe_usrreqs *sc_tu; /* TOE operations */
@@ -93,6 +94,8 @@
#define SCF_SACK 0x80 /* send SACK option */
#define SCF_ECN 0x100 /* send ECN setup packet */
#define SCF_UTO 0x200 /* send UTO option */
+#define SCF_RCVD_UTO 0x400 /* received UTO option */
+#define SCF_SENT_UTO 0x800 /* send UTO option successfully */
#define SYNCOOKIE_SECRET_SIZE 8 /* dwords */
#define SYNCOOKIE_LIFETIME 16 /* seconds */
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.c#3 (text+ko) ====
@@ -159,6 +159,8 @@
SYSCTL_INT(_net_inet_tcp, OID_AUTO, timer_race, CTLFLAG_RD, &tcp_timer_race,
0, "Count of t_inpcb races on tcp_discardcb");
+static int tcp_timer_uto_interval(struct tcpcb *);
+
/*
* TCP timer processing.
*/
@@ -445,7 +447,25 @@
INP_INFO_WUNLOCK(&V_tcbinfo);
CURVNET_RESTORE();
}
+static int
+tcp_timer_uto_interval(struct tcpcb *tp)
+{
+ int rxtcur;
+ int rxttimes;
+ int rexmt;
+ int interval;
+
+ rxttimes = min(TCP_MAXRXTSHIFT, tp->t_rxtshift);
+ rexmt = TCP_REXMTVAL(tp) * tcp_backoff[rxttimes];
+ TCPT_RANGESET(rxtcur, rexmt, tp->t_rttmin, TCPTV_REXMTMAX);
+ interval = rxtcur / TCP_REXMTVAL(tp);
+ if (tp->t_uto_left - interval < 0)
+ interval = tp->t_uto_left;
+ tp->t_uto_left -= interval;
+
+ return (interval);
+}
void
tcp_timer_rexmt(void * xtp)
{
@@ -491,7 +511,8 @@
* been acked within retransmit interval. Back off
* to a longer retransmit interval and retransmit one segment.
*/
- if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) {
+ if ((++tp->t_rxtshift > TCP_MAXRXTSHIFT && (tp->uto_flags & TCPUTO_IMPL) == 0) ||
+ (tp->t_uto_left == 0 && tp->uto_flags & TCPUTO_IMPL) {
tp->t_rxtshift = TCP_MAXRXTSHIFT;
TCPSTAT_INC(tcps_timeoutdrop);
tp = tcp_drop(tp, tp->t_softerror ?
@@ -518,12 +539,31 @@
else
tp->t_flags &= ~TF_WASFRECOVERY;
tp->t_badrxtwin = ticks + (tp->t_srtt >> (TCP_RTT_SHIFT + 1));
+
+ if (tp->uto_flags & TCPUTO_ENABLE && (tp->uto_flags & TCPUTO_SET ||
+ (tp->uto_flags & TCPUTO_PEER_SET) == TCPUTO_PEER_SET)) {
+ u_int utoval;
+ if (tp->uto_flags & TCPUTO_SET) {
+ TCP_UTOVAL(utoval, tp->snd_uto);
+ tp->t_uto_impl = min(tcp_uto_min, max(utoval, tcp_uto_max));
+ } else {
+ TCP_UTOVAL(utoval, tp->rcv_uto);
+ tp->t_uto_impl = min(tcp_uto_max,
+ max(tp->t_uto_adv, max(utoval, tcp_uto_min)));
+ }
+ tp->uto_flags |= TCPUTO_IMPL;
+ }
+ tp->t_uto_left = tp->t_uto_impl;
}
TCPSTAT_INC(tcps_rexmttimeo);
if (tp->t_state == TCPS_SYN_SENT)
rexmt = TCP_REXMTVAL(tp) * tcp_syn_backoff[tp->t_rxtshift];
else
- rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
+ if ((tp->uto_flags & TCPUTO_IMPL) == 0)
+ rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift];
+ else
+ rexmt = TCP_REXMTVAL(tp) * tcp_timer_uto_interval(tp);
+
TCPT_RANGESET(tp->t_rxtcur, rexmt,
tp->t_rttmin, TCPTV_REXMTMAX);
/*
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.h#4 (text+ko) ====
@@ -171,6 +171,8 @@
extern int tcp_finwait2_timeout;
extern int tcp_fast_finwait2_recycle;
+extern int tcp_uto_min;
+extern int tcp_uto_max;
void tcp_timer_init(void);
void tcp_timer_2msl(void *xtp);
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_usrreq.c#2 (text+ko) ====
@@ -1365,6 +1365,33 @@
error = EINVAL;
break;
+ case TCP_UTO:
+ INP_WUNLOCK(inp);
+ error = sooptcopyin(sopt, &optval, sizeof optval,
+ sizeof optval);
+ if (error)
+ return (error);
+
+ INP_WLOCK_RECHECK(inp);
+ if (optval > 0 && optval <= 0x8FFF * 60) {
+ if (optval > 0x8FFF) {
+ tp->snd_uto = optval / 60;
+ tp->snd_uto <<= 1;
+ tp->snd_uto |= 1;
+ } else {
+ tp->snd_uto = optval;
+ tp->snd_uto <<= 1;
+ }
+ tp->t_uto_adv = optval;
+ tp->uto_flags |= TCPUTO_NEED;
+ tp->uto_flags |= TCPUTO_ENABLE;
+ tp->uto_flags &= ~TCPUTO_CHANGEABLE;
+ }
+ else
+ error = EINVAL;
+ INP_WUNLOCK(inp);
+ break;
+
default:
INP_WUNLOCK(inp);
error = ENOPROTOOPT;
==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_var.h#9 (text+ko) ====
@@ -194,11 +194,11 @@
/* user timeout variables (RFC 5482) */
uint16_t rcv_uto; /* received user timeout */
uint16_t snd_uto; /* send user timeout */
- uint8_t uto_flag;
-#define UTO_ENABLE 0x01
-#define UTO_CHANGEABLE 0x02
-#define UTO_IMPL 0x04
- u_int t_impl_uto; /* implemented user timeout */
+ uint8_t uto_flags;
+ u_int t_uto_adv;
+ u_int t_uto_impl; /* implemented user timeout */
+ u_int t_uto_left; /* remained user timeout value */
+ tcp_seq uto_carrier; /* max sequence number that carry user timeout */
};
/*
@@ -230,8 +230,6 @@
#define TF_ECN_PERMIT 0x4000000 /* connection ECN-ready */
#define TF_ECN_SND_CWR 0x8000000 /* ECN CWR in queue */
#define TF_ECN_SND_ECE 0x10000000 /* ECN ECE in queue */
-#define TF_RCVD_UTO 0x20000000 /* a user timeout was received */
-#define TF_NEEDUTO 0x40000000 /* send user timeout */
#define IN_FASTRECOVERY(tp) (tp->t_flags & TF_FASTRECOVERY)
#define ENTER_FASTRECOVERY(tp) tp->t_flags |= TF_FASTRECOVERY
@@ -243,6 +241,25 @@
#define TCPOOB_HAVEDATA 0x01
#define TCPOOB_HADDATA 0x02
+/*
+ * Flags for the uto_flags field.
+ */
+#define TCPUTO_ENABLE 0x01 /* enable tcp user timeout */
+#define TCPUTO_CHANGEABLE 0x02 /* user timeout can be changed by other side */
+#define TCPUTO_IMPL 0x04 /* implement user timeout */
+#define TCPUTO_RCVD 0x08 /* other side has requested user timeout */
+#define TCPUTO_NEED 0x10 /* user timeout need to be sent */
+#define TCPUTO_SENDING 0x20 /* user timeout is in the process of sending */
+#define TCPUTO_SENT 0x40 /* user timeout is sent successfully */
+#define TCPUTO_SET (TCPUTO_NEED | TCPUTO_SENDING | TCPUTO_SENT)
+#define TCPUTO_PEER_SET (TCPUTO_CHANGEABLE | TCPUTO_RCVD)
+
+#define TCP_UTOVAL(utoval, uto) do { \
+ (utoval) = (uto) >> 1; \
+ if ((uto) & 1) \
+ (utoval) *= 60; \
+} while(0)
+
#ifdef TCP_SIGNATURE
/*
* Defines which are needed by the xform_tcp module and tcp_[in|out]put
More information about the p4-projects
mailing list