Date: Mon, 15 Jun 2009 13:42:57 GMT From: Fang Wang <fangwang@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 164426 for review Message-ID: <200906151342.n5FDgvPu020815@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=164426 Change 164426 by fangwang@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906151342.n5FDgvPu020815>