From owner-p4-projects@FreeBSD.ORG Fri Jul 3 18:56:04 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 90DB91065676; Fri, 3 Jul 2009 18:56:03 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4DDAA1065673 for ; Fri, 3 Jul 2009 18:56:03 +0000 (UTC) (envelope-from fangwang@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 3B6A18FC1A for ; Fri, 3 Jul 2009 18:56:03 +0000 (UTC) (envelope-from fangwang@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n63Iu3VU026042 for ; Fri, 3 Jul 2009 18:56:03 GMT (envelope-from fangwang@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n63Iu3wV026040 for perforce@freebsd.org; Fri, 3 Jul 2009 18:56:03 GMT (envelope-from fangwang@FreeBSD.org) Date: Fri, 3 Jul 2009 18:56:03 GMT Message-Id: <200907031856.n63Iu3wV026040@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to fangwang@FreeBSD.org using -f From: Fang Wang To: Perforce Change Reviews Cc: Subject: PERFORCE change 165572 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 03 Jul 2009 18:56:04 -0000 http://perforce.freebsd.org/chv.cgi?CH=165572 Change 165572 by fangwang@fangwang_utobsd on 2009/07/03 18:55:40 Tcp uto can work now. Affected files ... .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp.h#6 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_input.c#6 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_output.c#8 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_subr.c#5 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.c#9 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.h#6 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.c#6 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.h#5 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_usrreq.c#6 edit .. //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_var.h#11 edit .. //depot/projects/soc2009/tcputo/src/tools/regression/netinet/tcputo/Makefile#2 edit .. //depot/projects/soc2009/tcputo/src/tools/regression/netinet/tcputo/tcputo.c#4 edit Differences ... ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp.h#6 (text+ko) ==== @@ -154,11 +154,11 @@ #define TCP_CONGESTION 0x40 /* get/set congestion control algorithm */ #define TCP_UTO 0x80 /* set tcp user timeout */ /* Used with TCP_UTO through setsockopt and getsockopt */ -struct tcp_uto { +struct tcputo { int uto; int flags; }; -/* Values for flags in struct tcp_uto */ +/* Values for flags in struct tcputo */ #define STORE_UTO 0x01 #define ENABLE_UTO 0x02 #define ENABLE_CHANGE 0x04 ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_input.c#6 (text+ko) ==== @@ -1188,8 +1188,11 @@ /* * 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 to use it. + * optional option, we do nothing at this moment. We will + * process when we need to use it. And we need it in two + * cases: + * 1. We need do retransmission. + * 2. Users request a UTO value. */ if (to.to_flags & TOF_UTO) { tp->uto_flags |= TCPUTO_RCVD; @@ -2246,11 +2249,14 @@ } process_ACK: + /* + * If we are sending the UTO option, and we receive a ACK acknowledge the + * segment carrying the UTO option, the UTO was send successfully. So we + * stop sending the UTO option. + */ if (tp->uto_flags & TCPUTO_SENDING) - if (SEQ_GT(th->th_ack, tp->uto_carrier)) { + if (SEQ_GEQ(th->th_ack, tp->uto_carrier)) tp->uto_flags &= ~TCPUTO_SENDING; - tp->uto_flags |= TCPUTO_SENT; - } INP_INFO_LOCK_ASSERT(&V_tcbinfo); KASSERT(ti_locked == TI_RLOCKED || ti_locked == TI_WLOCKED, ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_output.c#8 (text+ko) ==== @@ -701,7 +701,7 @@ * 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 (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; @@ -710,8 +710,16 @@ /* 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) && + /* + * According to RFC 5482: + * "In addition to exchanging UTO options in the SYN segments, a + * connection that has enabled UTO options SHOULD include a UTO option + * in the first packet that does not have the SYN flag set. This helps to minimize + * the amount of state information TCP must keep for connections in non-synchronized states." + * So even though UTO options is put in SYN segment successfully, we still transmit it. + */ + if ((flags & TH_SYN) == 0 && + 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; ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_subr.c#5 (text+ko) ==== @@ -403,8 +403,8 @@ tcp_rexmit_slop = TCPTV_CPU_VAR; tcp_finwait2_timeout = TCPTV_FINWAIT2_TIMEOUT; tcp_tcbhashsize = hashsize; - tcp_uto_min = TCPTV_UTOMIN; - tcp_uto_max = TCPTV_UTOMAX; + tcp_uto_min = TCPTV_UTO_MIN; + tcp_uto_max = TCPTV_UTO_MAX; #ifdef INET6 #define TCP_MINPROTOHDR (sizeof(struct ip6_hdr) + sizeof(struct tcphdr)) @@ -740,13 +740,15 @@ tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->t_rcvtime = ticks; tp->t_bw_rtttime = ticks; + + tp->uto_flags = TCPUTO_CHANGEABLE; + if (tcp_uto_enable) + tp->uto_flags |= TCPUTO_ENABLE; /* - * 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_flags = TCPUTO_ENABLE | TCPUTO_CHANGEABLE; - tp->t_uto_adv = 64 * 4; + * According to RFC 5482, t_uto_adv is UTO option advertised to the remote TCP peer. + * It defaults to the default system-wide USER TIMEOUT. + */ + tp->t_uto_adv = TCPTV_UTO_DEFAULT; /* * 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#9 (text+ko) ==== @@ -772,7 +772,7 @@ #endif if (sc->sc_flags & SCF_SACK) tp->t_flags |= TF_SACK_PERMIT; - if (sc->sc_flags & SCF_RCVD_UTO) { + if (sc->sc_flags & SCF_UTO) { tp->uto_flags |= TCPUTO_RCVD; tp->rcv_uto = sc->sc_peer_uto; } @@ -1220,11 +1220,7 @@ sc->sc_flags |= SCF_ECN; if (to->to_flags & TOF_UTO) { sc->sc_peer_uto = to->to_uto; - sc->sc_flags |= SCF_RCVD_UTO; - } - if (uto_flags & TCPUTO_NEED) { - sc->sc_uto = snd_uto; - sc->sc_flags = SCF_NEED_UTO; + sc->sc_flags |= SCF_UTO; } if (V_tcp_syncookies) { @@ -1393,10 +1389,6 @@ if (sc->sc_flags & SCF_SIGNATURE) to.to_flags |= TOF_SIGNATURE; #endif - if (sc->sc_flags & SCF_NEED_UTO) { - to.to_uto = sc->sc_uto; - to.to_flags |= TOF_UTO; - } optlen = tcp_addoptions(&to, (u_char *)(th + 1)); ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_syncache.h#6 (text+ko) ==== @@ -70,7 +70,6 @@ u_int8_t sc_requested_s_scale:4, sc_requested_r_scale:4; 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,8 +92,7 @@ #define SCF_SIGNATURE 0x20 /* send MD5 digests */ #define SCF_SACK 0x80 /* send SACK option */ #define SCF_ECN 0x100 /* send ECN setup packet */ -#define SCF_NEED_UTO 0x200 /* send UTO option */ -#define SCF_RCVD_UTO 0x400 /* received UTO option */ +#define SCF_UTO 0x200 /* UTO option received */ #define SYNCOOKIE_SECRET_SIZE 8 /* dwords */ #define SYNCOOKIE_LIFETIME 16 /* seconds */ ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.c#6 (text+ko) ==== @@ -117,6 +117,9 @@ int tcp_uto_max; SYSCTL_PROC(_net_inet_tcp, OID_AUTO, uto_max, CTLTYPE_INT|CTLFLAG_RW, &tcp_uto_max, 0, sysctl_msec_to_ticks, "I", "Maximum user timeout"); +int tcp_uto_enable = 0; +SYSCTL_INT(_net_inet_tcp, OID_AUTO, always_enableuto, CTLFLAG_RW, + &tcp_uto_enable , 0, "Enable TCP user timeout option on all TCP connections"); static int tcp_keepcnt = TCPTV_KEEPCNT; /* max idle probes */ @@ -159,7 +162,6 @@ 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. @@ -448,26 +450,6 @@ 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) { @@ -508,6 +490,20 @@ } callout_deactivate(&tp->t_timers->tt_rexmt); tcp_free_sackholes(tp); + + if (tp->t_rxtshift == 0) { + if (tp->uto_flags & TCPUTO_ENABLE && + tp->uto_flags & TCPUTO_RCVD && + tp->uto_flags & TCPUTO_CHANGEABLE) { + u_int utoval; + TCPT_UTOGET(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_RCVD; + tp->uto_flags |= TCPUTO_IMPL; + } + tp->t_uto_left = tp->t_uto_impl / hz; + } /* * Retransmission timer went off. Message has not * been acked within retransmit interval. Back off @@ -541,17 +537,6 @@ 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_PEER_SET) == TCPUTO_PEER_SET) { - u_int utoval; - 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_PEER_SET; - tp->uto_flags |= TCPUTO_IMPL; - } - tp->t_uto_left = tp->t_uto_impl; } TCPSTAT_INC(tcps_rexmttimeo); if (tp->t_state == TCPS_SYN_SENT) @@ -559,8 +544,13 @@ else 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); + else { + int rxtshift; + rxtshift = min(TCP_MAXRXTSHIFT, tp->t_rxtshift); + tp->t_uto_left -= min(tp->t_uto_left, + min(TCP_REXMTMAX, tcp_backoff[rxtshift])); + rexmt = TCP_REXMTVAL(tp) * tcp_backoff[rxtshift]; + } TCPT_RANGESET(tp->t_rxtcur, rexmt, tp->t_rttmin, TCPTV_REXMTMAX); ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_timer.h#5 (text+ko) ==== @@ -91,8 +91,9 @@ #define TCPTV_FINWAIT2_TIMEOUT (60*hz) /* FIN_WAIT_2 timeout if no receiver */ -#define TCPTV_UTOMIN (120*hz) /* min user timeout */ -#define TCPTV_UTOMAX (720*hz) /* max user timeout */ +#define TCPTV_UTO_MIN ( 120*hz) /* min user timeout */ +#define TCPTV_UTO_MAX (1020*hz) /* max user timeout */ +#define TCPTV_UTO_DEFAULT ( 511*hz) /* default user timeout */ /* * Minimum retransmit timer is 3 ticks, for algorithmic stability. @@ -115,9 +116,9 @@ * networks faster then a modem that has minor (e.g. 1%) packet loss. */ #define TCPTV_MIN ( hz/33 ) /* minimum allowable value */ -#define TCPTV_CPU_VAR ( hz/5 ) /* cpu variance allowed (200ms) */ -#define TCPTV_REXMTMAX ( 64*hz) /* max allowable REXMT value */ - +#define TCPTV_CPU_VAR ( hz/5 ) /* cpu variance allowed (200ms) */ +#define TCPTV_REXMTMAX ( TCP_REXMTMAX*hz ) /* max allowable REXMT value */ +#define TCP_REXMTMAX 64 /* max allowable REXMT value in seconds */ #define TCPTV_TWTRUNC 8 /* RTO factor to truncate TW */ #define TCP_LINGERTIME 120 /* linger at most 2 minutes */ @@ -142,6 +143,16 @@ (tv) = (tvmax); \ } while(0) +/* +* Get user timeout value(ticks). +*/ +#define TCPT_UTOGET(utoval, uto) do { \ + (utoval) = (uto) >> 1; \ + if ((uto) & 1) \ + (utoval) *= 60; \ + (utoval) *= hz; \ +} while(0) + #ifdef _KERNEL struct tcp_timer { @@ -173,7 +184,7 @@ extern int tcp_fast_finwait2_recycle; extern int tcp_uto_min; extern int tcp_uto_max; - +extern int tcp_uto_enable; void tcp_timer_init(void); void tcp_timer_2msl(void *xtp); struct tcptw * ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_usrreq.c#6 (text+ko) ==== @@ -1256,7 +1256,7 @@ struct inpcb *inp; struct tcpcb *tp; struct tcp_info ti; - struct tcp_uto tu; + struct tcputo tu; error = 0; inp = sotoinpcb(so); @@ -1374,33 +1374,37 @@ return (error); INP_WLOCK_RECHECK(inp); + if (tu.flags & ~(ENABLE_UTO | STORE_UTO | ENABLE_CHANGE)) { + error = EINVAL; + break; + } if (tu.flags & ENABLE_UTO) tp->uto_flags |= TCPUTO_ENABLE; - if (tu.flags & STORE_UTO) + if (tu.flags & STORE_UTO) { tp->uto_flags |= TCPUTO_NEED; + if (tu.uto > 0 && tu.uto <= 0x8FFF * 60) { + if (tu.uto > 0x8FFF) { + tp->snd_uto = tu.uto / 60; + tp->snd_uto <<= 1; + tp->snd_uto |= 1; + } else { + tp->snd_uto = tu.uto; + tp->snd_uto <<= 1; + } + if (tp->uto_flags & TCPUTO_ENABLE && + tp->uto_flags & TCPUTO_NEED) { + tp->t_uto_impl = min(tcp_uto_max, + max(tu.uto * hz, tcp_uto_min)); + tp->t_uto_adv = tp->t_uto_impl; + tp->uto_flags &= ~TCPUTO_CHANGEABLE; + tp->uto_flags |= TCPUTO_IMPL; + } + } + else + error = EINVAL; + } if ( tu.flags & ENABLE_CHANGE) tp->uto_flags |= TCPUTO_CHANGEABLE; - if (tu.flags & STORE_UTO && - tu.uto > 0 && tu.uto <= 0x8FFF * 60) { - if (tu.uto > 0x8FFF) { - tp->snd_uto = tu.uto / 60; - tp->snd_uto <<= 1; - tp->snd_uto |= 1; - } else { - tp->snd_uto = tu.uto; - tp->snd_uto <<= 1; - } - if (tp->uto_flags & TCPUTO_ENABLE && - tp->uto_flags & TCPUTO_NEED) { - tp->t_uto_impl = min(tcp_uto_max, - max(tu.uto, tcp_uto_min)); - tp->t_uto_adv = tp->t_uto_impl; - tp->uto_flags &= ~TCPUTO_CHANGEABLE; - tp->uto_flags |= TCPUTO_IMPL; - } - } - else - error = EINVAL; INP_WUNLOCK(inp); break; @@ -1454,11 +1458,12 @@ if (tp->uto_flags & TCPUTO_CHANGEABLE) tu.flags |= ENABLE_CHANGE; if (tp->uto_flags & TCPUTO_ENABLE && - (tp->uto_flags & TCPUTO_PEER_SET) == TCPUTO_PEER_SET) { - TCP_UTOVAL(tu.uto, tp->rcv_uto); + tp->uto_flags & TCPUTO_RCVD && + tp->uto_flags & TCPUTO_CHANGEABLE) { + TCPT_UTOGET(tp->t_uto_impl, tp->rcv_uto); tp->t_uto_impl = min(tcp_uto_max, - max(tp->t_uto_adv, max(tu.uto, tcp_uto_min))); - tp->uto_flags &= ~TCPUTO_PEER_SET; + max(tp->t_uto_adv, max(tp->t_uto_impl, tcp_uto_min))); + tp->uto_flags &= ~TCPUTO_RCVD; tp->uto_flags |= TCPUTO_IMPL; } if (tp->uto_flags & TCPUTO_IMPL) { ==== //depot/projects/soc2009/tcputo/src/sys/netinet/tcp_var.h#11 (text+ko) ==== @@ -195,9 +195,9 @@ uint16_t rcv_uto; /* received user timeout */ uint16_t snd_uto; /* send 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 */ + u_int t_uto_adv; /* user timeout send to remote peer(ticks) */ + u_int t_uto_impl; /* implemented user timeout(ticks) */ + u_int t_uto_left; /* remained user timeout value(seconds) */ tcp_seq uto_carrier; /* max sequence number that carry user timeout */ }; @@ -250,14 +250,6 @@ #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_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 /* ==== //depot/projects/soc2009/tcputo/src/tools/regression/netinet/tcputo/Makefile#2 (text+ko) ==== @@ -1,8 +1,7 @@ # -# $FreeBSD: src/tools/regression/netinet/tcputo/Makefile,v 1.3 2009/6/28 08:47:22 ru Exp $ +# $FreeBSD: src/tools/regression/netinet/tcputo/Makefile,v 1.3 2009/6/28 08:47:22 fw Exp $ # -CFLAGS+= -Wall PROG= tcputo NO_MAN= ==== //depot/projects/soc2009/tcputo/src/tools/regression/netinet/tcputo/tcputo.c#4 (text+ko) ==== @@ -23,15 +23,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/tools/regression/netinet/tcputo/tcputo.c $ + * $FreeBSD: src/tools/regression/netinet/tcputo/tcputo.c 2009/7/4 02:54:36 fw $ */ #include #include #include -//#include -#include "tcp.h" +#include #include @@ -47,8 +46,8 @@ usage(void) { - fprintf(stderr, "tcpconnect server port\n"); - fprintf(stderr, "tcpconnect client ip port\n"); + fprintf(stderr, "tcpconnect server port [user timeout]\n"); + fprintf(stderr, "tcpconnect client ip port [user timeout]\n"); exit(-1); } @@ -82,8 +81,9 @@ long port; int user_timeout; int optval; + struct tcputo uto; - if (argc != 1) + if (argc != 1 && argc != 2) usage(); bzero(&sin, sizeof(sin)); @@ -99,10 +99,10 @@ listen_sock = socket(PF_INET, SOCK_STREAM, 0); if (listen_sock == -1) err(-1, "socket"); - optval = 150; - /*if (setsockopt(listen_sock, IPPROTO_TCP, TCP_UTO, &optval, sizeof(optval)) == -1) + optval = 1; + if (setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) err(-1, "setsockopt"); -*/ + if (bind(listen_sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) err(-1, "bind"); @@ -110,10 +110,17 @@ err(-1, "listen"); accept_sock = accept(listen_sock, NULL, NULL); - close(listen_sock); optval = 4*1024; if (setsockopt(accept_sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == -1) err(-1, "setsockopt"); + uto.flags = ENABLE_UTO; + if (argc == 2) { + uto.uto = atoi(argv[1]); + uto.flags |= STORE_UTO; + } + if (setsockopt(accept_sock, IPPROTO_TCP, TCP_UTO, &uto, sizeof(uto)) == -1) + err(-1, "setsockopt"); + close(listen_sock); while(1) { sleep(1); printf("server again %d\n", optval++); @@ -142,8 +149,9 @@ int sock; int user_timeout; int optval = 4*1024; + struct tcputo uto; - if (argc != 2) + if (argc != 2 && argc != 3) usage(); bzero(&sin, sizeof(sin)); @@ -162,19 +170,13 @@ err(-1, "socket"); if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == -1) err(-1, "setsockopt"); - optval = 150; -/* if (setsockopt(sock, IPPROTO_TCP, TCP_UTO, &optval, sizeof(optval)) == -1) - err(-1, "setsockopt"); -*/ - /* No warning in default case on ENOPROTOOPT. */ - /* if (setsockopt(sock, IPPROTO_TCP, TCP_MD5SIG, - &md5enable, sizeof(md5enable)) != 0) { - if (errno == ENOPROTOOPT && md5enable > 0) - err(-1, "setsockopt(TCP_MD5SIG)"); - else if (errno != ENOPROTOOPT) - warn("setsockopt(TCP_MD5SIG)"); - } */ - + + if (argc == 3) { + uto.uto = atoi(argv[2]); + uto.flags = ENABLE_UTO | STORE_UTO; + if (setsockopt(sock, IPPROTO_TCP, TCP_UTO, &uto, sizeof(uto)) == -1) + err(-1, "setsockopt"); + } if (connect(sock, (struct sockaddr *)&sin, sizeof(sin)) == -1) err(-1, "connect");