Date: Sun, 24 Jul 2011 14:17:52 GMT From: Catalin Nicutar <cnicutar@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 196633 for review Message-ID: <201107241417.p6OEHqPO056697@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@196633?ac=10 Change 196633 by cnicutar@cnicutar_cronos on 2011/07/24 14:17:31 Add IPv6 support to UTO tests and cleanup. Affected files ... .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/long_uto.c#2 edit .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/runtest.sh#2 edit .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/send_uto.c#2 edit .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/short_uto.c#2 edit .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/test_utils.c#2 edit .. //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/test_utils.h#2 edit Differences ... ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/long_uto.c#2 (text+ko) ==== @@ -1,7 +1,6 @@ #include <sys/wait.h> #include <err.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sysexits.h> @@ -9,10 +8,6 @@ #include "test_utils.h" -#define CLIENT_ADDR "192.0.2.2" -#define SERVER_ADDR "192.0.2.3" -#define PORT 1296 - #define UTO 20*60 /* 20 minutes UTO. */ #define DOWNTIME 5*60 /* 5 minutes of network downtime. */ #define WAITTIME 7*60 /* Waiting 7 minutes. */ @@ -26,12 +21,21 @@ * The test passes if the server exits normally (the second write succeeds). */ int -main(void) +main(int argc, char *argv[]) { int status; + char *caddr, *saddr, *port; pid_t server; pid_t client; + if (argc != 4) + errx(EX_USAGE, "Usage: %s client_addr server_addr port", + argv[0]); + + caddr = argv[1]; + saddr = argv[2]; + port = argv[3]; + if(getuid()) errx(EX_USAGE, "Only root may run this test"); @@ -41,8 +45,7 @@ err(EX_OSERR, "fork"); break; case 0: - server_disconnect(SERVER_ADDR, PORT, CLIENT_ADDR, DOWNTIME, - UTO, 1); + server_disconnect(saddr, port, caddr, DOWNTIME, UTO, 1); exit(EX_OK); break; } @@ -56,14 +59,14 @@ err(EX_OSERR, "fork"); break; case 0: - client_generic(CLIENT_ADDR, SERVER_ADDR, PORT, 0, 1); + client_generic(caddr, saddr, port, 0, 1); exit(EX_OK); break; } sleep(WAITTIME); - /* Wait server. The test passes if the server exits normlly (which + /* Wait server. The test passes if the server exits normally (which * means the second write completed successfully). */ if (waitpid(server, &status, WNOHANG) <= 0) ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/runtest.sh#2 (text+ko) ==== @@ -10,41 +10,46 @@ # Create two loopback interfaces and assign example addresses lo_up() { + # Just in case they are still around lo_down ifconfig lo2 create ifconfig lo3 create - - ifconfig lo2 192.0.2.2 netmask 255.255.255.255 mtu 1500 up - ifconfig lo3 192.0.2.3 netmask 255.255.255.255 mtu 1500 up + + if [ -n "$ipv6" ] + then + ifconfig lo2 inet6 "$1/128" mtu 1500 up + ifconfig lo3 inet6 "$2/128" mtu 1500 up + else + ifconfig lo2 "$1/32" mtu 1500 up + ifconfig lo3 "$2/32" mtu 1500 up + fi } -# Run a test and display results -runtest() +needroot() { - no=$1 # Test number - name=$2 # Test name - needroot=$3 # Does the test need root ? - - killall "$name" > /dev/null 2>&1 - - if [ -n "$needroot" ] && [ $(id -u) -ne 0 ] + if [ $(id -u) -ne 0 ] then echo "not ok $no - $name # Only root may run this test" exit 1 fi +} + +# Run a test and display results +runtest() +{ + args=$1 # Test arguments - # Create loopback interfaces - lo_up > /dev/null 2>&1 + killall "$bin" > /dev/null 2>&1 - if ! make -f "Makefile.${name}" > /dev/null 2>&1 + if ! make -f "Makefile.${bin}" > /dev/null 2>&1 then echo "not ok $no - $name # make failed" exit 1 fi # Finally run the test - if ./$name > /dev/null 2>&1 + if ./$bin > /dev/null 2>&1 $args then echo "ok $no - $name" else @@ -53,12 +58,58 @@ lo_down > /dev/null 2>&1 } +test_with_loopback() +{ + lo1=$1 + lo2=$2 + # Make sure we run as root + needroot -case "$1" in - "1") runtest "$1" send_uto ;; - "2") runtest "$1" short_uto 1 ;; - "3") runtest "$1" long_uto 1 ;; + # Create loopback interfaces + lo_up $lo1 $lo2 > /dev/null 2>&1 + + # Run the atual test + runtest "$lo1 $lo2 $PORT" + + # Destroy loopback interfaces + lo_down > /dev/null 2>&1 +} + +PORT="1296" + +no=$1 +case "$no" in + "1") + name="Send UTO" + bin="send_uto" + addr="127.0.0.1" + + runtest "$addr $PORT" + ;; + "2") + name="short_uto" + bin="short_uto" + client="192.0.2.2" + server="192.0.2.3" + + test_with_loopback $client $server + ;; + "3") + name="long_uto" + bin="long_uto" + client="192.0.2.2" + server="192.0.2.3" + + test_with_loopback $client $server + ;; + "4") + name="send_uto_ipv6" + bin="send_uto" + addr="127.0.0.1" + + runtest "$addr $PORT" + ;; esac ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/send_uto.c#2 (text+ko) ==== @@ -3,7 +3,6 @@ #include <sys/wait.h> #include <err.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sysexits.h> @@ -12,9 +11,6 @@ #include "test_utils.h" -#define ADDR "127.0.0.1" -#define PORT 1296 - #define SERVER_UTO 1600 #define CLIENT_UTO 1200 #define WAITTIME 5 @@ -25,7 +21,7 @@ * Send new UTO and tests again the received UTO. */ static void -server() +server(char *addr, char *port) { int listen_sock; int sock; @@ -35,7 +31,7 @@ int send_uto, recv_uto; /* Bind and start listening. */ - listen_sock = listen_socket(ADDR, PORT, SERVER_UTO, 1); + listen_sock = listen_uto(addr, port, SERVER_UTO, 1); sock = accept(listen_sock, NULL, NULL); if (sock < 0) @@ -70,7 +66,7 @@ * Exchanges data and tests the received value again. */ static void -client() +client(char *addr, char *port) { int sock; static char buf[6000]; @@ -78,7 +74,7 @@ int send_uto, recv_uto; /* Connect to the server, with the specified UTO values. */ - sock = connect_socket(ADDR, ADDR, PORT, CLIENT_UTO, 1); + sock = connect_uto(addr, addr, port, CLIENT_UTO, 1); /* See what the server sent. */ uto_get(sock, &send_uto, &recv_uto); @@ -112,16 +108,23 @@ */ int -main(void) +main(int argc, char *argv[]) { int status; + char *addr, *port; + + if (argc != 3) + errx(EX_USAGE, "Usage: %s address port", argv[0]); + + addr = argv[1]; + port = argv[2]; switch(fork()) { case -1: err(EX_OSERR, "fork"); break; case 0: - server(); + server(addr, port); exit(EX_OK); break; } @@ -134,7 +137,7 @@ err(EX_OSERR, "fork"); break; case 0: - client(); + client(addr, port); exit(EX_OK); break; } ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/short_uto.c#2 (text+ko) ==== @@ -1,7 +1,6 @@ #include <sys/wait.h> #include <err.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <sysexits.h> @@ -9,10 +8,6 @@ #include "test_utils.h" -#define CLIENT_ADDR "192.0.2.2" -#define SERVER_ADDR "192.0.2.3" -#define PORT 1296 - #define UTO 10 /* 10 seconds UTO. */ #define DOWNTIME 20 /* 20 seconds of network downtime. */ #define WAITTIME 40 /* Waiting 40 seconds. */ @@ -29,12 +24,21 @@ * The test passes if the server exits abnormally with EX_IOERR. */ int -main(void) +main(int argc, char *argv[]) { int status; + char *caddr, *saddr, *port; pid_t server; pid_t client; + if (argc != 4) + errx(EX_USAGE, "Usage: %s client_addr server_addr port", + argv[0]); + + caddr = argv[1]; + saddr = argv[2]; + port = argv[3]; + /* Changing a network flag requires root. */ if(getuid()) errx(EX_USAGE, "Only root may run this test"); @@ -45,8 +49,7 @@ err(EX_OSERR, "fork"); break; case 0: - server_disconnect(SERVER_ADDR, PORT, CLIENT_ADDR, DOWNTIME, - UTO, 1); + server_disconnect(saddr, port, caddr, DOWNTIME, UTO, 1); exit(EX_OK); break; } @@ -60,12 +63,11 @@ err(EX_OSERR, "fork"); break; case 0: - client_generic(CLIENT_ADDR, SERVER_ADDR, PORT, 0, 1); + client_generic(caddr, saddr, port, 0, 1); exit(EX_OK); break; } - /* Allow connection to run. */ sleep(WAITTIME); /* @@ -77,6 +79,7 @@ exit(-1); if (WIFEXITED(status) && WEXITSTATUS(status) == EX_IOERR) exit(EX_OK); - + + printf("Here\n"); return -1; } ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/test_utils.c#2 (text+ko) ==== @@ -3,12 +3,10 @@ #include <netinet/in.h> #include <netinet/tcp.h> -#include <arpa/inet.h> #include <err.h> #include <errno.h> -#include <fcntl.h> -#include <pthread.h> +#include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -21,33 +19,86 @@ /* * Bind a socket to an address, using the SO_REUSEADDR socket option. */ -void -tcp_bind(int s, char *addr, int port) +int tcp_bind(char *addr, char *port) { - struct sockaddr_in sin; - int optval; + int s, rc, yes = 1; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(hints)); + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; /* Both v4 and v6.*/ + hints.ai_flags = AI_PASSIVE; + + /* Address lookup. */ + rc = getaddrinfo(addr, port, &hints, &result); + if (rc) + return -1; + + /* Loop until we can bind to something. */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (s == -1) + /* Try another result. */ + continue; - sin.sin_port = htons(port); - sin.sin_family = AF_INET; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes, + sizeof(yes))) { + close(s); + freeaddrinfo(result); + return -1; + } - if (NULL != addr && strlen(addr)) { - int rc; - rc = inet_pton(AF_INET, addr, &sin.sin_addr); - if (rc < 0) - err(EX_DATAERR, "inet_pton"); - if (rc == 0) - errx(EX_DATAERR, "inet_pton can't parse `%s'", addr); + if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) + /* Return bound socket. */ + break; + + /* Couldn't bind; try another result. */ + close(s); } + freeaddrinfo(result); - optval = 1; - if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))) - err(EX_UNAVAILABLE, "setsockopt"); + return (rp == NULL) ? -1 : s; +} + + +int tcp_connect(int s, char *addr, char *port) +{ + int rc; + struct addrinfo hints; + struct addrinfo *result, *rp; + + memset(&hints, 0, sizeof(hints)); + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; /* Both v4 and v6.*/ + + /* Look up address. */ + rc = getaddrinfo(addr, port, &hints, &result); + if (rc) + return -1; + + /* Search for a suitable combination. */ + for (rp = result; rp != NULL; rp = rp->ai_next) { + if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) + /* Done connect, break. */ + break; + + /* Connect failed; trying next entry. */ + } + freeaddrinfo(result); - if (bind(s, (struct sockaddr *)&sin, sizeof(sin))) - err(EX_UNAVAILABLE, "bind"); + return (rp == NULL) ? -1 : s; } + + /* * Set UTO values on a socket. */ @@ -84,16 +135,14 @@ * Create a socket, set UTO values, bind it locally, start listening. */ int -listen_socket(char *listen_addr, int port, int send_uto, int recv_uto) +listen_uto(char *laddr, char *port, int send_uto, int recv_uto) { int s; - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s <= 0) - err(EX_OSERR, "socket"); - + + s = tcp_bind(laddr, port); + if (s < 0) + err(EX_UNAVAILABLE, "tcp_bind"); uto_set(s, send_uto, recv_uto); - tcp_bind(s, listen_addr, port); if(listen(s, -1)) err(EX_UNAVAILABLE, "listen"); @@ -104,31 +153,26 @@ * Create a socket, set UTO values, bind it locally and attempt to connect. */ int -connect_socket(char *local_addr, char *remote_addr, int remote_port, - int send_uto, int recv_uto) +connect_uto(char *laddr, char *raddr, char *rport, int send_uto, int recv_uto) { int s; - struct sockaddr_in sin; - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s <= 0) - err(EX_OSERR, "socket"); + + s = tcp_bind(laddr, NULL); + if (s < 0) + err(EX_UNAVAILABLE, "tcp_bind"); uto_set(s, send_uto, recv_uto); - tcp_bind(s, local_addr, 0); - - sin.sin_family = AF_INET; - sin.sin_port = htons(remote_port); + if (s != tcp_connect(s, raddr, rport)) + err(EX_UNAVAILABLE, "tcp_connect"); - if (inet_pton(AF_INET, remote_addr, &sin.sin_addr) <= 0) - err(EX_DATAERR, "inet_pton"); - - if (connect(s, (struct sockaddr *)&sin, sizeof(sin))) - err(EX_UNAVAILABLE, "connect"); - return s; } +int +is_v6(char *addr) +{ + return strchr(addr, ':') != NULL; +} /* * Simulate broken connectivity by setting the "blackhole" flag on a route; @@ -139,7 +183,13 @@ route_down(char *addr) { static char cmd[256]; - snprintf(cmd, sizeof(cmd), "route change %s -blackhole", addr); + + if (is_v6(addr)) + snprintf(cmd, sizeof(cmd), "route change -inet6 %s -blackhole", + addr); + else + snprintf(cmd, sizeof(cmd), "route change -inet %s -blackhole", + addr); system(cmd); } @@ -150,7 +200,10 @@ route_up(char *addr) { static char cmd[256]; - snprintf(cmd, sizeof(cmd), "route change %s", addr); + if (is_v6(addr)) + snprintf(cmd, sizeof(cmd), "route change -inet6 %s", addr); + else + snprintf(cmd, sizeof(cmd), "route change %s", addr); system(cmd); } @@ -163,7 +216,7 @@ * If the connection is dead, write(2) should trigger an EPIPE. */ void -server_disconnect(char *laddr, int lport, char *downaddr, int downtime, +server_disconnect(char *laddr, char *lport, char *downaddr, int downtime, int send_uto, int recv_uto) { int listen_sock; @@ -172,7 +225,7 @@ ssize_t bytes; /* Bind and start listening. */ - listen_sock = listen_socket(laddr, lport, send_uto, recv_uto); + listen_sock = listen_uto(laddr, lport, send_uto, recv_uto); sock = accept(listen_sock, NULL, NULL); if (sock < 0) @@ -202,14 +255,14 @@ * Generic client that simply connects and tries to receive data. */ void -client_generic(char *laddr, char *raddr, int rport, int send_uto, int recv_uto) +client_generic(char *laddr, char *raddr, char *rport, int send_uto, int recv_uto) { int sock; static char buf[6000]; ssize_t bytes; /* Connect to the server, with the specified UTO values. */ - sock = connect_socket(laddr, raddr, rport, send_uto, recv_uto); + sock = connect_uto(laddr, raddr, rport, send_uto, recv_uto); bytes = recv(sock, &buf, sizeof(buf), MSG_WAITALL); if (bytes < 0 || (unsigned) bytes < sizeof(buf)) ==== //depot/projects/soc2011/cnicutar_tcputo_8/src/tools/regression/netinet/tcputo/test_utils.h#2 (text+ko) ==== @@ -5,17 +5,16 @@ #define TCP_RCVUTO_TIMEOUT 0x100 -void tcp_bind(int s, char *addr, int port); +int tcp_bind(char *addr, char *port); void uto_set(int s, int send_uto, int recv_uto); void uto_get(int s, int *send_uto, int *recv_uto); -int listen_socket(char *listen_addr, int port, int send_uto, int recv_uto); -int connect_socket(char *local_addr, char *remote_addr, int remote_port, - int send_uto, int recv_uto); +int listen_uto(char *laddr, char *port, int send_uto, int recv_uto); +int connect_uto(char *laddr, char *raddr, char *rport, int send_uto, int recv_uto); void route_down(char *addr); void route_up(char *addr); -void server_disconnect(char *laddr, int lport, char *downaddr, int downtime, +void server_disconnect(char *laddr, char *lport, char *downaddr, int downtime, int send_uto, int recv_uto); -void client_generic(char *laddr, char *raddr, int rport, +void client_generic(char *laddr, char *raddr, char *rport, int send_uto, int recv_uto); #endif
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201107241417.p6OEHqPO056697>